Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] - Timeline UI refactor #168230

Merged
merged 59 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
54bf025
feat/intial_timeline_ui
logeekal Oct 6, 2023
69d6538
more experimental UI
logeekal Oct 12, 2023
1f4dd53
incremental save
logeekal Oct 23, 2023
b3a13bd
incremental save
logeekal Oct 24, 2023
b5c17d7
feat: added timeline action menu + fixed filter badges
logeekal Oct 25, 2023
ef13b22
timeline ui all changes
logeekal Oct 30, 2023
133756f
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Oct 30, 2023
70002c6
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Oct 30, 2023
ba4bcc0
fix: add missing translations
logeekal Oct 30, 2023
74b3cb8
Merged main -> current branch
logeekal Oct 30, 2023
eb76e7f
fix: types + some tests
logeekal Oct 31, 2023
fee5b8c
fix: more tests
logeekal Oct 31, 2023
c3c11b9
fix: cypress tests
logeekal Nov 3, 2023
e80341b
Merged main -> current branch
logeekal Nov 7, 2023
f244f03
fix: adapt UI according to new timeline saving strategy
logeekal Nov 7, 2023
84997b1
fix: cypress+ftr tests
logeekal Nov 8, 2023
9b20c0e
fix: some tests
logeekal Nov 8, 2023
5266dce
fix: types
logeekal Nov 8, 2023
580b0f0
fix: jest tests
logeekal Nov 9, 2023
790576d
Merged main -> current branch
logeekal Nov 9, 2023
8fa0e74
fix: review feedback
logeekal Nov 9, 2023
2ae0cdc
fix: data provider redesign
logeekal Nov 9, 2023
92b5f91
fix: tests + housekeeping
logeekal Nov 10, 2023
7dbf8dc
fix: organise tests + more fixes
logeekal Nov 10, 2023
2174293
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 10, 2023
9877b9b
fix: remove unnecssary eslint exception
logeekal Nov 13, 2023
780b5fd
fix: types
logeekal Nov 13, 2023
1219c20
Merge branch 'main' into expr/new_timeline_ui
kibanamachine Nov 14, 2023
9e78fbf
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 14, 2023
b63a5bc
fix: review feedback
logeekal Nov 15, 2023
4c99fb5
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 15, 2023
8d06e2c
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 15, 2023
9147e34
fix: translations title
logeekal Nov 15, 2023
7e05d5d
fix: hide standard filters
logeekal Nov 16, 2023
64b500c
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 16, 2023
39fe8cb
Merged main -> current branch
logeekal Nov 20, 2023
528366e
fix: more UI Fixes as per PR feedback
logeekal Nov 20, 2023
5ba8785
hide kpis till lens embeddables are working
logeekal Nov 21, 2023
4ed7d4e
fix: modal padding + radius + alignment + more nits
logeekal Nov 21, 2023
d5a0630
fix: more fixes
logeekal Nov 21, 2023
8d9376f
Merged main -> current branch
logeekal Nov 21, 2023
d1d72d0
fix: notes tab spacing inconsistencies
logeekal Nov 21, 2023
6213e11
fix: cypress tests
logeekal Nov 21, 2023
772a300
fix: more spacing on notes tab
logeekal Nov 21, 2023
1f9853e
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 21, 2023
5f891f0
fix: review feedback
logeekal Nov 22, 2023
a2502d4
fix: revert some unncessary changes
logeekal Nov 22, 2023
bfc1246
fix:filter-search-popover-width
logeekal Nov 22, 2023
53c6c39
Merged main -> current branch
logeekal Nov 23, 2023
af2d737
fix: review feedback
logeekal Nov 24, 2023
7451a7d
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 24, 2023
ac257e3
fix: revert some changes
logeekal Nov 24, 2023
ef489cf
fix: remove data-test-subj from styles
logeekal Nov 24, 2023
05b43e2
fix: spellings
logeekal Nov 24, 2023
05d764c
fix: flyout footer
logeekal Nov 24, 2023
2ed673e
fix: cypress test
logeekal Nov 24, 2023
304b99a
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 25, 2023
5273e4c
fix: misc
logeekal Nov 26, 2023
bb377ed
Merge branch 'main' into expr/new_timeline_ui
logeekal Nov 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/plugins/unified_search/public/filter_bar/filter_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const FilterBarUI = React.memo(function FilterBarUI(props: Props) {
gutterSize="none" // We use `gap` in the styles instead for better truncation of badges
alignItems="center"
tabIndex={-1}
data-test-subj="filter-items-group"
className={`filter-items-group ${props.className ?? ''}`}
>
{props.prepend}
<FilterItems
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ const RoundBadge = styled(EuiBadge)`
margin: 0 5px 0 5px;
padding: 7px 6px 4px 6px;
user-select: none;
width: 34px;
width: 40px;
height: 40px;
.euiBadge__content {
position: relative;
top: -1px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@

import { noop, pick } from 'lodash/fp';
import React, { useCallback, useMemo } from 'react';
import type { DropResult } from '@hello-pangea/dnd';
import type { DragStart, DropResult } from '@hello-pangea/dnd';
import { DragDropContext } from '@hello-pangea/dnd';
import { useDispatch } from 'react-redux';
import type { Dispatch } from 'redux';
import deepEqual from 'fast-deep-equal';
import { IS_DRAGGING_CLASS_NAME } from '@kbn/securitysolution-t-grid';

import type { BeforeCapture } from './drag_drop_context';
import type { BrowserFields } from '../../containers/source';
import { dragAndDropSelectors } from '../../store';
import { timelineSelectors } from '../../../timelines/store/timeline';
Expand Down Expand Up @@ -151,8 +150,9 @@ export const DragDropContextWrapperComponent: React.FC<Props> = ({ browserFields
},
[activeTimelineDataProviders, browserFields, dataProviders, dispatch, onAddedToTimeline]
);

return (
<DragDropContext onDragEnd={onDragEnd} onBeforeCapture={onBeforeCapture} sensors={sensors}>
<DragDropContext onBeforeDragStart={onBeforeDragStart} onDragEnd={onDragEnd} sensors={sensors}>
{children}
</DragDropContext>
);
Expand All @@ -168,12 +168,12 @@ export const DragDropContextWrapper = React.memo(

DragDropContextWrapper.displayName = 'DragDropContextWrapper';

const onBeforeCapture = (before: BeforeCapture) => {
if (!draggableIsField(before)) {
const onBeforeDragStart = (start: DragStart) => {
if (!draggableIsField(start)) {
document.body.classList.add(IS_DRAGGING_CLASS_NAME);
}

if (draggableIsField(before)) {
if (draggableIsField(start)) {
document.body.classList.add(IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@

import { EuiButton, EuiWindowEvent } from '@elastic/eui';
import React, { useCallback } from 'react';
import styled from 'styled-components';

import * as i18n from './translations';

export const EXIT_FULL_SCREEN_CLASS_NAME = 'exit-full-screen';

const StyledEuiButton = styled(EuiButton)`
margin: ${({ theme }) => theme.eui.euiSizeS};
`;

interface Props {
fullScreen: boolean;
setFullScreen: (fullScreen: boolean) => void;
Expand Down Expand Up @@ -45,16 +40,17 @@ const ExitFullScreenComponent: React.FC<Props> = ({ fullScreen, setFullScreen })
return (
<>
<EuiWindowEvent event="keydown" handler={onKeyDown} />
<StyledEuiButton
<EuiButton
className={EXIT_FULL_SCREEN_CLASS_NAME}
data-test-subj="exit-full-screen"
fullWidth={false}
iconType="fullScreen"
fill
isDisabled={!fullScreen}
onClick={exitFullScreen}
>
{i18n.EXIT_FULL_SCREEN}
</StyledEuiButton>
</EuiButton>
</>
);
};
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const HeaderSectionComponent: React.FC<HeaderSectionProps> = ({
stackHeader,
subtitle,
title,
titleSize = 'm',
titleSize = 'l',
toggleQuery,
toggleStatus = true,
tooltip,
Expand Down Expand Up @@ -173,7 +173,6 @@ const HeaderSectionComponent: React.FC<HeaderSectionProps> = ({
<span className="eui-textBreakNormal">{title}</span>
{tooltip && (
<>
{' '}
<EuiIconTip
color="subdued"
title={tooltipTitle}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface InspectButtonProps {
onCloseInspect?: () => void;
queryId: string;
showInspectButton?: boolean;
title: string | React.ReactElement | React.ReactNode;
title?: string | React.ReactElement | React.ReactNode;
}

const InspectButtonComponent: React.FC<InspectButtonProps> = ({
Expand Down Expand Up @@ -80,9 +80,6 @@ const InspectButtonComponent: React.FC<InspectButtonProps> = ({
className={BUTTON_CLASS}
aria-label={i18n.INSPECT}
data-test-subj="inspect-empty-button"
color="text"
iconSide="left"
iconType="inspect"
isDisabled={isButtonDisabled}
isLoading={loading}
onClick={handleClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ export const QueryBar = memo<QueryBarComponentProps>(
savedQuery={savedQuery}
displayStyle={displayStyle}
isDisabled={isDisabled}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small thing I noticed that has probably always been there. When you update the query in either the main security application or in discover the refresh button changes to update. Would it be a huge lift to implement that here as well? If so, we can pull it out to a separate issue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelolo24 , I can see it happening today.

Screen.Recording.2023-11-15.at.09.45.54.mov

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yea, I agree it's not a bug you introduced. Was just wondering if it could be done as part of this refactor to align with the other experiences, but that can be done separately.

hideTextBasedRunQueryLabel
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';

import { Sourcerer } from '.';
import { sourcererModel } from '../../store/sourcerer';
import {
createSecuritySolutionStorageMock,
kibanaObservable,
mockGlobalState,
SUB_PLUGINS_REDUCER,
TestProviders,
} from '../../mock';
import { createStore } from '../../store';
import { useSourcererDataView } from '../../containers/sourcerer';
import { useSignalHelpers } from '../../containers/sourcerer/use_signal_helpers';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';

const mockDispatch = jest.fn();

jest.mock('../../containers/sourcerer');
jest.mock('../../containers/sourcerer/use_signal_helpers');
const mockUseUpdateDataView = jest.fn().mockReturnValue(() => true);
jest.mock('./use_update_data_view', () => ({
useUpdateDataView: () => mockUseUpdateDataView,
}));
jest.mock('react-redux', () => {
const original = jest.requireActual('react-redux');

return {
...original,
useDispatch: () => mockDispatch,
};
});

jest.mock('@kbn/kibana-react-plugin/public', () => {
const original = jest.requireActual('@kbn/kibana-react-plugin/public');

return {
...original,
toMountPoint: jest.fn(),
};
});

const mockUpdateUrlParam = jest.fn();
jest.mock('../../utils/global_query_string', () => {
const original = jest.requireActual('../../utils/global_query_string');

return {
...original,
useUpdateUrlParam: () => mockUpdateUrlParam,
};
});

let store: ReturnType<typeof createStore>;
const sourcererDataView = {
indicesExist: true,
loading: false,
};
describe('sourcerer on alerts page or rules details page', () => {
const { storage } = createSecuritySolutionStorageMock();
store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage);
const testProps = {
scope: sourcererModel.SourcererScopeName.detections,
};

const pollForSignalIndexMock = jest.fn();

beforeEach(async () => {
jest.clearAllMocks();

(useSignalHelpers as jest.Mock).mockReturnValue({
pollForSignalIndex: pollForSignalIndexMock,
signalIndexNeedsInit: false,
});

(useSourcererDataView as jest.Mock).mockReturnValue({
...sourcererDataView,
indicesExist: true,
});

render(
<TestProviders store={store}>
<Sourcerer {...testProps} />
</TestProviders>
);

fireEvent.click(screen.getByTestId('sourcerer-trigger'));
await waitFor(() => {
expect(screen.getByTestId('sourcerer-advanced-options-toggle')).toBeVisible();
});
fireEvent.click(screen.getByTestId('sourcerer-advanced-options-toggle'));
});

it('renders an alerts badge in sourcerer button', () => {
expect(screen.getByTestId('sourcerer-advanced-options-toggle')).toHaveTextContent(
/Advanced options/
);
});

it('renders a callout', () => {
expect(screen.getByTestId('sourcerer-callout')).toHaveTextContent(
'Data view cannot be modified on this page'
);
});

it('disable data view selector', () => {
expect(screen.getByTestId('sourcerer-select')).toBeDisabled();
});

it('data view selector is default to Security Data View', () => {
expect(screen.getByTestId('sourcerer-select')).toHaveTextContent(/security data view/i);
});

it('renders an alert badge in data view selector', () => {
expect(screen.getByTestId('security-alerts-option-badge')).toHaveTextContent('Alerts');
});

it('disable index pattern selector', () => {
expect(screen.getByTestId('sourcerer-combo-box')).toHaveAttribute('disabled');
});

it('shows signal index as index pattern option', () => {
expect(screen.getByTestId('euiComboBoxPill')).toHaveTextContent('.siem-signals-spacename');
});

it('does not render reset button', () => {
expect(screen.queryByTestId('sourcerer-reset')).toBeFalsy();
});

it('does not render save button', () => {
expect(screen.queryByTestId('sourcerer-save')).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { EuiSuperSelectOption, EuiFormRowProps } from '@elastic/eui';
import { EuiIcon, EuiBadge, EuiButtonEmpty, EuiFormRow } from '@elastic/eui';
import styled, { css } from 'styled-components';

import { euiThemeVars } from '@kbn/ui-theme';
import type { sourcererModel } from '../../store/sourcerer';

import * as i18n from './translations';
Expand All @@ -23,7 +24,7 @@ export const StyledFormRow = styled(EuiFormRow)`
max-width: none;
`;

export const StyledButton = styled(EuiButtonEmpty)`
export const StyledButtonEmpty = styled(EuiButtonEmpty)`
&:enabled:focus,
&:focus {
background-color: transparent;
Expand All @@ -43,7 +44,7 @@ export const PopoverContent = styled.div`
`;

export const StyledBadge = styled(EuiBadge)`
margin-left: 8px;
margin-left: ${euiThemeVars.euiSizeXS};
&,
.euiBadge__text {
cursor: pointer;
Expand Down
Loading
Loading