From 9c0c2f422e2766890657ad451ec8bf75fa88cb20 Mon Sep 17 00:00:00 2001 From: Joanne Wang Date: Thu, 3 Oct 2024 14:25:23 -0700 Subject: [PATCH] Fit and Finish UX Fixes (#1174) * add plus sign to create detector button Signed-off-by: Joanne Wang * change getting started to get started Signed-off-by: Joanne Wang * run yarn test:jest -u Signed-off-by: Joanne Wang * move tabs to top Signed-off-by: Joanne Wang * remove duplicate code Signed-off-by: Joanne Wang * change total active alerts to total active threat alerts Signed-off-by: Joanne Wang * Add period to end of correlate events content Signed-off-by: Joanne Wang * fix spacing and padding Signed-off-by: Joanne Wang * make search and filters compressed Signed-off-by: Joanne Wang * make search and filter compressed pt 2 Signed-off-by: Joanne Wang * move refresh and actions next to search bar Signed-off-by: Joanne Wang * move bulk delete to left of search bar Signed-off-by: Joanne Wang * fix spacing for detector details view Signed-off-by: Joanne Wang * change content panel from h2 to h3 Signed-off-by: Joanne Wang * remove empty hover state Signed-off-by: Joanne Wang * fix sizing for empty widget Signed-off-by: Joanne Wang * fix heading spacing Signed-off-by: Joanne Wang * change getting started to get started pt2 Signed-off-by: Joanne Wang * run yarn test:jest -u Signed-off-by: Joanne Wang * add helper function for empty prompt and change to p instead of span Signed-off-by: Joanne Wang --------- Signed-off-by: Joanne Wang --- .../components/ContentPanel/ContentPanel.tsx | 7 +- .../__snapshots__/ContentPanel.test.tsx.snap | 6 +- .../ThreatIntelAlertsTable.tsx | 8 +- .../pages/Alerts/containers/Alerts/Alerts.tsx | 149 +- .../Alerts/__snapshots__/Alerts.test.tsx.snap | 2144 ++++++++++------- .../containers/CorrelationRules.tsx | 3 +- .../containers/CorrelationsContainer.tsx | 12 +- .../containers/CreateDetector.tsx | 2 +- .../DetectorBasicDetailsView.test.tsx.snap | 12 +- .../DetectorRulesView.test.tsx.snap | 57 +- .../FieldMappingsView.test.tsx.snap | 12 +- .../UpdateDetectorRules.test.tsx.snap | 12 +- .../AlertTriggersView.test.tsx.snap | 10 +- .../containers/Detector/DetectorDetails.tsx | 4 +- .../DetectorDetails.test.tsx.snap | 82 +- .../DetectorDetailsView.tsx | 1 - .../DetectorDetailsView.test.tsx.snap | 74 +- .../containers/Detectors/Detectors.tsx | 115 +- .../__snapshots__/Detectors.test.tsx.snap | 695 ++++-- .../FindingsTable/FindingsTable.tsx | 4 + .../ThreatIntelFindingsTable.tsx | 8 +- .../Findings/containers/Findings/Findings.tsx | 126 +- public/pages/LogTypes/utils/helpers.tsx | 3 + .../components/Widgets/RecentAlertsWidget.tsx | 37 +- .../Widgets/RecentFindingsWidget.tsx | 37 +- .../RecentThreatIntelFindingsWidget.tsx | 37 +- .../Overview/components/Widgets/Summary.tsx | 11 +- .../components/Widgets/TopRulesWidget.tsx | 19 +- .../Overview/containers/Overview/Overview.tsx | 6 +- public/pages/Overview/utils/constants.ts | 8 +- .../__snapshots__/RulesTable.test.tsx.snap | 20 +- public/pages/Rules/containers/Rules/Rules.tsx | 12 +- public/pages/Rules/utils/helpers.tsx | 4 + public/plugin.ts | 8 +- public/utils/constants.ts | 4 +- public/utils/helpers.tsx | 19 + 36 files changed, 2190 insertions(+), 1578 deletions(-) diff --git a/public/components/ContentPanel/ContentPanel.tsx b/public/components/ContentPanel/ContentPanel.tsx index edb92e293..3433bf1aa 100644 --- a/public/components/ContentPanel/ContentPanel.tsx +++ b/public/components/ContentPanel/ContentPanel.tsx @@ -48,15 +48,12 @@ const ContentPanel = ({ hideHeaderBorder = false, className = '', }: ContentPanelProps): JSX.Element => ( - + {typeof title === 'string' ? ( -

{title}

+

{title}

) : ( title diff --git a/public/components/ContentPanel/__snapshots__/ContentPanel.test.tsx.snap b/public/components/ContentPanel/__snapshots__/ContentPanel.test.tsx.snap index 38b86519a..abd12b5c4 100644 --- a/public/components/ContentPanel/__snapshots__/ContentPanel.test.tsx.snap +++ b/public/components/ContentPanel/__snapshots__/ContentPanel.test.tsx.snap @@ -3,7 +3,7 @@ exports[` spec renders the component 1`] = `
spec renders the component 1`] = `
-

+

Testing -

+
= ({ }, ]; + const search = { + box: { + compressed: true, + }, + }; + return ( <> = ({ items={alerts} itemId={(item) => `${item.id}`} pagination - search + search={search} selection={itemSelection} isSelectable={true} /> diff --git a/public/pages/Alerts/containers/Alerts/Alerts.tsx b/public/pages/Alerts/containers/Alerts/Alerts.tsx index 9bcb18500..df6fb3dd5 100644 --- a/public/pages/Alerts/containers/Alerts/Alerts.tsx +++ b/public/pages/Alerts/containers/Alerts/Alerts.tsx @@ -938,12 +938,14 @@ export class Alerts extends Component { box: { placeholder: 'Search alerts', schema: true, + compressed: true, }, filters: [ { type: 'field_value_selection', field: 'severity', name: 'Alert severity', + compressed: true, options: Array.from(severities).map((severity) => ({ value: severity, name: parseAlertSeverityToOption(severity)?.label || severity, @@ -954,6 +956,7 @@ export class Alerts extends Component { type: 'field_value_selection', field: 'state', name: 'Status', + compressed: true, options: Array.from(statuses).map((status) => ({ value: status, name: capitalizeFirstLetter(status) || status, @@ -967,12 +970,14 @@ export class Alerts extends Component { box: { placeholder: 'Search alerts', schema: true, + compressed: true, }, filters: [ { type: 'field_value_selection', field: 'severity', name: 'Alert severity', + compressed: true, options: Array.from(corrSeverities).map((severity) => ({ value: severity, name: parseAlertSeverityToOption(severity)?.label || severity, @@ -983,6 +988,7 @@ export class Alerts extends Component { type: 'field_value_selection', field: 'state', name: 'Status', + compressed: true, options: Array.from(corrStatuses).map((status) => ({ value: status, name: capitalizeFirstLetter(status) || status, @@ -1018,18 +1024,22 @@ export class Alerts extends Component { content: ( <> - `${item.id}`} - isSelectable={true} - pagination - search={search} - sorting={sorting} - selection={selection} - loading={loading} - message={widgetEmptyMessage} - /> + {this.getAlertsGraph(alerts, loading)} + + + `${item.id}`} + isSelectable={true} + pagination + search={search} + sorting={sorting} + selection={selection} + loading={loading} + message={widgetEmptyMessage} + /> + ), }, @@ -1039,11 +1049,15 @@ export class Alerts extends Component { content: ( <> - + {this.getAlertsGraph(alerts, loading)} + + + + ), }, @@ -1060,18 +1074,22 @@ export class Alerts extends Component { content: ( <> - `${item.id}`} - isSelectable={true} - pagination - search={correlationSearch} - sorting={sorting} - selection={correlationSelection} - loading={loading} - message={widgetEmptyCorrelationMessage} - /> + {this.getAlertsGraph(alerts, loading)} + + + `${item.id}`} + isSelectable={true} + pagination + search={correlationSearch} + sorting={sorting} + selection={correlationSelection} + loading={loading} + message={widgetEmptyCorrelationMessage} + /> + ), }, @@ -1109,7 +1127,7 @@ export class Alerts extends Component { onAcknowledge={this.onAcknowledgeCorrelationAlert} /> )} - + { {datePicker} - - - - - {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. - -

- } - /> - ) : ( - - )} -
-
-
- + this.setState({ selectedTabId: id as AlertTabId })} + initialSelectedTab={tabs.find(({ id }) => id === selectedTabId) ?? tabs[0]} + />
+
+ + ); + } + + private getAlertsGraph(alerts: any[], loading: boolean) { + return ( + + + {this.createGroupByControl()} - - this.setState({ selectedTabId: id as AlertTabId })} - initialSelectedTab={tabs.find(({ id }) => id === selectedTabId) ?? tabs[0]} + {!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. + +

+ } /> -
+ ) : ( + + )}
- +
); } } 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 0f21fe9cb..2899073d5 100644 --- a/public/pages/Alerts/containers/Alerts/__snapshots__/Alerts.test.tsx.snap +++ b/public/pages/Alerts/containers/Alerts/__snapshots__/Alerts.test.tsx.snap @@ -209,9 +209,10 @@ exports[` spec renders the component 1`] = ` >
spec renders the component 1`] = `
- -
-
@@ -832,43 +826,235 @@ 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 +

+
+ } + /> +
+
+
+ + + Acknowledge + , + ] } + title="Alerts" > -
+ selection={ + Object { + "onSelectionChange": [Function], + "selectable": [Function], + "selectableMessage": [Function], + } + } + sorting={ + Object { + "sort": Object { + "direction": "dsc", + "field": "start_time", + }, + } + } + tableLayout="fixed" + /> + + , + "id": "detection-rules", + "name": "Detection rules", + } + } + onTabClick={[Function]} + size="s" + tabs={ + Array [ + Object { + "content": + + -
- -
spec renders the component 1`] = ` } prepend="Group by" value="status" - > - + + + + + + - -
- - - -
- - - - -
- - - - - -
-
-
-
-
-
-
-
-
-
+ detectors + + to generate alerts. + +

+ } + title={ + +

+ No alerts +

+
+ } + /> +
-
-
- -
+ + + Acknowledge + , + ] + } + title="Alerts" > - - - Adjust the time range to see more results or create alert triggers in your - - - detectors - - to generate alerts. - -

+ -

- No alerts -

- + isSelectable={true} + itemId={[Function]} + items={Array []} + loading={true} + pagination={true} + responsive={true} + search={ + Object { + "box": Object { + "compressed": true, + "placeholder": "Search alerts", + "schema": true, + }, + "filters": Array [ + Object { + "compressed": true, + "field": "severity", + "multiSelect": "or", + "name": "Alert severity", + "options": Array [], + "type": "field_value_selection", + }, + Object { + "compressed": true, + "field": "state", + "multiSelect": "or", + "name": "Status", + "options": Array [], + "type": "field_value_selection", + }, + ], + } + } + selection={ + Object { + "onSelectionChange": [Function], + "selectable": [Function], + "selectableMessage": [Function], + } + } + sorting={ + Object { + "sort": Object { + "direction": "dsc", + "field": "start_time", + }, + } } + tableLayout="fixed" + /> +
+ , + "id": "detection-rules", + "name": "Detection rules", + }, + Object { + "content": + + + -
- - -
+ + + + + + + Adjust the time range to see more results or create alert triggers in your + + + detectors + + to generate alerts. + +

+ } + title={ +

No alerts

-
-
-
- + } + /> + + + + + + Acknowledge + , + ] + } + title="Alerts" + > + + + , + "id": "threat-intel", + "name": "Threat intel", + }, + Object { + "content": + + + + + - - -
- - -
-

- -

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

-
-
- - -
- -
- -
- -
- - -
- -
- - -
- - Acknowledge - , - ] - } - title="Alerts" - > - -
- -
- -
- -
-

- Alerts -

-
-
-
-
- -
- -
- -
- + + + + + + - - - - - - -
-
-
-
-
-
-
-
- -
-
-
- - + to generate alerts. + +

+ } + title={ + +

+ No alerts +

+
+ } /> - + + + + + Acknowledge + , + ] + } + title="Alerts" + > + - , - "id": "detection-rules", - "name": "Detection rules", - } - } - onTabClick={[Function]} - size="s" - tabs={ - Array [ - Object { - "content": - - - , - "id": "detection-rules", - "name": "Detection rules", - }, - Object { - "content": - - - , - "id": "threat-intel", - "name": "Threat intel", - }, + "compressed": true, + "field": "state", + "multiSelect": "or", + "name": "Status", + "options": Array [], + "type": "field_value_selection", + }, + ], + } + } + selection={ + Object { + "onSelectionChange": [Function], + "selectable": [Function], + "selectableMessage": [Function], + } + } + sorting={ + Object { + "sort": Object { + "direction": "dsc", + "field": "start_time", + }, + } + } + tableLayout="fixed" + /> + + , + "id": "correlations", + "name": +
- - - , - "id": "correlations", - "name": + + Correlations + + +
+
, + }, + ] + } + > +
+ +
+ + + + + + + + + +
+
+
+ +
+ + +
-
- +
-
- - - - +
+ + + +
+ + + +
+ + + + +
+ + + + + +
+
+
+
+
+
+
+
+ +
+ +
+ + +
- - - + +
+

+ No alerts +

+
+
+ + + + +
+ + +
+

+ +

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

+
+
+ + +
+ +
+
+
+ +
+
+ +
+ + + Acknowledge + , + ] + } + title="Alerts" + > + +
+ +
+ +
+ +
+

+ Alerts +

+
+
+
+
+ - + + +
- - - - - + +
+ +
+
- + + +
+
- -
- spec renders the component 1`] = ` search={ Object { "box": Object { + "compressed": true, "placeholder": "Search alerts", "schema": true, }, "filters": Array [ Object { + "compressed": true, "field": "severity", "multiSelect": "or", "name": "Alert severity", @@ -1870,6 +2219,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "state", "multiSelect": "or", "name": "Status", @@ -1900,6 +2250,7 @@ exports[` spec renders the component 1`] = ` spec renders the component 1`] = ` filters={ Array [ Object { + "compressed": true, "field": "severity", "multiSelect": "or", "name": "Alert severity", @@ -1933,6 +2285,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "state", "multiSelect": "or", "name": "Status", @@ -1959,6 +2312,7 @@ exports[` spec renders the component 1`] = ` className="euiFlexItem euiSearchBar__searchHolder" > spec renders the component 1`] = ` > spec renders the component 1`] = ` placeholder="Search alerts" >
spec renders the component 1`] = ` > spec renders the component 1`] = ` /> @@ -2011,7 +2365,7 @@ exports[` spec renders the component 1`] = ` className="euiFormControlLayoutIcons" > spec renders the component 1`] = `
- -
+ +
- - +
+
diff --git a/public/pages/Correlations/containers/CorrelationRules.tsx b/public/pages/Correlations/containers/CorrelationRules.tsx index b50e435bf..63e9c28d9 100644 --- a/public/pages/Correlations/containers/CorrelationRules.tsx +++ b/public/pages/Correlations/containers/CorrelationRules.tsx @@ -109,7 +109,7 @@ export const CorrelationRules: React.FC = (props: Correla return ( <> {isDeleteModalVisible && deleteModal ? deleteModal : null} - + @@ -120,7 +120,6 @@ export const CorrelationRules: React.FC = (props: Correla {createRuleAction} - diff --git a/public/pages/Correlations/containers/CorrelationsContainer.tsx b/public/pages/Correlations/containers/CorrelationsContainer.tsx index a5ff8eb4a..87e691c34 100644 --- a/public/pages/Correlations/containers/CorrelationsContainer.tsx +++ b/public/pages/Correlations/containers/CorrelationsContainer.tsx @@ -454,7 +454,11 @@ export class Correlations extends React.ComponentNo correlations found } - body={

There are no correlated findings in the system.

} + body={ + +

There are no correlated findings in the system.

+
+ } actions={[ Create correlation rule @@ -548,7 +552,7 @@ export class Correlations extends React.Component ) : null} - +
- Reset filters + + Reset filters +
diff --git a/public/pages/CreateDetector/containers/CreateDetector.tsx b/public/pages/CreateDetector/containers/CreateDetector.tsx index c029da6af..ffc7d344a 100644 --- a/public/pages/CreateDetector/containers/CreateDetector.tsx +++ b/public/pages/CreateDetector/containers/CreateDetector.tsx @@ -386,7 +386,7 @@ export default class CreateDetector extends Component

Create detector

- + {this.getStepContent()} diff --git a/public/pages/Detectors/components/DetectorBasicDetailsView/__snapshots__/DetectorBasicDetailsView.test.tsx.snap b/public/pages/Detectors/components/DetectorBasicDetailsView/__snapshots__/DetectorBasicDetailsView.test.tsx.snap index 5c7e3e9ec..dfe1ee3b8 100644 --- a/public/pages/Detectors/components/DetectorBasicDetailsView/__snapshots__/DetectorBasicDetailsView.test.tsx.snap +++ b/public/pages/Detectors/components/DetectorBasicDetailsView/__snapshots__/DetectorBasicDetailsView.test.tsx.snap @@ -7,7 +7,7 @@ Object {
-

+

Detector details -

+
-

+

Detector details -

+
spec renders the component 1`] = ` className="" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -224,8 +223,7 @@ exports[` spec renders the component 1`] = ` className="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--plain euiPanel--hasShadow" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -256,9 +254,9 @@ exports[` spec renders the component 1`] = `
-

+

Active rules (2) -

+
@@ -424,11 +422,13 @@ exports[` spec renders the component 1`] = ` search={ Object { "box": Object { + "compressed": true, "placeholder": "Search rules", "schema": true, }, "filters": Array [ Object { + "compressed": true, "field": "category", "multiSelect": "or", "name": "Log type", @@ -436,6 +436,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "level", "multiSelect": "or", "name": "Rule severity", @@ -489,6 +490,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "source", "multiSelect": "or", "name": "Source", @@ -512,6 +514,7 @@ exports[` spec renders the component 1`] = ` spec renders the component 1`] = ` filters={ Array [ Object { + "compressed": true, "field": "category", "multiSelect": "or", "name": "Log type", @@ -545,6 +549,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "level", "multiSelect": "or", "name": "Rule severity", @@ -598,6 +603,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "source", "multiSelect": "or", "name": "Source", @@ -631,6 +637,7 @@ exports[` spec renders the component 1`] = ` className="euiFlexItem euiSearchBar__searchHolder" > spec renders the component 1`] = ` > spec renders the component 1`] = ` placeholder="Search rules" >
spec renders the component 1`] = ` > spec renders the component 1`] = ` /> @@ -683,7 +690,7 @@ exports[` spec renders the component 1`] = ` className="euiFormControlLayoutIcons" > spec renders the component 1`] = `
diff --git a/public/pages/Detectors/containers/Detector/DetectorDetails.tsx b/public/pages/Detectors/containers/Detector/DetectorDetails.tsx index c079f427d..307a025b4 100644 --- a/public/pages/Detectors/containers/Detector/DetectorDetails.tsx +++ b/public/pages/Detectors/containers/Detector/DetectorDetails.tsx @@ -514,10 +514,10 @@ export class DetectorDetails extends React.Component - + {this.renderTabs()} - + {selectedTabContent} ); diff --git a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap index 868286b83..64ec5f51a 100644 --- a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap +++ b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap @@ -545,10 +545,10 @@ exports[` spec renders the component 1`] = `
@@ -622,10 +622,10 @@ exports[` spec renders the component 1`] = `
spec renders the component 1`] = ` className="" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -1505,8 +1504,7 @@ exports[` spec renders the component 1`] = ` className="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--plain euiPanel--hasShadow" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -1537,9 +1535,9 @@ exports[` spec renders the component 1`] = `
-

+

Detector details -

+
@@ -2330,13 +2328,6 @@ exports[` spec renders the component 1`] = ` className="euiSpacer euiSpacer--m" />
- -
- spec renders the component 1`] = ` className="" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -2789,8 +2779,7 @@ exports[` spec renders the component 1`] = ` className="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--plain euiPanel--hasShadow" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -2821,9 +2810,9 @@ exports[` spec renders the component 1`] = `
-

+

Active rules (2) -

+
@@ -2989,11 +2978,13 @@ exports[` spec renders the component 1`] = ` search={ Object { "box": Object { + "compressed": true, "placeholder": "Search rules", "schema": true, }, "filters": Array [ Object { + "compressed": true, "field": "category", "multiSelect": "or", "name": "Log type", @@ -3001,6 +2992,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "level", "multiSelect": "or", "name": "Rule severity", @@ -3054,6 +3046,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "source", "multiSelect": "or", "name": "Source", @@ -3077,6 +3070,7 @@ exports[` spec renders the component 1`] = ` spec renders the component 1`] = ` filters={ Array [ Object { + "compressed": true, "field": "category", "multiSelect": "or", "name": "Log type", @@ -3110,6 +3105,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "level", "multiSelect": "or", "name": "Rule severity", @@ -3163,6 +3159,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "source", "multiSelect": "or", "name": "Source", @@ -3196,6 +3193,7 @@ exports[` spec renders the component 1`] = ` className="euiFlexItem euiSearchBar__searchHolder" > spec renders the component 1`] = ` > spec renders the component 1`] = ` placeholder="Search rules" >
spec renders the component 1`] = ` > spec renders the component 1`] = ` /> @@ -3248,7 +3246,7 @@ exports[` spec renders the component 1`] = ` className="euiFormControlLayoutIcons" > spec renders the component 1`] = `
@@ -1252,13 +1250,6 @@ exports[` spec renders the component 1`] = ` className="euiSpacer euiSpacer--m" /> - -
- spec renders the component 1`] = ` className="" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -1486,8 +1476,7 @@ exports[` spec renders the component 1`] = ` className="euiPanel euiPanel--paddingMedium euiPanel--borderRadiusMedium euiPanel--plain euiPanel--hasShadow" style={ Object { - "paddingLeft": "0px", - "paddingRight": "0px", + "padding": "16px", } } > @@ -1518,9 +1507,9 @@ exports[` spec renders the component 1`] = `
-

+

Active rules (2) -

+
@@ -1686,11 +1675,13 @@ exports[` spec renders the component 1`] = ` search={ Object { "box": Object { + "compressed": true, "placeholder": "Search rules", "schema": true, }, "filters": Array [ Object { + "compressed": true, "field": "category", "multiSelect": "or", "name": "Log type", @@ -1698,6 +1689,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "level", "multiSelect": "or", "name": "Rule severity", @@ -1751,6 +1743,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "source", "multiSelect": "or", "name": "Source", @@ -1774,6 +1767,7 @@ exports[` spec renders the component 1`] = ` spec renders the component 1`] = ` filters={ Array [ Object { + "compressed": true, "field": "category", "multiSelect": "or", "name": "Log type", @@ -1807,6 +1802,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "level", "multiSelect": "or", "name": "Rule severity", @@ -1860,6 +1856,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "source", "multiSelect": "or", "name": "Source", @@ -1893,6 +1890,7 @@ exports[` spec renders the component 1`] = ` className="euiFlexItem euiSearchBar__searchHolder" > spec renders the component 1`] = ` > spec renders the component 1`] = ` placeholder="Search rules" >
spec renders the component 1`] = ` > spec renders the component 1`] = ` /> @@ -1945,7 +1943,7 @@ exports[` spec renders the component 1`] = ` className="euiFormControlLayoutIcons" > spec renders the component 1`] = `
- - -
- - Actions - - } - closePopover={[Function]} - data-test-subj="detectorsActionsPopover" - display="inlineBlock" - hasArrow={true} - id="detectorsActionsPopover" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - - - - - -
-
-
-
-
-
spec renders the component 1`] = ` data-test-subj="detectorsCreateButton" fill={true} href="#/create-detector" + iconGap="s" + iconSide="left" + iconType="plus" > spec renders the component 1`] = ` element="a" fill={true} href="#/create-detector" + iconGap="s" + iconSide="left" + iconType="plus" isDisabled={false} rel="noreferrer" size="s" @@ -375,8 +142,9 @@ exports[` spec renders the component 1`] = ` > spec renders the component 1`] = ` } > + + EuiIconMock + @@ -405,13 +181,6 @@ exports[` spec renders the component 1`] = `
- -
-
@@ -689,12 +458,14 @@ exports[` spec renders the component 1`] = ` search={ Object { "box": Object { + "compressed": true, "incremental": true, "placeholder": "Search threat detectors", "schema": true, }, "filters": Array [ Object { + "compressed": true, "field": "status", "multiSelect": "or", "name": "Status", @@ -707,6 +478,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "logType", "multiSelect": "or", "name": "Log type", @@ -714,6 +486,55 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, ], + "toolsLeft": Array [ + + Delete detectors + , + ], + "toolsRight": Array [ + + Refresh + , + + Actions + + } + closePopover={[Function]} + data-test-subj="detectorsActionsPopover" + display="inlineBlock" + hasArrow={true} + id="detectorsActionsPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + + , + ], } } selection={ @@ -735,6 +556,7 @@ exports[` spec renders the component 1`] = ` spec renders the component 1`] = ` filters={ Array [ Object { + "compressed": true, "field": "status", "multiSelect": "or", "name": "Status", @@ -774,6 +597,7 @@ exports[` spec renders the component 1`] = ` "type": "field_value_selection", }, Object { + "compressed": true, "field": "logType", "multiSelect": "or", "name": "Log type", @@ -783,6 +607,59 @@ exports[` spec renders the component 1`] = ` ] } onChange={[Function]} + toolsLeft={ + Array [ + + Delete detectors + , + ] + } + toolsRight={ + Array [ + + Refresh + , + + Actions + + } + closePopover={[Function]} + data-test-subj="detectorsActionsPopover" + display="inlineBlock" + hasArrow={true} + id="detectorsActionsPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + + , + ] + } > spec renders the component 1`] = `
+ +
+ + + + + + + +
+
spec renders the component 1`] = ` className="euiFlexItem euiSearchBar__searchHolder" > spec renders the component 1`] = ` > spec renders the component 1`] = ` placeholder="Search threat detectors" >
spec renders the component 1`] = ` > spec renders the component 1`] = ` /> @@ -852,7 +812,7 @@ exports[` spec renders the component 1`] = ` className="euiFormControlLayoutIcons" > spec renders the component 1`] = `
+ +
+ + + + + + + +
+
+ +
+ + Actions + + } + closePopover={[Function]} + data-test-subj="detectorsActionsPopover" + display="inlineBlock" + hasArrow={true} + id="detectorsActionsPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + + + + + +
+
+
+
+
diff --git a/public/pages/Findings/components/FindingsTable/FindingsTable.tsx b/public/pages/Findings/components/FindingsTable/FindingsTable.tsx index 1a66a1c2d..005e32663 100644 --- a/public/pages/Findings/components/FindingsTable/FindingsTable.tsx +++ b/public/pages/Findings/components/FindingsTable/FindingsTable.tsx @@ -271,12 +271,14 @@ export default class FindingsTable extends Component { const name = parseAlertSeverityToOption(severity)?.label || capitalizeFirstLetter(severity); @@ -288,6 +290,7 @@ export default class FindingsTable extends Component ({ value: type, name: formatRuleType(type), @@ -298,6 +301,7 @@ export default class FindingsTable extends Component = }, ]; - return ; + const search = { + box: { + compressed: true, + }, + }; + + return ; }; diff --git a/public/pages/Findings/containers/Findings/Findings.tsx b/public/pages/Findings/containers/Findings/Findings.tsx index c25d5c424..aeebd7d3e 100644 --- a/public/pages/Findings/containers/Findings/Findings.tsx +++ b/public/pages/Findings/containers/Findings/Findings.tsx @@ -564,22 +564,26 @@ class Findings extends Component { ), content: ( <> - - + + {this.getFindingsGraph(findings, loading)} + + + + ), }, @@ -595,10 +599,14 @@ class Findings extends Component { ), content: ( <> - - + + {this.getFindingsGraph(findings, loading)} + + + + ), }, @@ -617,7 +625,7 @@ class Findings extends Component { ); return ( - + {
{datePicker} - - - - - - {this.createGroupByControl()} - - - {!findings || findings.length === 0 ? ( - -

No findings

- - } - body={ - - {this.state.findingStateByTabId[this.state.selectedTabId].emptyPromptBody} - - } - /> - ) : ( - - )} -
-
-
- - -
- - id === selectedTabId) ?? tabs[0]} - onTabClick={(tab) => { - this.setState({ selectedTabId: tab.id as FindingTabId }); - }} - /> - + id === selectedTabId) ?? tabs[0]} + onTabClick={(tab) => { + this.setState({ selectedTabId: tab.id as FindingTabId }); + }} + /> ); } + + private getFindingsGraph(findings: ThreatIntelFinding[] | FindingItemType[], loading: boolean) { + return ( + + + {this.createGroupByControl()} + + {!findings || findings.length === 0 ? ( + +

No findings

+ + } + body={ + + {this.state.findingStateByTabId[this.state.selectedTabId].emptyPromptBody} + + } + /> + ) : ( + + )} +
+
+
+ ); + } } export default withRouter(Findings); diff --git a/public/pages/LogTypes/utils/helpers.tsx b/public/pages/LogTypes/utils/helpers.tsx index 85f1e084d..6545eda1e 100644 --- a/public/pages/LogTypes/utils/helpers.tsx +++ b/public/pages/LogTypes/utils/helpers.tsx @@ -65,12 +65,14 @@ export const getLogTypesTableSearchConfig = (): Search => { box: { placeholder: 'Search log types', schema: true, + compressed: true, }, filters: [ { type: 'field_value_selection', field: 'category', name: 'Category', + compressed: true, multiSelect: 'or', options: logTypeCategories.map((category) => ({ value: category, @@ -80,6 +82,7 @@ export const getLogTypesTableSearchConfig = (): Search => { type: 'field_value_selection', field: 'source', name: 'Source', + compressed: true, multiSelect: 'or', options: ruleSource.map((source: string) => ({ value: source, diff --git a/public/pages/Overview/components/Widgets/RecentAlertsWidget.tsx b/public/pages/Overview/components/Widgets/RecentAlertsWidget.tsx index d961ce94f..6ea5e8646 100644 --- a/public/pages/Overview/components/Widgets/RecentAlertsWidget.tsx +++ b/public/pages/Overview/components/Widgets/RecentAlertsWidget.tsx @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiBasicTableColumn, EuiSmallButton, EuiEmptyPrompt, EuiText } from '@elastic/eui'; +import { EuiBasicTableColumn, EuiSmallButton } from '@elastic/eui'; import { ROUTES, SortDirection } from '../../../../utils/constants'; import React, { useEffect, useState } from 'react'; import { TableWidget } from './TableWidget'; import { WidgetContainer } from './WidgetContainer'; -import { getAlertSeverityBadge, renderTime } from '../../../../utils/helpers'; +import { getAlertSeverityBadge, getEuiEmptyPrompt, renderTime } from '../../../../utils/helpers'; import { OverviewAlertItem } from '../../../../../types'; const columns: EuiBasicTableColumn[] = [ @@ -44,9 +44,6 @@ export const RecentAlertsWidget: React.FC = ({ loading = false, }) => { const [alertItems, setAlertItems] = useState([]); - const [widgetEmptyMessage, setwidgetEmptyMessage] = useState( - undefined - ); useEffect(() => { items.sort((a, b) => { @@ -55,18 +52,6 @@ export const RecentAlertsWidget: React.FC = ({ return timeB - timeA; }); setAlertItems(items.slice(0, 20)); - setwidgetEmptyMessage( - items.length > 0 ? undefined : ( - - No recent alerts.Adjust the time range to - see more results. - - } - /> - ) - ); }, [items]); const actions = React.useMemo( @@ -76,14 +61,16 @@ export const RecentAlertsWidget: React.FC = ({ return ( - + {alertItems.length === 0 ? ( + getEuiEmptyPrompt('No recent alerts.') + ) : ( + + )} ); }; diff --git a/public/pages/Overview/components/Widgets/RecentFindingsWidget.tsx b/public/pages/Overview/components/Widgets/RecentFindingsWidget.tsx index a0dcf8fca..96edb94b0 100644 --- a/public/pages/Overview/components/Widgets/RecentFindingsWidget.tsx +++ b/public/pages/Overview/components/Widgets/RecentFindingsWidget.tsx @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiBasicTableColumn, EuiSmallButton, EuiEmptyPrompt, EuiText } from '@elastic/eui'; +import { EuiBasicTableColumn, EuiSmallButton } from '@elastic/eui'; import { FINDINGS_NAV_ID, ROUTES, SortDirection } from '../../../../utils/constants'; import React, { useEffect, useState } from 'react'; import { TableWidget } from './TableWidget'; import { WidgetContainer } from './WidgetContainer'; -import { renderTime, getSeverityBadge } from '../../../../utils/helpers'; +import { renderTime, getSeverityBadge, getEuiEmptyPrompt } from '../../../../utils/helpers'; import { OverviewFindingItem } from '../../../../../types'; import { getApplication, getUseUpdatedUx } from '../../../../services/utils/constants'; @@ -53,27 +53,12 @@ export const RecentFindingsWidget: React.FC = ({ loading = false, }) => { const [findingItems, setFindingItems] = useState([]); - const [widgetEmptyMessage, setWidgetEmptyMessage] = useState( - undefined - ); useEffect(() => { items.sort((a, b) => { return b.time - a.time; }); setFindingItems(items.slice(0, 20)); - setWidgetEmptyMessage( - items.length > 0 ? undefined : ( - - No recent findings.Adjust the time range to - see more results. - - } - /> - ) - ); }, [items]); const actions = React.useMemo(() => { @@ -83,14 +68,16 @@ export const RecentFindingsWidget: React.FC = ({ return ( - + {findingItems.length === 0 ? ( + getEuiEmptyPrompt('No recent findings.') + ) : ( + + )} ); }; diff --git a/public/pages/Overview/components/Widgets/RecentThreatIntelFindingsWidget.tsx b/public/pages/Overview/components/Widgets/RecentThreatIntelFindingsWidget.tsx index f11dff12a..a6e100e3d 100644 --- a/public/pages/Overview/components/Widgets/RecentThreatIntelFindingsWidget.tsx +++ b/public/pages/Overview/components/Widgets/RecentThreatIntelFindingsWidget.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiBasicTableColumn, EuiSmallButton, EuiEmptyPrompt, EuiText } from '@elastic/eui'; +import { EuiBasicTableColumn, EuiSmallButton } from '@elastic/eui'; import { DEFAULT_EMPTY_DATA, FINDINGS_NAV_ID, @@ -14,7 +14,7 @@ import { import React, { useEffect, useState } from 'react'; import { TableWidget } from './TableWidget'; import { WidgetContainer } from './WidgetContainer'; -import { renderTime } from '../../../../utils/helpers'; +import { getEuiEmptyPrompt, renderTime } from '../../../../utils/helpers'; import { ThreatIntelFinding } from '../../../../../types'; import { getApplication, getUseUpdatedUx } from '../../../../services/utils/constants'; import { IocLabel, ThreatIntelIocType } from '../../../../../common/constants'; @@ -55,27 +55,12 @@ export const RecentThreatIntelFindingsWidget: React.FC { const [findingItems, setFindingItems] = useState([]); - const [widgetEmptyMessage, setWidgetEmptyMessage] = useState( - undefined - ); useEffect(() => { items.sort((a, b) => { return b.timestamp - a.timestamp; }); setFindingItems(items.slice(0, 20)); - setWidgetEmptyMessage( - items.length > 0 ? undefined : ( - - No recent findings.Adjust the time range to - see more results. - - } - /> - ) - ); }, [items]); const actions = React.useMemo(() => { @@ -91,14 +76,16 @@ export const RecentThreatIntelFindingsWidget: React.FC - + {findingItems.length === 0 ? ( + getEuiEmptyPrompt('No recent findings.') + ) : ( + + )} ); }; diff --git a/public/pages/Overview/components/Widgets/Summary.tsx b/public/pages/Overview/components/Widgets/Summary.tsx index 0270e47c3..910aa555b 100644 --- a/public/pages/Overview/components/Widgets/Summary.tsx +++ b/public/pages/Overview/components/Widgets/Summary.tsx @@ -170,12 +170,16 @@ export const Summary: React.FC = ({ {activeAlerts === 0 && totalFindings === 0 ? (

No alerts and findings found

} + title={ + +

No alerts and findings found

+
+ } body={ <>

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

@@ -183,6 +187,9 @@ export const Summary: React.FC = ({ href={`#${ROUTES.DETECTORS_CREATE}`} fill={true} data-test-subj={'detectorsCreateButton'} + iconType="plus" + iconSide="left" + iconGap="s" > Create a detector diff --git a/public/pages/Overview/components/Widgets/TopRulesWidget.tsx b/public/pages/Overview/components/Widgets/TopRulesWidget.tsx index 29bb45a1d..b6ef0a512 100644 --- a/public/pages/Overview/components/Widgets/TopRulesWidget.tsx +++ b/public/pages/Overview/components/Widgets/TopRulesWidget.tsx @@ -3,12 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { renderVisualization } from '../../../../utils/helpers'; +import { getEuiEmptyPrompt, renderVisualization } from '../../../../utils/helpers'; import React, { useEffect } from 'react'; import { WidgetContainer } from './WidgetContainer'; import { getTopRulesVisualizationSpec } from '../../utils/helpers'; import { ChartContainer } from '../../../../components/Charts/ChartContainer'; -import { EuiEmptyPrompt, EuiText } from '@elastic/eui'; import { OverviewFindingItem } from '../../../../../types'; export interface TopRulesWidgetProps { @@ -37,21 +36,9 @@ export const TopRulesWidget: React.FC = ({ findings, loadin return ( {findings.length === 0 ? ( - -

- - No findings with detection rules.Adjust - the time range to see more results. - -

-
- } - /> + getEuiEmptyPrompt('No findings with detection rules.') ) : ( - + )} ); diff --git a/public/pages/Overview/containers/Overview/Overview.tsx b/public/pages/Overview/containers/Overview/Overview.tsx index 9c99c28bc..5735dd3a8 100644 --- a/public/pages/Overview/containers/Overview/Overview.tsx +++ b/public/pages/Overview/containers/Overview/Overview.tsx @@ -216,6 +216,9 @@ export const Overview: React.FC = (props) => { href={`#${ROUTES.DETECTORS_CREATE}`} fill={true} data-test-subj={'detectorsCreateButton'} + iconType="plus" + iconSide="left" + iconGap="s" > Create detector @@ -240,7 +243,7 @@ export const Overview: React.FC = (props) => { }; return ( - + = (props) => { {datePicker} {createDetectorAction} - {getUseUpdatedUx() && ( diff --git a/public/pages/Overview/utils/constants.ts b/public/pages/Overview/utils/constants.ts index f3e51317e..8a6087967 100644 --- a/public/pages/Overview/utils/constants.ts +++ b/public/pages/Overview/utils/constants.ts @@ -7,7 +7,7 @@ import { EuiCardProps, EuiStatProps } from '@elastic/eui'; import { CORRELATIONS_RULE_NAV_ID, DETECTORS_NAV_ID, - GETTING_STARTED_NAV_ID, + GET_STARTED_NAV_ID, THREAT_ALERTS_NAV_ID, THREAT_INTEL_NAV_ID, } from '../../../utils/constants'; @@ -26,7 +26,7 @@ export const getOverviewsCardsProps = (): EuiCardProps[] => [ description: 'Set up tools and components to get started.', selectable: { onClick: () => { - getApplication().navigateToApp(GETTING_STARTED_NAV_ID); + getApplication().navigateToApp(GET_STARTED_NAV_ID); }, children: 'Getting started guide', isDisabled: false, @@ -67,7 +67,7 @@ export const getOverviewsCardsProps = (): EuiCardProps[] => [ }, { title: 'Correlate events', - description: 'Detect multi-system threats with correlation rule builder', + description: 'Detect multi-system threats with correlation rule builder.', selectable: { onClick: () => { getApplication().navigateToApp(CORRELATIONS_RULE_NAV_ID); @@ -98,7 +98,7 @@ export const getOverviewStatsProps = ({ return [ { title: alerts, - description: 'Total active alerts', + description: 'Total active threat alerts', }, { title: correlations, diff --git a/public/pages/Rules/components/RulesTable/__snapshots__/RulesTable.test.tsx.snap b/public/pages/Rules/components/RulesTable/__snapshots__/RulesTable.test.tsx.snap index 09d948c0f..b32277ed8 100644 --- a/public/pages/Rules/components/RulesTable/__snapshots__/RulesTable.test.tsx.snap +++ b/public/pages/Rules/components/RulesTable/__snapshots__/RulesTable.test.tsx.snap @@ -13,14 +13,14 @@ Object { class="euiFlexItem euiSearchBar__searchHolder" >
+ } + /> + ); +} + export function initializeServices(coreStart: CoreStart, indexPattern: CoreIndexPatternsService) { const { http, savedObjects } = coreStart;