Skip to content

Commit

Permalink
[SIEM] Overview page feedback (#56261) (#56276)
Browse files Browse the repository at this point in the history
## [SIEM] Overview page feedback

Implements feedback and fixes to the Overview page

### Overview (default theme)

![01-overview-default-theme](https://user-images.githubusercontent.com/4459398/73315509-899c5500-41ed-11ea-9949-82853dd4ba59.png)

### Overview (dark theme)

![02-overview-dark-theme](https://user-images.githubusercontent.com/4459398/73315527-902acc80-41ed-11ea-9701-6a2c5fa40cce.png)

## Highlights

* The new order of widgets is Signals, Alerts, Events, Host Events, Network events, per elastic/siem-team#494

* Changed the default `External alerts count` `Stack by` to `event.module` elastic/siem-team#491

*  Added `event.module` to the `Events count` histogram elastic/siem-team#491

* Widget titles will no longer include the currently selected `Stack by option`. The widgets will use the same static title text that appears on the other pages (i.e.. `Signals count`, `External alerts count`, and `Events count`) elastic/siem-team#491

* The `Signals count` includes a `Stack by` that defaults to `signal.rule.threat.tatic.name`

* Standardized on a 300px widget height for all histograms in the app (thanks @MichaelMarcialis for paring on this!)

* The `Open as duplicate timeline` action is `Recent timelines` is now only shown when hovering over a recent timeline

## Loading States

* The `Recent timelines` and `Security news` widgets now use the horizontal bar loading indicator

* The `Host events` and `Network events` widgets now use the horizontal bar loading indicator

* The `Host events` and `Network events` Showing _n_ events subtitles are now hidden on initial load

* The counts in the `Host events` and `Network events` Showing _n_ events subtitles are now hidden on initial load

* We no longer hide some histogram subtitles after initial load, to prevent shifting of content when a user makes a `Stack by` selection

## News Feed Error State

![news-feed-error-state](https://user-images.githubusercontent.com/4459398/73316060-1e538280-41ef-11ea-83f5-b8d6e9fa3741.png)

* Fixed an issue where the `Security news` header was hidden when an invalid URL is configured

* Added a space between the word `via` and the `SIEM advanced settings` link

* Removed the capital “N” from "News" in the error message

## Misc Visual Changes

* Fixed text truncation of the `Severity` column in the `Detections` page's `Signals` table

* Added the “showing” subtitle to the `Signals count` histogram on the Detections page

* Increased the `Stack by` histogram selector and the `View signals | alerts | events' buttons from 8 to 24px

* Tweaked the border rendering in the Overview `Host Events` and `Network events` widget headers

* Added 8px of spacing between the Overview `Host Events` and `Network events` widget accordion headers and their contents

* Fixed an issue where the `Host events` and `Networ events` widgets didn't render in ie11 elastic/siem-team#499

## Non-Visual Fixes

* Removed an incorrect usage of `usememo`

* Removed the placeholder client-side username query from `x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx`

* Updated the query of the Overview `Host events` widget to filter by "host.name exists"

* Updated the query of the Overview `Network events` widget to filter by "source.ip exists or destination.ip : exists"
  • Loading branch information
andrew-goldstein authored Jan 29, 2020
1 parent beff7c7 commit b546bf8
Show file tree
Hide file tree
Showing 40 changed files with 1,858 additions and 1,388 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import React, { useState, useEffect, useCallback } from 'react';
import { ScaleType } from '@elastic/charts';
import styled from 'styled-components';

import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSelect, EuiSpacer } from '@elastic/eui';
import { noop } from 'lodash/fp';
Expand All @@ -25,8 +26,21 @@ import {
import { ChartSeriesData } from '../charts/common';
import { InspectButtonContainer } from '../inspect';

const DEFAULT_PANEL_HEIGHT = 300;

const HeaderChildrenFlexItem = styled(EuiFlexItem)`
margin-left: 24px;
`;

const HistogramPanel = styled(Panel)<{ height?: number }>`
display: flex;
flex-direction: column;
${({ height }) => (height != null ? `height: ${height}px;` : '')}
`;

export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &
MatrixHistogramQueryProps> = ({
chartHeight,
dataKey,
defaultStackByOption,
endDate,
Expand All @@ -43,6 +57,7 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &
isInspected,
legendPosition = 'right',
mapping,
panelHeight = DEFAULT_PANEL_HEIGHT,
query,
scaleType = ScaleType.Time,
setQuery,
Expand All @@ -56,6 +71,7 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &
yTickFormatter,
}) => {
const barchartConfigs = getBarchartConfigs({
chartHeight,
from: startDate,
legendPosition,
to: endDate,
Expand Down Expand Up @@ -143,7 +159,7 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &
return (
<>
<InspectButtonContainer show={!isInitialLoading}>
<Panel data-test-subj={`${id}Panel`}>
<HistogramPanel data-test-subj={`${id}Panel`} height={panelHeight}>
{loading && !isInitialLoading && (
<EuiProgress
data-test-subj="initialLoadingPanelMatrixOverTime"
Expand All @@ -155,15 +171,33 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &

{isInitialLoading ? (
<>
<HeaderSection id={id} title={titleWithStackByField} />
<HeaderSection
id={id}
title={titleWithStackByField}
subtitle={!loading && (totalCount >= 0 ? subtitleWithCounts : null)}
>
<EuiFlexGroup alignItems="center" gutterSize="none">
<EuiFlexItem grow={false}>
{stackByOptions?.length > 1 && (
<EuiSelect
onChange={setSelectedChartOptionCallback}
options={stackByOptions}
prepend={i18n.STACK_BY}
value={selectedStackByOption?.value}
/>
)}
</EuiFlexItem>
<HeaderChildrenFlexItem grow={false}>{headerChildren}</HeaderChildrenFlexItem>
</EuiFlexGroup>
</HeaderSection>
<MatrixLoader />
</>
) : (
<>
<HeaderSection
id={id}
title={titleWithStackByField}
subtitle={!loading && (totalCount >= 0 ? subtitleWithCounts : null)}
subtitle={!isInitialLoading && (totalCount >= 0 ? subtitleWithCounts : null)}
>
<EuiFlexGroup alignItems="center" gutterSize="none">
<EuiFlexItem grow={false}>
Expand All @@ -176,13 +210,13 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &
/>
)}
</EuiFlexItem>
<EuiFlexItem grow={false}>{headerChildren}</EuiFlexItem>
<HeaderChildrenFlexItem grow={false}>{headerChildren}</HeaderChildrenFlexItem>
</EuiFlexGroup>
</HeaderSection>
<BarChart barChart={barChartData} configs={barchartConfigs} />
</>
)}
</Panel>
</HistogramPanel>
</InspectButtonContainer>
<EuiSpacer size="l" />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import styled from 'styled-components';

const StyledEuiFlexGroup = styled(EuiFlexGroup)`
height: 350px; /* to avoid jump when histogram loads */
flex 1;
`;

const MatrixLoaderComponent = () => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type GetSubTitle = (count: number) => string;
export type GetTitle = (matrixHistogramOption: MatrixHistogramOption) => string;

export interface MatrixHistogramBasicProps {
chartHeight?: number;
defaultIndex: string[];
defaultStackByOption: MatrixHistogramOption;
endDate: number;
Expand All @@ -39,6 +40,7 @@ export interface MatrixHistogramBasicProps {
id: string;
legendPosition?: Position;
mapping?: MatrixHistogramMappingTypes;
panelHeight?: number;
setQuery: SetQuery;
sourceId: string;
startDate: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { MatrixHistogramDataTypes, MatrixHistogramMappingTypes } from './types';
import { histogramDateTimeFormatter } from '../utils';

interface GetBarchartConfigsProps {
chartHeight?: number;
from: number;
legendPosition?: Position;
to: number;
Expand All @@ -20,7 +21,10 @@ interface GetBarchartConfigsProps {
showLegend?: boolean;
}

export const DEFAULT_CHART_HEIGHT = 174;

export const getBarchartConfigs = ({
chartHeight,
from,
legendPosition,
to,
Expand Down Expand Up @@ -65,7 +69,7 @@ export const getBarchartConfigs = ({
},
},
},
customHeight: 324,
customHeight: chartHeight ?? DEFAULT_CHART_HEIGHT,
});

export const formatToChartDataItem = ([key, value]: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,42 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiLoadingSpinner, EuiSpacer } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import React from 'react';

import { NoNews } from './no_news';
import { LoadingPlaceholders } from '../page/overview/loading_placeholders';
import { NEWS_FEED_TITLE } from '../../pages/overview/translations';
import { Post } from './post';
import { SidebarHeader } from '../sidebar_header';

import { NoNews } from './no_news';
import { Post } from './post';
import { NewsItem } from './types';

interface Props {
news: NewsItem[] | null | undefined;
}

export const NewsFeed = React.memo<Props>(({ news }) => {
if (news == null) {
return <EuiLoadingSpinner size="m" />;
}

if (news.length === 0) {
return <NoNews />;
}
const SHOW_PLACEHOLDERS = 5;
const LINES_PER_LOADING_PLACEHOLDER = 4;

return (
<>
<SidebarHeader title={NEWS_FEED_TITLE} />
{news.map((n: NewsItem) => (
const NewsFeedComponent: React.FC<Props> = ({ news }) => (
<>
<SidebarHeader title={NEWS_FEED_TITLE} />
{news == null ? (
<LoadingPlaceholders lines={LINES_PER_LOADING_PLACEHOLDER} placeholders={SHOW_PLACEHOLDERS} />
) : news.length === 0 ? (
<NoNews />
) : (
news.map((n: NewsItem) => (
<React.Fragment key={n.hash}>
<Post newsItem={n} />
<EuiSpacer size="l" />
</React.Fragment>
))}
</>
);
});
))
)}
</>
);

NewsFeedComponent.displayName = 'NewsFeedComponent';

NewsFeed.displayName = 'NewsFeed';
export const NewsFeed = React.memo(NewsFeedComponent);
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as i18n from '../translations';
export const NoNews = React.memo(() => (
<>
<EuiText color="subdued" size="s">
{i18n.NO_NEWS_MESSAGE}
{i18n.NO_NEWS_MESSAGE}{' '}
<EuiLink href={'/app/kibana#/management/kibana/settings'}>
{i18n.ADVANCED_SETTINGS_LINK_TITLE}
</EuiLink>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';

export const NO_NEWS_MESSAGE = i18n.translate('xpack.siem.newsFeed.noNewsMessage', {
defaultMessage:
'Your current News feed URL returned no recent news. You may update the URL or disable security news via',
'Your current news feed URL returned no recent news. You may update the URL or disable security news via',
});

export const ADVANCED_SETTINGS_LINK_TITLE = i18n.translate(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiLoadingContent, EuiSpacer } from '@elastic/eui';
import React from 'react';

const LoadingPlaceholdersComponent: React.FC<{
lines: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
placeholders: number;
}> = ({ lines, placeholders }) => (
<>
{[...Array(placeholders).keys()].map((_, i) => (
<React.Fragment key={i}>
<EuiLoadingContent lines={lines} />
{i !== placeholders - 1 && <EuiSpacer size="l" />}
</React.Fragment>
))}
</>
);

LoadingPlaceholdersComponent.displayName = 'LoadingPlaceholdersComponent';

export const LoadingPlaceholders = React.memo(LoadingPlaceholdersComponent);
Loading

0 comments on commit b546bf8

Please sign in to comment.