[SECURITY SOLUTION] [RAC] bug actions padding (#109029)

* wip

* match design for selecting grid view

* wip to integrate event rendered view

* wip

* integration of the event rendered

* fix perPage action on Euibasic table

* Add bulding block background color to EventRenderedView

* styling

* remove header

* fix types

* fix unit tests

* use memo for listProps

* fix styling + add feature flag

* review I

* fix merge

* change the gutter size

* fix bugs

* fix alert consumers

Co-authored-by: Pablo Neves Machado <pablo.nevesmachado@elastic.co>
Co-authored-by: Angela Chuang <yi-chun.chuang@elastic.co>
Co-authored-by: Michael Olorunnisola <michael.olorunnisola@elastic.co>
This commit is contained in:
Xavier Mouligneau 2021-08-18 07:37:40 -04:00 committed by GitHub
parent 2592e36c15
commit e4bf6140fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 50 additions and 47 deletions

View file

@ -8,7 +8,6 @@
import React, { useCallback, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import { AlertConsumers } from '@kbn/rule-data-utils';
import {
getCaseDetailsUrl,
getCaseDetailsUrlWithCommentId,
@ -34,7 +33,6 @@ import { SpyRoute } from '../../../common/utils/route/spy_routes';
import * as timelineMarkdownPlugin from '../../../common/components/markdown_editor/plugins/timeline';
import { CaseDetailsRefreshContext } from '../../../common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context';
import { getEndpointDetailsPath } from '../../../management/common/routing';
import { EntityType } from '../../../../../timelines/common';
interface Props {
caseId: string;
@ -55,7 +53,7 @@ export interface CaseProps extends Props {
updateCase: (newCase: Case) => void;
}
const ALERT_CONSUMER: AlertConsumers[] = [AlertConsumers.SIEM];
const SECURITY_SOLUTION_ALERT_CONSUMERS: AlertConsumers[] = [AlertConsumers.SIEM];
const TimelineDetailsPanel = ({ alertConsumers }: { alertConsumers?: AlertConsumers[] }) => {
const { browserFields, docValueFields } = useSourcererScope(SourcererScopeName.detections);
@ -65,7 +63,7 @@ const TimelineDetailsPanel = ({ alertConsumers }: { alertConsumers?: AlertConsum
alertConsumers={alertConsumers}
browserFields={browserFields}
docValueFields={docValueFields}
entityType={EntityType.ALERTS}
entityType="alerts"
isFlyoutView
timelineId={TimelineId.casePage}
/>
@ -234,7 +232,7 @@ export const CaseView = React.memo(({ caseId, subCaseId, userCanCrud }: Props) =
showAlertDetails,
subCaseId,
timelineIntegration: {
alertConsumers: ALERT_CONSUMER,
alertConsumers: SECURITY_SOLUTION_ALERT_CONSUMERS,
editor_plugins: {
parsingPlugin: timelineMarkdownPlugin.parser,
processingPluginRenderer: timelineMarkdownPlugin.renderer,

View file

@ -20,6 +20,7 @@ import { useKibana } from '../../lib/kibana';
import { SourcererScopeName } from '../../store/sourcerer/model';
import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features';
import { DEFAULT_COLUMN_MIN_WIDTH } from '../../../timelines/components/timeline/body/constants';
import type { EntityType } from '../../../../../timelines/common';
export interface OwnProps {
end: string;
@ -63,6 +64,7 @@ const defaultAlertsFilters: Filter[] = [
interface Props {
timelineId: TimelineIdLiteral;
endDate: string;
entityType?: EntityType;
startDate: string;
pageFilters?: Filter[];
}
@ -70,6 +72,7 @@ interface Props {
const AlertsTableComponent: React.FC<Props> = ({
timelineId,
endDate,
entityType = 'alerts',
startDate,
pageFilters = [],
}) => {
@ -107,7 +110,7 @@ const AlertsTableComponent: React.FC<Props> = ({
defaultModel={alertsDefaultModel}
defaultCellActions={defaultCellActions}
end={endDate}
entityType="alerts"
entityType={entityType}
id={timelineId}
renderCellValue={DefaultCellRenderer}
rowRenderers={defaultRowRenderers}

View file

@ -25,6 +25,7 @@ const AlertsViewComponent: React.FC<AlertsComponentsProps> = ({
timelineId,
deleteQuery,
endDate,
entityType,
filterQuery,
indexNames,
pageFilters,
@ -74,6 +75,7 @@ const AlertsViewComponent: React.FC<AlertsComponentsProps> = ({
<AlertsTable
timelineId={timelineId}
endDate={endDate}
entityType={entityType}
startDate={startDate}
pageFilters={pageFilters}
/>

View file

@ -6,6 +6,7 @@
*/
import { Filter } from '../../../../../../../src/plugins/data/public';
import type { EntityType } from '../../../../../timelines/common';
import { TimelineIdLiteral } from '../../../../common/types/timeline';
import { HostsComponentsQueryProps } from '../../../hosts/pages/navigation/types';
import { NetworkComponentQueryProps } from '../../../network/pages/navigation/types';
@ -23,5 +24,6 @@ export interface AlertsComponentsProps
stackByOptions?: MatrixHistogramOption[];
defaultFilters?: Filter[];
defaultStackByOption?: MatrixHistogramOption;
entityType?: EntityType;
indexNames: string[];
}

View file

@ -11,7 +11,6 @@ import deepEqual from 'fast-deep-equal';
import styled from 'styled-components';
import { isEmpty } from 'lodash/fp';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { inputsModel, inputsSelectors, State } from '../../store';
import { inputsActions } from '../../store/actions';
import { ControlColumnProps, RowRenderer, TimelineId } from '../../../../common/types/timeline';
@ -24,7 +23,7 @@ import { useGlobalFullScreen } from '../../containers/use_full_screen';
import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features';
import { SourcererScopeName } from '../../store/sourcerer/model';
import { useSourcererScope } from '../../containers/sourcerer';
import { EntityType } from '../../../../../timelines/common';
import type { EntityType } from '../../../../../timelines/common';
import { TGridCellAction } from '../../../../../timelines/common/types';
import { DetailsPanel } from '../../../timelines/components/side_panel';
import { CellValueElementProps } from '../../../timelines/components/timeline/cell_rendering';
@ -69,8 +68,6 @@ export interface OwnProps {
type Props = OwnProps & PropsFromRedux;
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
/**
* The stateful events viewer component is the highest level component that is utilized across the security_solution pages layer where
* timeline is used BESIDES the flyout. The flyout makes use of the `EventsViewer` component which is a subcomponent here
@ -219,9 +216,8 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
</InspectButtonContainer>
</FullScreenContainer>
<DetailsPanel
alertConsumers={alertConsumers}
browserFields={browserFields}
entityType={EntityType.ALERTS}
entityType={entityType}
docValueFields={docValueFields}
isFlyoutView
timelineId={id}

View file

@ -52,6 +52,7 @@ export const HostAlertsQueryTabBody = React.memo((alertsProps: AlertsComponentQu
return (
<AlertsView
entityType="events"
timelineId={TimelineId.hostsPageExternalAlerts}
{...rest}
pageFilters={hostPageFilters}

View file

@ -65,6 +65,7 @@ export const filterNetworkData: Filter[] = [
export const NetworkAlertsQueryTabBody = React.memo((alertsProps: NetworkComponentQueryProps) => (
<AlertsView
entityType="events"
timelineId={TimelineId.networkPageExternalAlerts}
{...alertsProps}
pageFilters={filterNetworkData}

View file

@ -68,11 +68,13 @@ interface EventDetailsPanelProps {
timelineId: string;
}
const SECURITY_SOLUTION_ALERT_CONSUMERS: AlertConsumers[] = [AlertConsumers.SIEM];
const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({
alertConsumers,
alertConsumers = SECURITY_SOLUTION_ALERT_CONSUMERS, // Default to Security Solution so only other applications have to pass this in
browserFields,
docValueFields,
entityType,
entityType = 'events', // Default to events so only alerts have to pass entityType in
expandedEvent,
handleOnEventClosed,
isFlyoutView,

View file

@ -13,7 +13,6 @@ import {
EuiFlyoutFooter,
EuiBadge,
} from '@elastic/eui';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { isEmpty } from 'lodash/fp';
import React, { useEffect, useCallback } from 'react';
import styled from 'styled-components';
@ -152,8 +151,6 @@ export type Props = OwnProps & PropsFromRedux;
const NO_SORTING: Sort[] = [];
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
export const EqlTabContentComponent: React.FC<Props> = ({
activeTab,
columns,
@ -349,7 +346,6 @@ export const EqlTabContentComponent: React.FC<Props> = ({
<VerticalRule />
<ScrollableFlexItem grow={1}>
<DetailsPanel
alertConsumers={alertConsumers}
browserFields={browserFields}
docValueFields={docValueFields}
tabType={TimelineTabs.eql}

View file

@ -16,7 +16,6 @@ import {
EuiPanel,
EuiHorizontalRule,
} from '@elastic/eui';
import { AlertConsumers } from '@kbn/rule-data-utils';
import React, { Fragment, useCallback, useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';
@ -71,8 +70,6 @@ const Username = styled(EuiText)`
font-weight: bold;
`;
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
interface UsernameWithAvatar {
username: string;
}
@ -185,7 +182,6 @@ const NotesTabContentComponent: React.FC<NotesTabContentProps> = ({ timelineId }
() =>
expandedDetail[TimelineTabs.notes]?.panelView ? (
<DetailsPanel
alertConsumers={alertConsumers}
browserFields={browserFields}
docValueFields={docValueFields}
handleOnPanelClosed={handleOnPanelClosed}

View file

@ -6,7 +6,6 @@
*/
import { EuiFlexGroup, EuiFlexItem, EuiFlyoutBody, EuiFlyoutFooter } from '@elastic/eui';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { isEmpty } from 'lodash/fp';
import React, { useMemo, useCallback } from 'react';
import styled from 'styled-components';
@ -89,8 +88,6 @@ const VerticalRule = styled.div`
VerticalRule.displayName = 'VerticalRule';
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
interface OwnProps {
renderCellValue: (props: CellValueElementProps) => React.ReactNode;
rowRenderers: RowRenderer[];
@ -269,7 +266,6 @@ export const PinnedTabContentComponent: React.FC<Props> = ({
<VerticalRule />
<ScrollableFlexItem grow={1}>
<DetailsPanel
alertConsumers={alertConsumers}
browserFields={browserFields}
docValueFields={docValueFields}
handleOnPanelClosed={handleOnPanelClosed}

View file

@ -13,7 +13,6 @@ import {
EuiFlyoutFooter,
EuiBadge,
} from '@elastic/eui';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { isEmpty } from 'lodash/fp';
import React, { useState, useMemo, useEffect, useCallback } from 'react';
import styled from 'styled-components';
@ -136,8 +135,6 @@ const EventsCountBadge = styled(EuiBadge)`
margin-left: ${({ theme }) => theme.eui.paddingSizes.s};
`;
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
const isTimerangeSame = (prevProps: Props, nextProps: Props) =>
prevProps.end === nextProps.end &&
prevProps.start === nextProps.start &&
@ -417,7 +414,6 @@ export const QueryTabContentComponent: React.FC<Props> = ({
<VerticalRule />
<ScrollableFlexItem grow={1}>
<DetailsPanel
alertConsumers={alertConsumers}
browserFields={browserFields}
docValueFields={docValueFields}
handleOnPanelClosed={handleOnPanelClosed}

View file

@ -41,6 +41,14 @@ const EventRenderedFlexItem = styled(EuiFlexItem)`
}
`;
const ActionsContainer = styled.div`
display: flex;
align-items: center;
div div:first-child div.siemEventsTable__tdContent {
margin-left: ${({ theme }) => theme.eui.paddingSizes.m};
}
`;
// Fix typing issue with EuiBasicTable and styled
type BasicTableType = ComponentType<EuiBasicTableProps<TimelineItem>>;
@ -113,25 +121,31 @@ const EventRenderedViewComponent = ({
name: ActionTitle,
truncateText: false,
hideForMobile: false,
// eslint-disable-next-line react/display-name
render: (name: unknown, item: unknown) => {
const alertId = get(item, '_id');
const rowIndex = events.findIndex((evt) => evt._id === alertId);
return leadingControlColumns.length > 0
? leadingControlColumns.map((action) => {
const getActions = action.rowCellRender as (
props: EuiDataGridCellValueElementProps
) => React.ReactNode;
return getActions({
columnId: 'actions',
isDetails: false,
isExpandable: false,
isExpanded: false,
rowIndex,
setCellProps: () => null,
});
})
: null;
return (
<ActionsContainer>
{leadingControlColumns.length > 0
? leadingControlColumns.map((action) => {
const getActions = action.rowCellRender as (
props: EuiDataGridCellValueElementProps
) => React.ReactNode;
return getActions({
columnId: 'actions',
isDetails: false,
isExpandable: false,
isExpanded: false,
rowIndex,
setCellProps: () => null,
});
})
: null}
</ActionsContainer>
);
},
width: '120px',
},
{
field: 'ecs.@timestamp',

View file

@ -142,7 +142,6 @@ const SummaryViewSelectorComponent = ({ viewSelected, onViewChange }: SummaryVie
>
<ContainerEuiSelectable>
<EuiSelectable
aria-label="Basic example"
options={options}
onChange={onChangeSelectable}
renderOption={renderOption}

View file

@ -232,6 +232,7 @@ const TGridIntegratedComponent: React.FC<TGridIntegratedProps> = ({
loading,
{ events, loadPage, pageInfo, refetch, totalCount = 0, inspect },
] = useTimelineEvents({
// We rely on entityType to determine Events vs Alerts
alertConsumers: SECURITY_ALERTS_CONSUMERS,
docValueFields,
entityType,
@ -302,7 +303,7 @@ const TGridIntegratedComponent: React.FC<TGridIntegratedProps> = ({
<UpdatedFlexItem grow={false} show={!loading}>
{!resolverIsShowing(graphEventId) && additionalFilters}
</UpdatedFlexItem>
{tGridEventRenderedViewEnabled && (
{tGridEventRenderedViewEnabled && entityType === 'alerts' && (
<UpdatedFlexItem grow={false} show={!loading}>
<SummaryViewSelector viewSelected={tableView} onViewChange={setTableView} />
</UpdatedFlexItem>