* Revert "[SIEM] apollo@3 (#51926)" * cleanup
This commit is contained in:
parent
8e4a3b5447
commit
9d5582bcc4
17
package.json
17
package.json
|
@ -75,31 +75,23 @@
|
|||
"url": "https://github.com/elastic/kibana.git"
|
||||
},
|
||||
"resolutions": {
|
||||
"**/@apollo/client": "^3.0.0-beta.37",
|
||||
"**/@graphql-toolkit/common": "^0.9.7",
|
||||
"**/@graphql-toolkit/core": "^0.9.7",
|
||||
"**/@graphql-toolkit/graphql-file-loader": "^0.9.7",
|
||||
"**/@graphql-toolkit/json-file-loader": "^0.9.7",
|
||||
"**/@graphql-toolkit/schema-merging": "^0.9.7",
|
||||
"**/@graphql-toolkit/url-loader": "^0.9.7",
|
||||
"**/@types/node": "10.12.27",
|
||||
"**/@types/react": "^16.9.19",
|
||||
"**/@types/react-router": "^5.1.3",
|
||||
"**/@types/hapi": "^17.0.18",
|
||||
"**/@types/angular": "^1.6.56",
|
||||
"**/@types/hoist-non-react-statics": "^3.3.1",
|
||||
"**/apollo-link": "^1.2.13",
|
||||
"**/deepmerge": "^4.2.2",
|
||||
"**/fast-deep-equal": "^3.1.1",
|
||||
"**/fast-glob": "3.1.1",
|
||||
"**/typescript": "3.7.2",
|
||||
"**/graphql-toolkit/lodash": "^4.17.13",
|
||||
"**/hoist-non-react-statics": "^3.3.2",
|
||||
"**/isomorphic-git/**/base64-js": "^1.2.1",
|
||||
"**/image-diff/gm/debug": "^2.6.9",
|
||||
"**/react-dom": "^16.12.0",
|
||||
"**/react": "^16.12.0",
|
||||
"**/react-test-renderer": "^16.12.0",
|
||||
"**/deepmerge": "^4.2.2",
|
||||
"**/serialize-javascript": "^2.1.1",
|
||||
"**/typescript": "3.7.2"
|
||||
"**/fast-deep-equal": "^3.1.1"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
@ -329,6 +321,7 @@
|
|||
"@types/getos": "^3.0.0",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/globby": "^8.0.0",
|
||||
"@types/graphql": "^0.13.2",
|
||||
"@types/hapi": "^17.0.18",
|
||||
"@types/hapi-auth-cookie": "^9.1.0",
|
||||
"@types/has-ansi": "^3.0.0",
|
||||
|
|
|
@ -38,6 +38,7 @@ beforeAll(async () => {
|
|||
await cpy('**/*', MOCK_REPO_DIR, {
|
||||
cwd: MOCK_REPO_SRC,
|
||||
parents: true,
|
||||
deep: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ beforeEach(async () => {
|
|||
await cpy('**/*', MOCK_REPO_DIR, {
|
||||
cwd: MOCK_REPO_SRC,
|
||||
parents: true,
|
||||
deep: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
|
|||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js', '.ts', '.tsx', '.json'],
|
||||
extensions: ['.js', '.ts', '.tsx', '.json'],
|
||||
alias: {
|
||||
tinymath: require.resolve('tinymath/lib/tinymath.es5.js'),
|
||||
},
|
||||
|
|
24999
packages/kbn-pm/dist/index.js
vendored
24999
packages/kbn-pm/dist/index.js
vendored
File diff suppressed because one or more lines are too long
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const rootSchema = gql`
|
||||
schema {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const sharedSchema = gql`
|
||||
input TimerangeInput {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { createHashHistory, History } from 'history';
|
||||
import React, { memo, useMemo, FC } from 'react';
|
||||
import { ApolloProvider } from '@apollo/client';
|
||||
import { ApolloProvider } from 'react-apollo';
|
||||
import { Store } from 'redux';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
@ -30,6 +30,8 @@ import { createStore, createInitialState } from '../store';
|
|||
import { GlobalToaster, ManageGlobalToaster } from '../components/toasters';
|
||||
import { MlCapabilitiesProvider } from '../components/ml/permissions/ml_capabilities_provider';
|
||||
|
||||
import { ApolloClientContext } from '../utils/apollo_context';
|
||||
|
||||
interface AppPluginRootComponentProps {
|
||||
apolloClient: AppApolloClient;
|
||||
history: History;
|
||||
|
@ -46,13 +48,15 @@ const AppPluginRootComponent: React.FC<AppPluginRootComponentProps> = ({
|
|||
<ManageGlobalToaster>
|
||||
<ReduxStoreProvider store={store}>
|
||||
<ApolloProvider client={apolloClient}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<MlCapabilitiesProvider>
|
||||
<PageRouter history={history} />
|
||||
</MlCapabilitiesProvider>
|
||||
</ThemeProvider>
|
||||
<ErrorToastDispatcher />
|
||||
<GlobalToaster />
|
||||
<ApolloClientContext.Provider value={apolloClient}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<MlCapabilitiesProvider>
|
||||
<PageRouter history={history} />
|
||||
</MlCapabilitiesProvider>
|
||||
</ThemeProvider>
|
||||
<ErrorToastDispatcher />
|
||||
<GlobalToaster />
|
||||
</ApolloClientContext.Provider>
|
||||
</ApolloProvider>
|
||||
</ReduxStoreProvider>
|
||||
</ManageGlobalToaster>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { mount, shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
|
||||
import { mockBrowserFields, mocksSource } from '../../containers/source/mock';
|
||||
import { TestProviders } from '../../mock';
|
||||
|
@ -20,7 +20,7 @@ describe('DragDropContextWrapper', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<TestProviders>
|
||||
<MockedProvider mocks={[]} addTypename={false}>
|
||||
<MockedProvider mocks={{}} addTypename={false}>
|
||||
<DragDropContextWrapper browserFields={mockBrowserFields}>
|
||||
{message}
|
||||
</DragDropContextWrapper>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
|
||||
import { mockBrowserFields, mocksSource } from '../../containers/source/mock';
|
||||
import { TestProviders } from '../../mock';
|
||||
|
@ -24,7 +24,7 @@ describe('DraggableWrapper', () => {
|
|||
test('it renders against the snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<TestProviders>
|
||||
<MockedProvider mocks={[]} addTypename={false}>
|
||||
<MockedProvider mocks={{}} addTypename={false}>
|
||||
<DragDropContextWrapper browserFields={mockBrowserFields}>
|
||||
<DraggableWrapper dataProvider={dataProvider} render={() => message} />
|
||||
</DragDropContextWrapper>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
|
||||
import { mockBrowserFields, mocksSource } from '../../containers/source/mock';
|
||||
import { TestProviders } from '../../mock';
|
||||
|
@ -24,7 +24,7 @@ describe('DroppableWrapper', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<TestProviders>
|
||||
<MockedProvider mocks={[]} addTypename={false}>
|
||||
<MockedProvider mocks={{}} addTypename={false}>
|
||||
<DragDropContextWrapper browserFields={mockBrowserFields}>
|
||||
<DroppableWrapper droppableId="testing">{message}</DroppableWrapper>
|
||||
</DragDropContextWrapper>
|
||||
|
|
|
@ -20,7 +20,7 @@ import { Draggable } from 'react-beautiful-dnd';
|
|||
import styled from 'styled-components';
|
||||
|
||||
import { BrowserFields } from '../../containers/source';
|
||||
import { Scalars } from '../../graphql/types';
|
||||
import { ToStringArray } from '../../graphql/types';
|
||||
import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard';
|
||||
import { ColumnHeaderOptions } from '../../store/timeline/model';
|
||||
import { DragEffects } from '../drag_and_drop/draggable_wrapper';
|
||||
|
@ -159,7 +159,7 @@ export const getColumns = ({
|
|||
name: i18n.VALUE,
|
||||
sortable: true,
|
||||
truncateText: false,
|
||||
render: (values: Scalars['ToStringArray'] | null | undefined, data: EventFieldsData) => (
|
||||
render: (values: ToStringArray | null | undefined, data: EventFieldsData) => (
|
||||
<EuiFlexGroup direction="column" alignItems="flexStart" component="span" gutterSize="none">
|
||||
{values != null &&
|
||||
values.map((value, i) => (
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
DEFAULT_DATE_COLUMN_MIN_WIDTH,
|
||||
DEFAULT_COLUMN_MIN_WIDTH,
|
||||
} from '../timeline/body/constants';
|
||||
import { Scalars } from '../../graphql/types';
|
||||
import { ToStringArray } from '../../graphql/types';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
||||
|
@ -40,7 +40,7 @@ export interface Item {
|
|||
field: JSX.Element;
|
||||
fieldId: string;
|
||||
type: string;
|
||||
values: Scalars['ToStringArray'];
|
||||
values: ToStringArray;
|
||||
}
|
||||
|
||||
export const getColumnHeaderFromBrowserField = ({
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { act } from '@testing-library/react';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import useResizeObserver from 'use-resize-observer/polyfilled';
|
||||
|
||||
import { mockIndexPattern, TestProviders } from '../../mock';
|
||||
|
@ -53,7 +52,7 @@ describe('EventsViewer', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
|
@ -78,7 +77,7 @@ describe('EventsViewer', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
|
@ -103,7 +102,7 @@ describe('EventsViewer', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
|
@ -129,7 +128,7 @@ describe('EventsViewer', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
defaultHeaders.forEach(h =>
|
||||
|
|
|
@ -201,6 +201,7 @@ const EventsViewerComponent: React.FC<Props> = ({
|
|||
getUpdatedAt={getUpdatedAt}
|
||||
hasNextPage={getOr(false, 'hasNextPage', pageInfo)!}
|
||||
height={footerHeight}
|
||||
isEventViewer={true}
|
||||
isLive={isLive}
|
||||
isLoading={loading}
|
||||
itemsCount={events.length}
|
||||
|
@ -242,7 +243,7 @@ export const EventsViewer = React.memo(
|
|||
prevProps.kqlMode === nextProps.kqlMode &&
|
||||
deepEqual(prevProps.query, nextProps.query) &&
|
||||
prevProps.start === nextProps.start &&
|
||||
deepEqual(prevProps.sort, nextProps.sort) &&
|
||||
prevProps.sort === nextProps.sort &&
|
||||
deepEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) &&
|
||||
prevProps.utilityBar === nextProps.utilityBar
|
||||
);
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { act } from '@testing-library/react';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import useResizeObserver from 'use-resize-observer/polyfilled';
|
||||
|
||||
import { wait } from '../../lib/helpers';
|
||||
|
@ -52,7 +51,7 @@ describe('StatefulEventsViewer', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
|
@ -78,7 +77,7 @@ describe('StatefulEventsViewer', () => {
|
|||
</TestProviders>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find(`InspectButtonContainer`).exists()).toBe(true);
|
||||
|
|
|
@ -9,7 +9,6 @@ import { defaultTo, getOr } from 'lodash/fp';
|
|||
import React, { useCallback } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { State, timelineSelectors } from '../../store';
|
||||
import { DataProvider } from '../timeline/data_providers/data_provider';
|
||||
|
@ -91,17 +90,7 @@ export const FlyoutComponent = React.memo<Props>(
|
|||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) =>
|
||||
prevProps.children === nextProps.children &&
|
||||
deepEqual(prevProps.dataProviders, nextProps.dataProviders) &&
|
||||
prevProps.flyoutHeight === nextProps.flyoutHeight &&
|
||||
prevProps.headerHeight === nextProps.headerHeight &&
|
||||
prevProps.show === nextProps.show &&
|
||||
prevProps.showTimeline === nextProps.showTimeline &&
|
||||
prevProps.timelineId === nextProps.timelineId &&
|
||||
prevProps.usersViewing === nextProps.usersViewing &&
|
||||
prevProps.width === nextProps.width
|
||||
}
|
||||
);
|
||||
|
||||
FlyoutComponent.displayName = 'FlyoutComponent';
|
||||
|
|
|
@ -9,106 +9,11 @@ exports[`HeaderGlobal it renders 1`] = `
|
|||
justifyContent="spaceBetween"
|
||||
wrap={true}
|
||||
>
|
||||
<FlexItem>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
responsive={false}
|
||||
>
|
||||
<FlexItem
|
||||
grow={false}
|
||||
>
|
||||
<EuiLink
|
||||
href="#/link-to/overview"
|
||||
>
|
||||
<EuiIcon
|
||||
aria-label="SIEM"
|
||||
size="l"
|
||||
type="securityAnalyticsApp"
|
||||
/>
|
||||
</EuiLink>
|
||||
</FlexItem>
|
||||
<FlexItem
|
||||
component="nav"
|
||||
>
|
||||
<SiemNavigationContainer
|
||||
display="condensed"
|
||||
navTabs={
|
||||
Object {
|
||||
"case": Object {
|
||||
"disabled": false,
|
||||
"href": "#/link-to/case",
|
||||
"id": "case",
|
||||
"name": "Cases",
|
||||
"urlKey": "case",
|
||||
},
|
||||
"detections": Object {
|
||||
"disabled": false,
|
||||
"href": "#/link-to/detections",
|
||||
"id": "detections",
|
||||
"name": "Detections",
|
||||
"urlKey": "detections",
|
||||
},
|
||||
"hosts": Object {
|
||||
"disabled": false,
|
||||
"href": "#/link-to/hosts",
|
||||
"id": "hosts",
|
||||
"name": "Hosts",
|
||||
"urlKey": "host",
|
||||
},
|
||||
"network": Object {
|
||||
"disabled": false,
|
||||
"href": "#/link-to/network",
|
||||
"id": "network",
|
||||
"name": "Network",
|
||||
"urlKey": "network",
|
||||
},
|
||||
"overview": Object {
|
||||
"disabled": false,
|
||||
"href": "#/link-to/overview",
|
||||
"id": "overview",
|
||||
"name": "Overview",
|
||||
"urlKey": "overview",
|
||||
},
|
||||
"timelines": Object {
|
||||
"disabled": false,
|
||||
"href": "#/link-to/timelines",
|
||||
"id": "timelines",
|
||||
"name": "Timelines",
|
||||
"urlKey": "timeline",
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</FlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FlexItem>
|
||||
<FlexItem
|
||||
grow={false}
|
||||
<WithSource
|
||||
sourceId="default"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
gutterSize="s"
|
||||
responsive={false}
|
||||
wrap={true}
|
||||
>
|
||||
<FlexItem
|
||||
grow={false}
|
||||
>
|
||||
<MlPopover />
|
||||
</FlexItem>
|
||||
<FlexItem
|
||||
grow={false}
|
||||
>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="add-data"
|
||||
href="kibana#home/tutorial_directory/siem"
|
||||
iconType="plusInCircle"
|
||||
>
|
||||
Add data
|
||||
</EuiButtonEmpty>
|
||||
</FlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FlexItem>
|
||||
<Component />
|
||||
</WithSource>
|
||||
</EuiFlexGroup>
|
||||
</Wrapper>
|
||||
`;
|
||||
|
|
|
@ -17,15 +17,10 @@ jest.mock('ui/new_platform');
|
|||
jest.mock('../search_bar', () => ({
|
||||
SiemSearchBar: () => null,
|
||||
}));
|
||||
jest.mock('../../containers/source', () => ({
|
||||
useWithSource: () => ({
|
||||
contentAvailable: true,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('HeaderGlobal', () => {
|
||||
test('it renders', () => {
|
||||
const wrapper = shallow(<HeaderGlobal contentAvailable />);
|
||||
const wrapper = shallow(<HeaderGlobal />);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@ import { getOverviewUrl } from '../link_to';
|
|||
import { MlPopover } from '../ml_popover/ml_popover';
|
||||
import { SiemNavigation } from '../navigation';
|
||||
import * as i18n from './translations';
|
||||
import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source';
|
||||
|
||||
const Wrapper = styled.header`
|
||||
${({ theme }) => css`
|
||||
|
@ -33,64 +34,65 @@ const FlexItem = styled(EuiFlexItem)`
|
|||
FlexItem.displayName = 'FlexItem';
|
||||
|
||||
interface HeaderGlobalProps {
|
||||
contentAvailable: boolean;
|
||||
hideDetectionEngine?: boolean;
|
||||
}
|
||||
export const HeaderGlobal = React.memo<HeaderGlobalProps>(
|
||||
({ contentAvailable, hideDetectionEngine = false }) => (
|
||||
<Wrapper className="siemHeaderGlobal">
|
||||
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" wrap>
|
||||
<>
|
||||
<FlexItem>
|
||||
<EuiFlexGroup alignItems="center" responsive={false}>
|
||||
<FlexItem grow={false}>
|
||||
<EuiLink href={getOverviewUrl()}>
|
||||
<EuiIcon aria-label={i18n.SIEM} type="securityAnalyticsApp" size="l" />
|
||||
</EuiLink>
|
||||
</FlexItem>
|
||||
|
||||
<FlexItem component="nav">
|
||||
{contentAvailable ? (
|
||||
<SiemNavigation
|
||||
display="condensed"
|
||||
navTabs={
|
||||
hideDetectionEngine
|
||||
? pickBy((_, key) => key !== SiemPageName.detections, navTabs)
|
||||
: navTabs
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<SiemNavigation
|
||||
display="condensed"
|
||||
navTabs={pickBy((_, key) => key === SiemPageName.overview, navTabs)}
|
||||
/>
|
||||
)}
|
||||
</FlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FlexItem>
|
||||
|
||||
<FlexItem grow={false}>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false} wrap>
|
||||
{contentAvailable && (
|
||||
export const HeaderGlobal = React.memo<HeaderGlobalProps>(({ hideDetectionEngine = false }) => (
|
||||
<Wrapper className="siemHeaderGlobal">
|
||||
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" wrap>
|
||||
<WithSource sourceId="default">
|
||||
{({ indicesExist }) => (
|
||||
<>
|
||||
<FlexItem>
|
||||
<EuiFlexGroup alignItems="center" responsive={false}>
|
||||
<FlexItem grow={false}>
|
||||
<MlPopover />
|
||||
<EuiLink href={getOverviewUrl()}>
|
||||
<EuiIcon aria-label={i18n.SIEM} type="securityAnalyticsApp" size="l" />
|
||||
</EuiLink>
|
||||
</FlexItem>
|
||||
)}
|
||||
|
||||
<FlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="add-data"
|
||||
href="kibana#home/tutorial_directory/siem"
|
||||
iconType="plusInCircle"
|
||||
>
|
||||
{i18n.BUTTON_ADD_DATA}
|
||||
</EuiButtonEmpty>
|
||||
</FlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FlexItem>
|
||||
</>
|
||||
</EuiFlexGroup>
|
||||
</Wrapper>
|
||||
)
|
||||
);
|
||||
<FlexItem component="nav">
|
||||
{indicesExistOrDataTemporarilyUnavailable(indicesExist) ? (
|
||||
<SiemNavigation
|
||||
display="condensed"
|
||||
navTabs={
|
||||
hideDetectionEngine
|
||||
? pickBy((_, key) => key !== SiemPageName.detections, navTabs)
|
||||
: navTabs
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<SiemNavigation
|
||||
display="condensed"
|
||||
navTabs={pickBy((_, key) => key === SiemPageName.overview, navTabs)}
|
||||
/>
|
||||
)}
|
||||
</FlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FlexItem>
|
||||
|
||||
<FlexItem grow={false}>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false} wrap>
|
||||
{indicesExistOrDataTemporarilyUnavailable(indicesExist) && (
|
||||
<FlexItem grow={false}>
|
||||
<MlPopover />
|
||||
</FlexItem>
|
||||
)}
|
||||
|
||||
<FlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="add-data"
|
||||
href="kibana#home/tutorial_directory/siem"
|
||||
iconType="plusInCircle"
|
||||
>
|
||||
{i18n.BUTTON_ADD_DATA}
|
||||
</EuiButtonEmpty>
|
||||
</FlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FlexItem>
|
||||
</>
|
||||
)}
|
||||
</WithSource>
|
||||
</EuiFlexGroup>
|
||||
</Wrapper>
|
||||
));
|
||||
HeaderGlobal.displayName = 'HeaderGlobal';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ApolloClient } from '@apollo/client';
|
||||
import ApolloClient from 'apollo-client';
|
||||
import { getOr, set } from 'lodash/fp';
|
||||
import { Action } from 'typescript-fsa';
|
||||
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
|
||||
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
|
||||
import { mount } from 'enzyme';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { act } from '@testing-library/react';
|
||||
|
||||
import { wait } from '../../lib/helpers';
|
||||
import { TestProviderWithoutDragAndDrop } from '../../mock/test_providers';
|
||||
import { mockOpenTimelineQueryResults, MockedProvidedQuery } from '../../mock/timeline_results';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines';
|
||||
import { TestProviderWithoutDragAndDrop, apolloClient } from '../../mock/test_providers';
|
||||
import { mockOpenTimelineQueryResults } from '../../mock/timeline_results';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines/timelines_page';
|
||||
|
||||
import { StatefulOpenTimeline } from '.';
|
||||
import { NotePreviews } from './note_previews';
|
||||
|
@ -25,19 +24,15 @@ jest.mock('../../lib/kibana');
|
|||
describe('StatefulOpenTimeline', () => {
|
||||
const theme = () => ({ eui: euiDarkVars, darkMode: true });
|
||||
const title = 'All Timelines / Open Timelines';
|
||||
let mocks: MockedProvidedQuery[];
|
||||
|
||||
beforeEach(() => {
|
||||
mocks = mockOpenTimelineQueryResults;
|
||||
});
|
||||
|
||||
test('it has the expected initial state', () => {
|
||||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -66,13 +61,14 @@ describe('StatefulOpenTimeline', () => {
|
|||
});
|
||||
|
||||
describe('#onQueryChange', () => {
|
||||
test('it updates the query state with the expected trimmed value when the user enters a query', async () => {
|
||||
test('it updates the query state with the expected trimmed value when the user enters a query', () => {
|
||||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -81,11 +77,9 @@ describe('StatefulOpenTimeline', () => {
|
|||
</TestProviderWithoutDragAndDrop>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="search-bar"] input')
|
||||
.simulate('keyup', { keyCode: 13, target: { value: ' abcd ' } });
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('[data-test-subj="search-row"]')
|
||||
|
@ -98,8 +92,9 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -109,7 +104,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="search-bar"] input')
|
||||
|
@ -127,8 +122,9 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -138,7 +134,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="search-bar"] input')
|
||||
|
@ -158,8 +154,9 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -169,7 +166,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
|
@ -188,8 +185,9 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -199,7 +197,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('.euiCheckbox__input')
|
||||
|
@ -233,8 +231,9 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -244,7 +243,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('.euiCheckbox__input')
|
||||
|
@ -275,9 +274,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -287,7 +287,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('.euiCheckbox__input')
|
||||
|
@ -308,9 +308,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -346,9 +347,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -384,9 +386,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -396,7 +399,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
|
@ -420,11 +423,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
'10849df0-7b44-11e9-a608-ab3d811609': (
|
||||
<NotePreviews
|
||||
notes={
|
||||
mocks[0].result.data!.getAllTimeline.timeline[0].notes != null
|
||||
? mocks[0].result.data!.getAllTimeline.timeline[0].notes.map(note => ({
|
||||
...note,
|
||||
savedObjectId: note.noteId,
|
||||
}))
|
||||
mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].notes != null
|
||||
? mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].notes.map(
|
||||
note => ({ ...note, savedObjectId: note.noteId })
|
||||
)
|
||||
: []
|
||||
}
|
||||
/>
|
||||
|
@ -436,9 +438,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -448,7 +451,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper.update();
|
||||
|
||||
|
@ -471,9 +474,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -483,7 +487,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
|
@ -493,14 +497,15 @@ describe('StatefulOpenTimeline', () => {
|
|||
).toEqual(title);
|
||||
});
|
||||
|
||||
describe.skip('#resetSelectionState', () => {
|
||||
describe('#resetSelectionState', () => {
|
||||
test('when the user deletes selected timelines, resetSelectionState is invoked to clear the selection state', async () => {
|
||||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -514,7 +519,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
.find('[data-test-subj="open-timeline"]')
|
||||
.last()
|
||||
.prop('selectedItems');
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
expect(getSelectedItem().length).toEqual(0);
|
||||
wrapper
|
||||
.find('.euiCheckbox__input')
|
||||
|
@ -532,10 +537,11 @@ describe('StatefulOpenTimeline', () => {
|
|||
test('it renders the expected count of matching timelines when no query has been entered', async () => {
|
||||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -545,12 +551,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper.update();
|
||||
|
||||
await act(() => wait());
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('[data-test-subj="query-message"]')
|
||||
|
@ -566,9 +570,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -578,18 +583,21 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find(
|
||||
`[data-test-subj="title-${mocks[0].result.data!.getAllTimeline.timeline[0].savedObjectId}"]`
|
||||
`[data-test-subj="title-${
|
||||
mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].savedObjectId
|
||||
}"]`
|
||||
)
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(onOpenTimeline).toHaveBeenCalledWith({
|
||||
duplicate: false,
|
||||
timelineId: mocks[0].result.data!.getAllTimeline.timeline[0].savedObjectId,
|
||||
timelineId: mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0]
|
||||
.savedObjectId,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -600,9 +608,10 @@ describe('StatefulOpenTimeline', () => {
|
|||
const wrapper = mount(
|
||||
<ThemeProvider theme={theme}>
|
||||
<TestProviderWithoutDragAndDrop>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mockOpenTimelineQueryResults} addTypename={false}>
|
||||
<StatefulOpenTimeline
|
||||
data-test-subj="stateful-timeline"
|
||||
apolloClient={apolloClient}
|
||||
isModal={false}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
title={title}
|
||||
|
@ -612,7 +621,7 @@ describe('StatefulOpenTimeline', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="open-duplicate"]')
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import ApolloClient from 'apollo-client';
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
||||
|
@ -43,6 +43,7 @@ import {
|
|||
import { DEFAULT_SORT_FIELD, DEFAULT_SORT_DIRECTION } from './constants';
|
||||
|
||||
interface OwnProps<TCache = object> {
|
||||
apolloClient: ApolloClient<TCache>;
|
||||
/** Displays open timeline in modal */
|
||||
isModal: boolean;
|
||||
closeModalTimeline?: () => void;
|
||||
|
@ -67,6 +68,7 @@ export const getSelectedTimelineIds = (selectedItems: OpenTimelineResult[]): str
|
|||
/** Manages the state (e.g table selection) of the (pure) `OpenTimeline` component */
|
||||
export const StatefulOpenTimelineComponent = React.memo<OpenTimelineOwnProps>(
|
||||
({
|
||||
apolloClient,
|
||||
closeModalTimeline,
|
||||
createNewTimeline,
|
||||
defaultPageSize,
|
||||
|
@ -78,7 +80,6 @@ export const StatefulOpenTimelineComponent = React.memo<OpenTimelineOwnProps>(
|
|||
updateTimeline,
|
||||
updateIsLoading,
|
||||
}) => {
|
||||
const apolloClient = useApolloClient();
|
||||
/** Required by EuiTable for expandable rows: a map of `TimelineResult.savedObjectId` to rendered notes */
|
||||
const [itemIdToExpandedNotesRowMap, setItemIdToExpandedNotesRowMap] = useState<
|
||||
Record<string, JSX.Element>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines/timelines_page';
|
||||
import { OpenTimelineResult } from './types';
|
||||
import { TimelinesTableProps } from './timelines_table';
|
||||
import { mockTimelineResults } from '../../mock/timeline_results';
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { act } from '@testing-library/react';
|
||||
|
||||
import { wait } from '../../../lib/helpers';
|
||||
import { TestProviderWithoutDragAndDrop } from '../../../mock/test_providers';
|
||||
|
@ -18,6 +17,9 @@ import { mockOpenTimelineQueryResults } from '../../../mock/timeline_results';
|
|||
import { OpenTimelineModal } from '.';
|
||||
|
||||
jest.mock('../../../lib/kibana');
|
||||
jest.mock('../../../utils/apollo_context', () => ({
|
||||
useApolloClient: () => ({}),
|
||||
}));
|
||||
|
||||
describe('OpenTimelineModal', () => {
|
||||
const theme = () => ({ eui: euiDarkVars, darkMode: true });
|
||||
|
@ -33,7 +35,7 @@ describe('OpenTimelineModal', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper.update();
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import { EuiModal, EuiOverlayMask } from '@elastic/eui';
|
|||
import React from 'react';
|
||||
|
||||
import { TimelineModel } from '../../../store/timeline/model';
|
||||
import { useApolloClient } from '../../../utils/apollo_context';
|
||||
|
||||
import * as i18n from '../translations';
|
||||
import { ActionTimelineToShow } from '../types';
|
||||
|
@ -24,24 +25,31 @@ const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10;
|
|||
const OPEN_TIMELINE_MODAL_WIDTH = 1000; // px
|
||||
|
||||
export const OpenTimelineModal = React.memo<OpenTimelineModalProps>(
|
||||
({ hideActions = [], modalTitle, onClose, onOpen }) => (
|
||||
<EuiOverlayMask>
|
||||
<EuiModal
|
||||
data-test-subj="open-timeline-modal"
|
||||
maxWidth={OPEN_TIMELINE_MODAL_WIDTH}
|
||||
onClose={onClose}
|
||||
>
|
||||
<StatefulOpenTimeline
|
||||
closeModalTimeline={onClose}
|
||||
hideActions={hideActions}
|
||||
isModal={true}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
onOpenTimeline={onOpen}
|
||||
title={modalTitle ?? i18n.OPEN_TIMELINE_TITLE}
|
||||
/>
|
||||
</EuiModal>
|
||||
</EuiOverlayMask>
|
||||
)
|
||||
({ hideActions = [], modalTitle, onClose, onOpen }) => {
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
if (!apolloClient) return null;
|
||||
|
||||
return (
|
||||
<EuiOverlayMask>
|
||||
<EuiModal
|
||||
data-test-subj="open-timeline-modal"
|
||||
maxWidth={OPEN_TIMELINE_MODAL_WIDTH}
|
||||
onClose={onClose}
|
||||
>
|
||||
<StatefulOpenTimeline
|
||||
apolloClient={apolloClient}
|
||||
closeModalTimeline={onClose}
|
||||
hideActions={hideActions}
|
||||
isModal={true}
|
||||
defaultPageSize={DEFAULT_SEARCH_RESULTS_PER_PAGE}
|
||||
onOpenTimeline={onOpen}
|
||||
title={modalTitle ?? i18n.OPEN_TIMELINE_TITLE}
|
||||
/>
|
||||
</EuiModal>
|
||||
</EuiOverlayMask>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
OpenTimelineModal.displayName = 'OpenTimelineModal';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page';
|
||||
import { OpenTimelineResult } from '../types';
|
||||
import { TimelinesTableProps } from '../timelines_table';
|
||||
import { mockTimelineResults } from '../../../mock/timeline_results';
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { act } from '@testing-library/react';
|
||||
|
||||
import { wait } from '../../../lib/helpers';
|
||||
import { TestProviderWithoutDragAndDrop } from '../../../mock/test_providers';
|
||||
|
@ -30,7 +29,7 @@ describe('OpenTimelineModalButton', () => {
|
|||
</TestProviderWithoutDragAndDrop>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper.update();
|
||||
|
||||
|
@ -55,7 +54,7 @@ describe('OpenTimelineModalButton', () => {
|
|||
</ThemeProvider>
|
||||
);
|
||||
|
||||
await act(() => wait());
|
||||
await wait();
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="open-timeline-button"]')
|
||||
|
|
|
@ -11,7 +11,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page';
|
||||
import { mockTimelineResults } from '../../../mock/timeline_results';
|
||||
import { OpenTimelineResult } from '../types';
|
||||
import { TimelinesTable } from '.';
|
||||
|
|
|
@ -11,7 +11,7 @@ import React from 'react';
|
|||
import { ThemeProvider } from 'styled-components';
|
||||
import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page';
|
||||
import { getEmptyValue } from '../../empty_value';
|
||||
import { OpenTimelineResult } from '../types';
|
||||
import { mockTimelineResults } from '../../../mock/timeline_results';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page';
|
||||
import { getEmptyValue } from '../../empty_value';
|
||||
import { mockTimelineResults } from '../../../mock/timeline_results';
|
||||
import { OpenTimelineResult } from '../types';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page';
|
||||
import { mockTimelineResults } from '../../../mock/timeline_results';
|
||||
import { TimelinesTable } from '.';
|
||||
import { OpenTimelineResult } from '../types';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines';
|
||||
import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page';
|
||||
import { mockTimelineResults } from '../../../mock/timeline_results';
|
||||
import { OpenTimelineResult } from '../types';
|
||||
import { TimelinesTable, TimelinesTableProps } from '.';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { cloneDeep } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { render, act } from '@testing-library/react';
|
||||
|
||||
import { mockFirstLastSeenHostQuery } from '../../../../containers/hosts/first_last_seen/mock';
|
||||
|
@ -19,6 +19,16 @@ describe('FirstLastSeen Component', () => {
|
|||
const firstSeen = 'Apr 8, 2019 @ 16:09:40.692';
|
||||
const lastSeen = 'Apr 8, 2019 @ 18:35:45.064';
|
||||
|
||||
// Suppress warnings about "react-apollo" until we migrate to apollo@3
|
||||
/* eslint-disable no-console */
|
||||
const originalError = console.error;
|
||||
beforeAll(() => {
|
||||
console.error = jest.fn();
|
||||
});
|
||||
afterAll(() => {
|
||||
console.error = originalError;
|
||||
});
|
||||
|
||||
test('Loading', async () => {
|
||||
const { container } = render(
|
||||
<TestProviders>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { EuiIcon, EuiLoadingSpinner, EuiText, EuiToolTip } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { ApolloConsumer } from 'react-apollo';
|
||||
|
||||
import { useFirstLastSeenHostQuery } from '../../../../containers/hosts/first_last_seen';
|
||||
import { getEmptyTagValue } from '../../../empty_value';
|
||||
|
@ -18,37 +19,44 @@ export enum FirstLastSeenHostType {
|
|||
|
||||
export const FirstLastSeenHost = React.memo<{ hostname: string; type: FirstLastSeenHostType }>(
|
||||
({ hostname, type }) => {
|
||||
const { loading, firstSeen, lastSeen, errorMessage } = useFirstLastSeenHostQuery(
|
||||
hostname,
|
||||
'default'
|
||||
);
|
||||
if (errorMessage != null) {
|
||||
return (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
content={errorMessage}
|
||||
data-test-subj="firstLastSeenErrorToolTip"
|
||||
aria-label={`firstLastSeenError-${type}`}
|
||||
id={`firstLastSeenError-${hostname}-${type}`}
|
||||
>
|
||||
<EuiIcon aria-describedby={`firstLastSeenError-${hostname}-${type}`} type="alert" />
|
||||
</EuiToolTip>
|
||||
);
|
||||
}
|
||||
const valueSeen = type === FirstLastSeenHostType.FIRST_SEEN ? firstSeen : lastSeen;
|
||||
return (
|
||||
<>
|
||||
{loading && <EuiLoadingSpinner size="m" />}
|
||||
{!loading && valueSeen != null && new Date(valueSeen).toString() === 'Invalid Date'
|
||||
? valueSeen
|
||||
: !loading &&
|
||||
valueSeen != null && (
|
||||
<EuiText size="s">
|
||||
<FormattedRelativePreferenceDate value={`${valueSeen}`} />
|
||||
</EuiText>
|
||||
)}
|
||||
{!loading && valueSeen == null && getEmptyTagValue()}
|
||||
</>
|
||||
<ApolloConsumer>
|
||||
{client => {
|
||||
const { loading, firstSeen, lastSeen, errorMessage } = useFirstLastSeenHostQuery(
|
||||
hostname,
|
||||
'default',
|
||||
client
|
||||
);
|
||||
if (errorMessage != null) {
|
||||
return (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
content={errorMessage}
|
||||
data-test-subj="firstLastSeenErrorToolTip"
|
||||
aria-label={`firstLastSeenError-${type}`}
|
||||
id={`firstLastSeenError-${hostname}-${type}`}
|
||||
>
|
||||
<EuiIcon aria-describedby={`firstLastSeenError-${hostname}-${type}`} type="alert" />
|
||||
</EuiToolTip>
|
||||
);
|
||||
}
|
||||
const valueSeen = type === FirstLastSeenHostType.FIRST_SEEN ? firstSeen : lastSeen;
|
||||
return (
|
||||
<>
|
||||
{loading && <EuiLoadingSpinner size="m" />}
|
||||
{!loading && valueSeen != null && new Date(valueSeen).toString() === 'Invalid Date'
|
||||
? valueSeen
|
||||
: !loading &&
|
||||
valueSeen != null && (
|
||||
<EuiText size="s">
|
||||
<FormattedRelativePreferenceDate value={`${valueSeen}`} />
|
||||
</EuiText>
|
||||
)}
|
||||
{!loading && valueSeen == null && getEmptyTagValue()}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</ApolloConsumer>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -68,6 +68,97 @@ exports[`Hosts Table rendering it renders the default Hosts table 1`] = `
|
|||
}
|
||||
fakeTotalCount={50}
|
||||
id="hostsQuery"
|
||||
indexPattern={
|
||||
Object {
|
||||
"fields": Array [
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "@timestamp",
|
||||
"searchable": true,
|
||||
"type": "date",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "@version",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.ephemeral_id",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.hostname",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.id",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test1",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test2",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test3",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test4",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test5",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test6",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test7",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "agent.test8",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
Object {
|
||||
"aggregatable": true,
|
||||
"name": "host.name",
|
||||
"searchable": true,
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"title": "filebeat-*,auditbeat-*,packetbeat-*",
|
||||
}
|
||||
}
|
||||
isInspect={false}
|
||||
loadPage={[MockFunction]}
|
||||
loading={false}
|
||||
|
|
|
@ -7,9 +7,14 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
|
||||
import {
|
||||
apolloClientObservable,
|
||||
mockIndexPattern,
|
||||
mockGlobalState,
|
||||
TestProviders,
|
||||
} from '../../../../mock';
|
||||
import { useMountAppended } from '../../../../utils/use_mount_appended';
|
||||
import { createStore, hostsModel, State } from '../../../../store';
|
||||
import { HostsTableType } from '../../../../store/hosts/model';
|
||||
|
@ -44,6 +49,7 @@ describe('Hosts Table', () => {
|
|||
data={mockData.Hosts.edges}
|
||||
id="hostsQuery"
|
||||
isInspect={false}
|
||||
indexPattern={mockIndexPattern}
|
||||
fakeTotalCount={getOr(50, 'fakeTotalCount', mockData.Hosts.pageInfo)}
|
||||
loading={false}
|
||||
loadPage={loadPage}
|
||||
|
@ -66,6 +72,7 @@ describe('Hosts Table', () => {
|
|||
<TestProviders store={store}>
|
||||
<HostsTable
|
||||
id="hostsQuery"
|
||||
indexPattern={mockIndexPattern}
|
||||
isInspect={false}
|
||||
loading={false}
|
||||
data={mockData.Hosts.edges}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import { IIndexPattern } from 'src/plugins/data/public';
|
||||
|
||||
import { hostsActions } from '../../../../store/actions';
|
||||
import {
|
||||
Direction,
|
||||
|
@ -35,6 +37,7 @@ interface OwnProps {
|
|||
data: HostsEdges[];
|
||||
fakeTotalCount: number;
|
||||
id: string;
|
||||
indexPattern: IIndexPattern;
|
||||
isInspect: boolean;
|
||||
loading: boolean;
|
||||
loadPage: (newActivePage: number) => void;
|
||||
|
@ -75,6 +78,7 @@ const HostsTableComponent = React.memo<HostsTableProps>(
|
|||
direction,
|
||||
fakeTotalCount,
|
||||
id,
|
||||
indexPattern,
|
||||
isInspect,
|
||||
limit,
|
||||
loading,
|
||||
|
|
|
@ -33,7 +33,9 @@ interface KpiHostDetailsProps extends GenericKpiHostProps {
|
|||
}
|
||||
|
||||
const FlexGroupSpinner = styled(EuiFlexGroup)`
|
||||
min-height: ${kpiWidgetHeight}px;
|
||||
{
|
||||
min-height: ${kpiWidgetHeight}px;
|
||||
}
|
||||
`;
|
||||
|
||||
FlexGroupSpinner.displayName = 'FlexGroupSpinner';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { FlowTargetSourceDest } from '../../../../graphql/types';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { FlowTargetSourceDest } from '../../../../graphql/types';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
|
||||
import { FlowTarget } from '../../../../graphql/types';
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
import { cloneDeep } from 'lodash/fp';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedResponse, MockedProvider } from '@apollo/client/testing';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
|
||||
|
||||
import { OverviewHost } from '.';
|
||||
import { createStore, State } from '../../../../store';
|
||||
import { overviewHostQuery } from '../../../../containers/overview/overview_host/index.gql_query';
|
||||
import { GetOverviewHostQuery } from '../../../../graphql/types';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { wait } from '../../../../lib/helpers';
|
||||
|
||||
jest.mock('../../../../lib/kibana');
|
||||
|
@ -21,7 +22,12 @@ jest.mock('../../../../lib/kibana');
|
|||
const startDate = 1579553397080;
|
||||
const endDate = 1579639797080;
|
||||
|
||||
interface MockedProvidedQuery extends MockedResponse {
|
||||
interface MockedProvidedQuery {
|
||||
request: {
|
||||
query: GetOverviewHostQuery.Query;
|
||||
fetchPolicy: string;
|
||||
variables: GetOverviewHostQuery.Variables;
|
||||
};
|
||||
result: {
|
||||
data: {
|
||||
source: unknown;
|
||||
|
@ -33,6 +39,7 @@ const mockOpenTimelineQueryResults: MockedProvidedQuery[] = [
|
|||
{
|
||||
request: {
|
||||
query: overviewHostQuery,
|
||||
fetchPolicy: 'cache-and-network',
|
||||
variables: {
|
||||
sourceId: 'default',
|
||||
timerange: { interval: '12h', from: startDate, to: endDate },
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
import { cloneDeep } from 'lodash/fp';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
||||
|
||||
import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
|
||||
|
||||
import { OverviewNetwork } from '.';
|
||||
import { createStore, State } from '../../../../store';
|
||||
import { overviewNetworkQuery } from '../../../../containers/overview/overview_network/index.gql_query';
|
||||
import { GetOverviewHostQuery } from '../../../../graphql/types';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import { wait } from '../../../../lib/helpers';
|
||||
|
||||
jest.mock('../../../../lib/kibana');
|
||||
|
@ -21,7 +22,12 @@ jest.mock('../../../../lib/kibana');
|
|||
const startDate = 1579553397080;
|
||||
const endDate = 1579639797080;
|
||||
|
||||
interface MockedProvidedQuery extends MockedResponse {
|
||||
interface MockedProvidedQuery {
|
||||
request: {
|
||||
query: GetOverviewHostQuery.Query;
|
||||
fetchPolicy: string;
|
||||
variables: GetOverviewHostQuery.Variables;
|
||||
};
|
||||
result: {
|
||||
data: {
|
||||
source: unknown;
|
||||
|
@ -33,6 +39,7 @@ const mockOpenTimelineQueryResults: MockedProvidedQuery[] = [
|
|||
{
|
||||
request: {
|
||||
query: overviewNetworkQuery,
|
||||
fetchPolicy: 'cache-and-network',
|
||||
variables: {
|
||||
sourceId: 'default',
|
||||
timerange: { interval: '12h', from: startDate, to: endDate },
|
||||
|
|
|
@ -50,9 +50,6 @@ const OverviewNetworkComponent: React.FC<OverviewNetworkProps> = ({
|
|||
setQuery,
|
||||
}) => {
|
||||
const [defaultNumberFormat] = useUiSetting$<string>(DEFAULT_NUMBER_FORMAT);
|
||||
const title = (
|
||||
<FormattedMessage id="xpack.siem.overview.networkTitle" defaultMessage="Network events" />
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFlexItem>
|
||||
|
@ -92,7 +89,12 @@ const OverviewNetworkComponent: React.FC<OverviewNetworkProps> = ({
|
|||
<>{''}</>
|
||||
)
|
||||
}
|
||||
title={title}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.siem.overview.networkTitle"
|
||||
defaultMessage="Network events"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiButton href={getNetworkUrl()}>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import ApolloClient from 'apollo-client';
|
||||
import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui';
|
||||
import React, { useCallback } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
@ -27,14 +27,14 @@ export interface MeApiResponse {
|
|||
}
|
||||
|
||||
interface OwnProps {
|
||||
apolloClient: ApolloClient<{}>;
|
||||
filterBy: FilterMode;
|
||||
}
|
||||
|
||||
export type Props = OwnProps & PropsFromRedux;
|
||||
|
||||
const StatefulRecentTimelinesComponent = React.memo<Props>(
|
||||
({ filterBy, updateIsLoading, updateTimeline }) => {
|
||||
const apolloClient = useApolloClient();
|
||||
({ apolloClient, filterBy, updateIsLoading, updateTimeline }) => {
|
||||
const actionDispatcher = updateIsLoading as ActionCreator<{ id: string; isLoading: boolean }>;
|
||||
const onOpenTimeline: OnOpenTimeline = useCallback(
|
||||
({ duplicate, timelineId }: { duplicate: boolean; timelineId: string }) => {
|
||||
|
|
|
@ -372,7 +372,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
dispatch(inputsActions.setSearchBarFilter({ id, filters })),
|
||||
});
|
||||
|
||||
const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
export const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
|
||||
type PropsFromRedux = ConnectedProps<typeof connector>;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { get, getOr } from 'lodash/fp';
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { KpiHostsData, KpiHostDetailsData, KpiNetworkData } from '../../graphql/types';
|
||||
import { KpiHostsData, KpiNetworkData } from '../../graphql/types';
|
||||
import { AreaChart } from '../charts/areachart';
|
||||
import { BarChart } from '../charts/barchart';
|
||||
import { ChartSeriesData, ChartData, ChartSeriesConfigs, UpdateDateRange } from '../charts/common';
|
||||
|
@ -112,12 +112,12 @@ export const barchartConfigs = (config?: { onElementClick?: ElementClickListener
|
|||
|
||||
export const addValueToFields = (
|
||||
fields: StatItem[],
|
||||
data: KpiHostsData | KpiHostDetailsData | KpiNetworkData
|
||||
data: KpiHostsData | KpiNetworkData
|
||||
): StatItem[] => fields.map(field => ({ ...field, value: get(field.key, data) }));
|
||||
|
||||
export const addValueToAreaChart = (
|
||||
fields: StatItem[],
|
||||
data: KpiHostsData | KpiHostDetailsData | KpiNetworkData
|
||||
data: KpiHostsData | KpiNetworkData
|
||||
): ChartSeriesData[] =>
|
||||
fields
|
||||
.filter(field => get(`${field.key}Histogram`, data) != null)
|
||||
|
@ -129,7 +129,7 @@ export const addValueToAreaChart = (
|
|||
|
||||
export const addValueToBarChart = (
|
||||
fields: StatItem[],
|
||||
data: KpiHostsData | KpiHostDetailsData | KpiNetworkData
|
||||
data: KpiHostsData | KpiNetworkData
|
||||
): ChartSeriesData[] => {
|
||||
if (fields.length === 0) return [];
|
||||
return fields.reduce((acc: ChartSeriesData[], field: StatItem, idx: number) => {
|
||||
|
@ -158,7 +158,7 @@ export const addValueToBarChart = (
|
|||
|
||||
export const useKpiMatrixStatus = (
|
||||
mappings: Readonly<StatItems[]>,
|
||||
data: KpiHostsData | KpiHostDetailsData | KpiNetworkData,
|
||||
data: KpiHostsData | KpiNetworkData,
|
||||
id: string,
|
||||
from: number,
|
||||
to: number,
|
||||
|
|
|
@ -306,7 +306,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
updateReduxTime: dispatchUpdateReduxTime(dispatch),
|
||||
});
|
||||
|
||||
const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
export const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
|
||||
type PropsFromRedux = ConnectedProps<typeof connector>;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import { eventHasNotes, eventIsPinned, getPinTooltip, stringifyEvent } from './h
|
|||
describe('helpers', () => {
|
||||
describe('stringifyEvent', () => {
|
||||
test('it omits __typename when it appears at arbitrary levels', () => {
|
||||
const toStringify: Ecs = ({
|
||||
const toStringify: Ecs = {
|
||||
__typename: 'level 0',
|
||||
_id: '4',
|
||||
timestamp: '2018-11-08T19:03:25.937Z',
|
||||
|
@ -54,7 +54,7 @@ describe('helpers', () => {
|
|||
region_name: ['neither'],
|
||||
country_iso_code: ['sasquatch'],
|
||||
},
|
||||
} as unknown) as Ecs; // as cast so that `__typename` can be added for the tests even though it is not part of ECS
|
||||
} as Ecs; // as cast so that `__typename` can be added for the tests even though it is not part of ECS
|
||||
const expected: Ecs = {
|
||||
_id: '4',
|
||||
timestamp: '2018-11-08T19:03:25.937Z',
|
||||
|
|
|
@ -8,7 +8,6 @@ import { noop } from 'lodash/fp';
|
|||
import memoizeOne from 'memoize-one';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { BrowserFields } from '../../../containers/source';
|
||||
import { TimelineItem } from '../../../graphql/types';
|
||||
|
@ -194,7 +193,7 @@ const StatefulBodyComponent = React.memo<StatefulBodyComponentProps>(
|
|||
return (
|
||||
prevProps.browserFields === nextProps.browserFields &&
|
||||
prevProps.columnHeaders === nextProps.columnHeaders &&
|
||||
deepEqual(prevProps.data, nextProps.data) &&
|
||||
prevProps.data === nextProps.data &&
|
||||
prevProps.eventIdToNoteIds === nextProps.eventIdToNoteIds &&
|
||||
prevProps.notesById === nextProps.notesById &&
|
||||
prevProps.height === nextProps.height &&
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import { memo, useEffect } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import { IIndexPattern } from 'src/plugins/data/public';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { timelineSelectors, State } from '../../store';
|
||||
import { inputsActions } from '../../store/actions';
|
||||
|
@ -40,14 +39,7 @@ const TimelineKqlFetchComponent = memo<OwnProps>(
|
|||
});
|
||||
}, [kueryFilterQueryDraft, kueryFilterQuery, id]);
|
||||
return null;
|
||||
},
|
||||
(prevProps, nextProps) =>
|
||||
prevProps.id === nextProps.id &&
|
||||
deepEqual(prevProps.indexPattern, nextProps.indexPattern) &&
|
||||
prevProps.inputId === nextProps.inputId &&
|
||||
prevProps.kueryFilterQuery === nextProps.kueryFilterQuery &&
|
||||
prevProps.kueryFilterQueryDraft === nextProps.kueryFilterQueryDraft &&
|
||||
prevProps.setTimelineQuery === nextProps.setTimelineQuery
|
||||
}
|
||||
);
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
|
@ -66,7 +58,7 @@ const mapDispatchToProps = {
|
|||
setTimelineQuery: inputsActions.setQuery,
|
||||
};
|
||||
|
||||
const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
export const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
|
||||
type PropsFromRedux = ConnectedProps<typeof connector>;
|
||||
|
||||
|
|
|
@ -177,6 +177,7 @@ interface FooterProps {
|
|||
getUpdatedAt: () => number;
|
||||
hasNextPage: boolean;
|
||||
height: number;
|
||||
isEventViewer?: boolean;
|
||||
isLive: boolean;
|
||||
isLoading: boolean;
|
||||
itemsCount: number;
|
||||
|
@ -195,6 +196,7 @@ export const FooterComponent = ({
|
|||
getUpdatedAt,
|
||||
hasNextPage,
|
||||
height,
|
||||
isEventViewer,
|
||||
isLive,
|
||||
isLoading,
|
||||
itemsCount,
|
||||
|
@ -343,6 +345,7 @@ export const Footer = React.memo(
|
|||
prevProps.compact === nextProps.compact &&
|
||||
prevProps.hasNextPage === nextProps.hasNextPage &&
|
||||
prevProps.height === nextProps.height &&
|
||||
prevProps.isEventViewer === nextProps.isEventViewer &&
|
||||
prevProps.isLive === nextProps.isLive &&
|
||||
prevProps.isLoading === nextProps.isLoading &&
|
||||
prevProps.itemsCount === nextProps.itemsCount &&
|
||||
|
|
|
@ -8,7 +8,6 @@ import { EuiCallOut } from '@elastic/eui';
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { IIndexPattern } from 'src/plugins/data/public';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { Sort } from '../body/sort';
|
||||
import { DataProviders } from '../data_providers';
|
||||
|
@ -92,19 +91,4 @@ export const TimelineHeaderComponent: React.FC<Props> = ({
|
|||
</TimelineHeaderContainer>
|
||||
);
|
||||
|
||||
export const TimelineHeader = React.memo(
|
||||
TimelineHeaderComponent,
|
||||
(prevProps, nextProps) =>
|
||||
deepEqual(prevProps.browserFields, nextProps.browserFields) &&
|
||||
prevProps.id === nextProps.id &&
|
||||
deepEqual(prevProps.indexPattern, nextProps.indexPattern) &&
|
||||
deepEqual(prevProps.dataProviders, nextProps.dataProviders) &&
|
||||
prevProps.onChangeDataProviderKqlQuery === nextProps.onChangeDataProviderKqlQuery &&
|
||||
prevProps.onChangeDroppableAndProvider === nextProps.onChangeDroppableAndProvider &&
|
||||
prevProps.onDataProviderEdited === nextProps.onDataProviderEdited &&
|
||||
prevProps.onDataProviderRemoved === nextProps.onDataProviderRemoved &&
|
||||
prevProps.onToggleDataProviderEnabled === nextProps.onToggleDataProviderEnabled &&
|
||||
prevProps.onToggleDataProviderExcluded === nextProps.onToggleDataProviderExcluded &&
|
||||
prevProps.show === nextProps.show &&
|
||||
prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg
|
||||
);
|
||||
export const TimelineHeader = React.memo(TimelineHeaderComponent);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { isEmpty, isNumber, get } from 'lodash/fp';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { escapeQueryValue, convertToBuildEsQuery } from '../../lib/keury';
|
||||
|
||||
|
@ -94,68 +93,65 @@ export const buildGlobalQuery = (dataProviders: DataProvider[], browserFields: B
|
|||
}, '')
|
||||
.trim();
|
||||
|
||||
export const combineQueries = memoizeOne(
|
||||
({
|
||||
config,
|
||||
dataProviders,
|
||||
indexPattern,
|
||||
browserFields,
|
||||
filters = [],
|
||||
kqlQuery,
|
||||
kqlMode,
|
||||
start,
|
||||
end,
|
||||
isEventViewer,
|
||||
}: {
|
||||
config: EsQueryConfig;
|
||||
dataProviders: DataProvider[];
|
||||
indexPattern: IIndexPattern;
|
||||
browserFields: BrowserFields;
|
||||
filters: Filter[];
|
||||
kqlQuery: Query;
|
||||
kqlMode: string;
|
||||
start: number;
|
||||
end: number;
|
||||
isEventViewer?: boolean;
|
||||
}): { filterQuery: string } | null => {
|
||||
const kuery: Query = { query: '', language: kqlQuery.language };
|
||||
if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEmpty(filters) && !isEventViewer) {
|
||||
return null;
|
||||
} else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEventViewer) {
|
||||
kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
} else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && !isEmpty(filters)) {
|
||||
kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
} else if (isEmpty(dataProviders) && !isEmpty(kqlQuery.query)) {
|
||||
kuery.query = `(${kqlQuery.query}) and @timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
} else if (!isEmpty(dataProviders) && isEmpty(kqlQuery)) {
|
||||
kuery.query = `(${buildGlobalQuery(
|
||||
dataProviders,
|
||||
browserFields
|
||||
)}) and @timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
}
|
||||
const operatorKqlQuery = kqlMode === 'filter' ? 'and' : 'or';
|
||||
const postpend = (q: string) => `${!isEmpty(q) ? ` ${operatorKqlQuery} (${q})` : ''}`;
|
||||
kuery.query = `((${buildGlobalQuery(dataProviders, browserFields)})${postpend(
|
||||
kqlQuery.query as string
|
||||
export const combineQueries = ({
|
||||
config,
|
||||
dataProviders,
|
||||
indexPattern,
|
||||
browserFields,
|
||||
filters = [],
|
||||
kqlQuery,
|
||||
kqlMode,
|
||||
start,
|
||||
end,
|
||||
isEventViewer,
|
||||
}: {
|
||||
config: EsQueryConfig;
|
||||
dataProviders: DataProvider[];
|
||||
indexPattern: IIndexPattern;
|
||||
browserFields: BrowserFields;
|
||||
filters: Filter[];
|
||||
kqlQuery: Query;
|
||||
kqlMode: string;
|
||||
start: number;
|
||||
end: number;
|
||||
isEventViewer?: boolean;
|
||||
}): { filterQuery: string } | null => {
|
||||
const kuery: Query = { query: '', language: kqlQuery.language };
|
||||
if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEmpty(filters) && !isEventViewer) {
|
||||
return null;
|
||||
} else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEventViewer) {
|
||||
kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
} else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && !isEmpty(filters)) {
|
||||
kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
} else if (isEmpty(dataProviders) && !isEmpty(kqlQuery.query)) {
|
||||
kuery.query = `(${kqlQuery.query}) and @timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
} else if (!isEmpty(dataProviders) && isEmpty(kqlQuery)) {
|
||||
kuery.query = `(${buildGlobalQuery(
|
||||
dataProviders,
|
||||
browserFields
|
||||
)}) and @timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
},
|
||||
deepEqual
|
||||
);
|
||||
}
|
||||
const operatorKqlQuery = kqlMode === 'filter' ? 'and' : 'or';
|
||||
const postpend = (q: string) => `${!isEmpty(q) ? ` ${operatorKqlQuery} (${q})` : ''}`;
|
||||
kuery.query = `((${buildGlobalQuery(dataProviders, browserFields)})${postpend(
|
||||
kqlQuery.query as string
|
||||
)}) and @timestamp >= ${start} and @timestamp <= ${end}`;
|
||||
return {
|
||||
filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }),
|
||||
};
|
||||
};
|
||||
|
||||
interface CalculateBodyHeightParams {
|
||||
/** The the height of the flyout container, which is typically the entire "page", not including the standard Kibana navigation */
|
||||
|
@ -168,15 +164,13 @@ interface CalculateBodyHeightParams {
|
|||
timelineFooterHeight?: number;
|
||||
}
|
||||
|
||||
export const calculateBodyHeight = memoizeOne(
|
||||
({
|
||||
flyoutHeight = 0,
|
||||
flyoutHeaderHeight = 0,
|
||||
timelineHeaderHeight = 0,
|
||||
timelineFooterHeight = 0,
|
||||
}: CalculateBodyHeightParams): number =>
|
||||
flyoutHeight - (flyoutHeaderHeight + timelineHeaderHeight + timelineFooterHeight)
|
||||
);
|
||||
export const calculateBodyHeight = ({
|
||||
flyoutHeight = 0,
|
||||
flyoutHeaderHeight = 0,
|
||||
timelineHeaderHeight = 0,
|
||||
timelineFooterHeight = 0,
|
||||
}: CalculateBodyHeightParams): number =>
|
||||
flyoutHeight - (flyoutHeaderHeight + timelineHeaderHeight + timelineFooterHeight);
|
||||
|
||||
/**
|
||||
* The CSS class name of a "stateful event", which appears in both
|
||||
|
|
|
@ -8,7 +8,7 @@ import React, { useEffect, useCallback, useMemo } from 'react';
|
|||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { useWithSource } from '../../containers/source';
|
||||
import { WithSource } from '../../containers/source';
|
||||
import { useSignalIndex } from '../../containers/detection_engine/signals/use_signal_index';
|
||||
import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store';
|
||||
import { timelineActions } from '../../store/actions';
|
||||
|
@ -34,8 +34,6 @@ export interface OwnProps {
|
|||
|
||||
type Props = OwnProps & PropsFromRedux;
|
||||
|
||||
const EMPTY_INDEX_TO_ADD: string[] = [];
|
||||
|
||||
const StatefulTimelineComponent = React.memo<Props>(
|
||||
({
|
||||
columns,
|
||||
|
@ -77,7 +75,7 @@ const StatefulTimelineComponent = React.memo<Props>(
|
|||
) {
|
||||
return [signalIndexName];
|
||||
}
|
||||
return EMPTY_INDEX_TO_ADD;
|
||||
return [];
|
||||
}, [eventType, signalIndexExists, signalIndexName]);
|
||||
|
||||
const onDataProviderRemoved: OnDataProviderRemoved = useCallback(
|
||||
|
@ -165,40 +163,42 @@ const StatefulTimelineComponent = React.memo<Props>(
|
|||
}
|
||||
}, []);
|
||||
|
||||
const { indexPattern, browserFields } = useWithSource(indexToAdd);
|
||||
|
||||
return (
|
||||
<Timeline
|
||||
browserFields={browserFields}
|
||||
columns={columns}
|
||||
dataProviders={dataProviders!}
|
||||
end={end}
|
||||
eventType={eventType}
|
||||
filters={filters}
|
||||
flyoutHeaderHeight={flyoutHeaderHeight}
|
||||
flyoutHeight={flyoutHeight}
|
||||
id={id}
|
||||
indexPattern={indexPattern}
|
||||
indexToAdd={indexToAdd}
|
||||
isLive={isLive}
|
||||
itemsPerPage={itemsPerPage!}
|
||||
itemsPerPageOptions={itemsPerPageOptions!}
|
||||
kqlMode={kqlMode}
|
||||
kqlQueryExpression={kqlQueryExpression}
|
||||
loadingIndexName={loading}
|
||||
onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery}
|
||||
onChangeDroppableAndProvider={onChangeDroppableAndProvider}
|
||||
onChangeItemsPerPage={onChangeItemsPerPage}
|
||||
onDataProviderEdited={onDataProviderEditedLocal}
|
||||
onDataProviderRemoved={onDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={onToggleDataProviderEnabled}
|
||||
onToggleDataProviderExcluded={onToggleDataProviderExcluded}
|
||||
show={show!}
|
||||
showCallOutUnauthorizedMsg={showCallOutUnauthorizedMsg}
|
||||
sort={sort!}
|
||||
start={start}
|
||||
toggleColumn={toggleColumn}
|
||||
/>
|
||||
<WithSource sourceId="default" indexToAdd={indexToAdd}>
|
||||
{({ indexPattern, browserFields }) => (
|
||||
<Timeline
|
||||
browserFields={browserFields}
|
||||
columns={columns}
|
||||
dataProviders={dataProviders!}
|
||||
end={end}
|
||||
eventType={eventType}
|
||||
filters={filters}
|
||||
flyoutHeaderHeight={flyoutHeaderHeight}
|
||||
flyoutHeight={flyoutHeight}
|
||||
id={id}
|
||||
indexPattern={indexPattern}
|
||||
indexToAdd={indexToAdd}
|
||||
isLive={isLive}
|
||||
itemsPerPage={itemsPerPage!}
|
||||
itemsPerPageOptions={itemsPerPageOptions!}
|
||||
kqlMode={kqlMode}
|
||||
kqlQueryExpression={kqlQueryExpression}
|
||||
loadingIndexName={loading}
|
||||
onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery}
|
||||
onChangeDroppableAndProvider={onChangeDroppableAndProvider}
|
||||
onChangeItemsPerPage={onChangeItemsPerPage}
|
||||
onDataProviderEdited={onDataProviderEditedLocal}
|
||||
onDataProviderRemoved={onDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={onToggleDataProviderEnabled}
|
||||
onToggleDataProviderExcluded={onToggleDataProviderExcluded}
|
||||
show={show!}
|
||||
showCallOutUnauthorizedMsg={showCallOutUnauthorizedMsg}
|
||||
sort={sort!}
|
||||
start={start}
|
||||
toggleColumn={toggleColumn}
|
||||
/>
|
||||
)}
|
||||
</WithSource>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) => {
|
||||
|
|
|
@ -228,7 +228,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
updateReduxTime: dispatchUpdateReduxTime(dispatch),
|
||||
});
|
||||
|
||||
const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
export const connector = connect(makeMapStateToProps, mapDispatchToProps);
|
||||
|
||||
type PropsFromRedux = ConnectedProps<typeof connector>;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MockedProvider } from 'react-apollo/test-utils';
|
||||
import useResizeObserver from 'use-resize-observer/polyfilled';
|
||||
|
||||
import { timelineQuery } from '../../containers/timeline/index.gql_query';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { EuiFlexGroup } from '@elastic/eui';
|
||||
import { getOr, isEmpty } from 'lodash/fp';
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import useResizeObserver from 'use-resize-observer/polyfilled';
|
||||
|
||||
|
@ -121,12 +121,6 @@ export const TimelineComponent: React.FC<Props> = ({
|
|||
const { ref: measureRef, width = 0, height: timelineHeaderHeight = 0 } = useResizeObserver<
|
||||
HTMLDivElement
|
||||
>({});
|
||||
const bodyHeight = calculateBodyHeight({
|
||||
flyoutHeight,
|
||||
flyoutHeaderHeight,
|
||||
timelineHeaderHeight,
|
||||
timelineFooterHeight: footerHeight,
|
||||
});
|
||||
const kibana = useKibana();
|
||||
const combinedQueries = combineQueries({
|
||||
config: esQuery.getEsQueryConfig(kibana.services.uiSettings),
|
||||
|
@ -139,14 +133,7 @@ export const TimelineComponent: React.FC<Props> = ({
|
|||
start,
|
||||
end,
|
||||
});
|
||||
const sortField = {
|
||||
sortFieldId: sort.columnId,
|
||||
direction: sort.sortDirection as Direction,
|
||||
};
|
||||
const timelineQueryFields = useMemo(() => {
|
||||
const columnsHeader = isEmpty(columns) ? defaultHeaders : columns;
|
||||
return columnsHeader.map(c => c.id);
|
||||
}, [columns]);
|
||||
const columnsHeader = isEmpty(columns) ? defaultHeaders : columns;
|
||||
|
||||
return (
|
||||
<TimelineContainer
|
||||
|
@ -178,11 +165,14 @@ export const TimelineComponent: React.FC<Props> = ({
|
|||
eventType={eventType}
|
||||
id={id}
|
||||
indexToAdd={indexToAdd}
|
||||
fields={timelineQueryFields}
|
||||
fields={columnsHeader.map(c => c.id)}
|
||||
sourceId="default"
|
||||
limit={itemsPerPage}
|
||||
filterQuery={combinedQueries.filterQuery}
|
||||
sortField={sortField}
|
||||
sortField={{
|
||||
sortFieldId: sort.columnId,
|
||||
direction: sort.sortDirection as Direction,
|
||||
}}
|
||||
>
|
||||
{({
|
||||
events,
|
||||
|
@ -206,7 +196,12 @@ export const TimelineComponent: React.FC<Props> = ({
|
|||
browserFields={browserFields}
|
||||
data={events}
|
||||
id={id}
|
||||
height={bodyHeight}
|
||||
height={calculateBodyHeight({
|
||||
flyoutHeight,
|
||||
flyoutHeaderHeight,
|
||||
timelineHeaderHeight,
|
||||
timelineFooterHeight: footerHeight,
|
||||
})}
|
||||
sort={sort}
|
||||
toggleColumn={toggleColumn}
|
||||
/>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
|
||||
import { HookWrapper } from '../../mock';
|
||||
import { SiemPageName } from '../../pages/home/types';
|
||||
|
@ -73,11 +72,7 @@ describe('UrlStateContainer', () => {
|
|||
pageName,
|
||||
detailName,
|
||||
}).relativeTimeSearch.undefinedQuery;
|
||||
mount(
|
||||
<MockedProvider>
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
</MockedProvider>
|
||||
);
|
||||
mount(<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />);
|
||||
|
||||
expect(mockSetRelativeRangeDatePicker.mock.calls[1][0]).toEqual({
|
||||
from: 11223344556677,
|
||||
|
@ -106,11 +101,7 @@ describe('UrlStateContainer', () => {
|
|||
(page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => {
|
||||
mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName })
|
||||
.absoluteTimeSearch.undefinedQuery;
|
||||
mount(
|
||||
<MockedProvider>
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
</MockedProvider>
|
||||
);
|
||||
mount(<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />);
|
||||
|
||||
expect(mockSetAbsoluteRangeDatePicker.mock.calls[1][0]).toEqual({
|
||||
from: 1556736012685,
|
||||
|
@ -135,11 +126,7 @@ describe('UrlStateContainer', () => {
|
|||
(page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => {
|
||||
mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName })
|
||||
.relativeTimeSearch.undefinedQuery;
|
||||
mount(
|
||||
<MockedProvider>
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
</MockedProvider>
|
||||
);
|
||||
mount(<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />);
|
||||
|
||||
expect(mockSetFilterQuery.mock.calls[0][0]).toEqual({
|
||||
id: 'global',
|
||||
|
@ -163,11 +150,7 @@ describe('UrlStateContainer', () => {
|
|||
pageName,
|
||||
detailName,
|
||||
}).noSearch.definedQuery;
|
||||
mount(
|
||||
<MockedProvider>
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
</MockedProvider>
|
||||
);
|
||||
mount(<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />);
|
||||
|
||||
expect(
|
||||
mockHistory.replace.mock.calls[mockHistory.replace.mock.calls.length - 1][0]
|
||||
|
@ -197,9 +180,7 @@ describe('UrlStateContainer', () => {
|
|||
detailName,
|
||||
}).relativeTimeSearch.undefinedQuery;
|
||||
const wrapper = mount(
|
||||
<MockedProvider>
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
</MockedProvider>
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
);
|
||||
|
||||
wrapper.setProps({
|
||||
|
|
|
@ -52,4 +52,4 @@ const UseUrlStateComponent: React.FC<UrlStateProps> = props => {
|
|||
return <UrlStateRedux {...urlStateReduxProps} />;
|
||||
};
|
||||
|
||||
export const UseUrlState = React.memo(UseUrlStateComponent, deepEqual);
|
||||
export const UseUrlState = React.memo(UseUrlStateComponent);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
|
||||
import { HookWrapper } from '../../mock/hook_wrapper';
|
||||
import { SiemPageName } from '../../pages/home/types';
|
||||
|
@ -47,8 +46,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
|
|||
detailName: undefined,
|
||||
}).noSearch.definedQuery;
|
||||
const wrapper = mount(
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />,
|
||||
{ wrappingComponent: MockedProvider }
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
);
|
||||
|
||||
const newUrlState = {
|
||||
|
@ -99,8 +97,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
|
|||
detailName: undefined,
|
||||
}).noSearch.undefinedQuery;
|
||||
const wrapper = mount(
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />,
|
||||
{ wrappingComponent: MockedProvider }
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
);
|
||||
const newUrlState = {
|
||||
...mockProps.urlState,
|
||||
|
@ -132,8 +129,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
|
|||
}).noSearch.undefinedQuery;
|
||||
|
||||
const wrapper = mount(
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />,
|
||||
{ wrappingComponent: MockedProvider }
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
);
|
||||
const newUrlState = {
|
||||
...mockProps.urlState,
|
||||
|
@ -165,9 +161,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
|
|||
(page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => {
|
||||
mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName })
|
||||
.noSearch.undefinedQuery;
|
||||
mount(<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />, {
|
||||
wrappingComponent: MockedProvider,
|
||||
});
|
||||
mount(<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />);
|
||||
|
||||
expect(mockHistory.replace.mock.calls[0][0]).toEqual({
|
||||
hash: '',
|
||||
|
@ -204,8 +198,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
|
|||
detailName: undefined,
|
||||
}).noSearch.definedQuery;
|
||||
const wrapper = mount(
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />,
|
||||
{ wrappingComponent: MockedProvider }
|
||||
<HookWrapper hookProps={mockProps} hook={args => useUrlStateHooks(args)} />
|
||||
);
|
||||
|
||||
expect(
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ApolloClient } from '@apollo/client';
|
||||
import ApolloClient from 'apollo-client';
|
||||
import * as H from 'history';
|
||||
import { ActionCreator } from 'typescript-fsa';
|
||||
import {
|
||||
|
@ -88,6 +88,9 @@ export type KeyUrlState = keyof UrlState;
|
|||
export interface UrlStateProps {
|
||||
navTabs: Record<string, NavTab>;
|
||||
indexPattern?: IIndexPattern;
|
||||
mapToUrlState?: (value: string) => UrlState;
|
||||
onChange?: (urlState: UrlState, previousUrlState: UrlState) => void;
|
||||
onInitialize?: (urlState: UrlState) => void;
|
||||
}
|
||||
|
||||
export interface UrlStateStateToPropsType {
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
import { difference, isEmpty } from 'lodash/fp';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import { useApolloClient } from '../../utils/apollo_context';
|
||||
import { CONSTANTS, UrlStateType } from './constants';
|
||||
import {
|
||||
getQueryStringFromLocation,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const authenticationsQuery = gql`
|
||||
query GetAuthenticationsQuery(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
|
@ -13,7 +14,6 @@ import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
|||
import {
|
||||
AuthenticationsEdges,
|
||||
GetAuthenticationsQuery,
|
||||
GetAuthenticationsQueryComponent,
|
||||
PageInfoPaginated,
|
||||
} from '../../graphql/types';
|
||||
import { hostsModel, hostsSelectors, inputsModel, State, inputsSelectors } from '../../store';
|
||||
|
@ -22,6 +22,8 @@ import { generateTablePaginationOptions } from '../../components/paginated_table
|
|||
import { withKibana, WithKibanaProps } from '../../lib/kibana';
|
||||
import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated';
|
||||
|
||||
import { authenticationsQuery } from './index.gql_query';
|
||||
|
||||
const ID = 'authenticationQuery';
|
||||
|
||||
export interface AuthenticationArgs {
|
||||
|
@ -37,7 +39,7 @@ export interface AuthenticationArgs {
|
|||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplatePaginatedProps {
|
||||
children: (args: AuthenticationArgs) => React.ReactElement;
|
||||
children: (args: AuthenticationArgs) => React.ReactNode;
|
||||
type: hostsModel.HostsType;
|
||||
}
|
||||
|
||||
|
@ -81,7 +83,8 @@ class AuthenticationsComponentQuery extends QueryTemplatePaginated<
|
|||
inspect: isInspected,
|
||||
};
|
||||
return (
|
||||
<GetAuthenticationsQueryComponent
|
||||
<Query<GetAuthenticationsQuery.Query, GetAuthenticationsQuery.Variables>
|
||||
query={authenticationsQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -123,7 +126,7 @@ class AuthenticationsComponentQuery extends QueryTemplatePaginated<
|
|||
totalCount: getOr(-1, 'source.Authentications.totalCount', data),
|
||||
});
|
||||
}}
|
||||
</GetAuthenticationsQueryComponent>
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
*/
|
||||
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
|
||||
import { defaultIndexPattern } from '../../../../default_index_pattern';
|
||||
import { useApolloClient } from '../../../utils/apollo_context';
|
||||
import { mocksSource } from '../../source/mock';
|
||||
|
||||
import { useFetchIndexPatterns, Return } from './fetch_index_patterns';
|
||||
|
||||
const mockUseApolloClient = useApolloClient as jest.Mock;
|
||||
jest.mock('@apollo/client');
|
||||
jest.mock('../../../utils/apollo_context');
|
||||
|
||||
describe('useFetchIndexPatterns', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { isEmpty, get } from 'lodash/fp';
|
||||
import { useEffect, useState, Dispatch, SetStateAction } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
|
||||
import { IIndexPattern } from '../../../../../../../../src/plugins/data/public';
|
||||
|
@ -19,6 +18,7 @@ import {
|
|||
import { useStateToaster } from '../../../components/toasters';
|
||||
import { errorToToaster } from '../../../components/ml/api/error_to_toaster';
|
||||
import { SourceQuery } from '../../../graphql/types';
|
||||
import { useApolloClient } from '../../../utils/apollo_context';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
|
||||
import { reTryOneTimeOnErrorHandler, errorLinkHandler } from '.';
|
||||
import { ServerError, Operation } from '@apollo/client';
|
||||
import { ServerError } from 'apollo-link-http-common';
|
||||
import { Operation } from 'apollo-link';
|
||||
import { GraphQLError } from 'graphql';
|
||||
import * as store from '../../store';
|
||||
import { onError } from 'apollo-link-error';
|
||||
|
|
|
@ -5,18 +5,16 @@
|
|||
*/
|
||||
|
||||
import { get } from 'lodash/fp';
|
||||
import { FetchPolicy } from '@apollo/client';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../../common/constants';
|
||||
import {
|
||||
LastEventIndexKey,
|
||||
LastTimeDetails,
|
||||
useGetLastEventTimeQueryQuery,
|
||||
} from '../../../graphql/types';
|
||||
import { GetLastEventTimeQuery, LastEventIndexKey, LastTimeDetails } from '../../../graphql/types';
|
||||
import { inputsModel } from '../../../store';
|
||||
import { QueryTemplateProps } from '../../query_template';
|
||||
import { useUiSetting$ } from '../../../lib/kibana';
|
||||
|
||||
import { LastEventTimeGqlQuery } from './last_event_time.gql_query';
|
||||
import { useApolloClient } from '../../../utils/apollo_context';
|
||||
|
||||
export interface LastEventTimeArgs {
|
||||
id: string;
|
||||
|
@ -26,29 +24,63 @@ export interface LastEventTimeArgs {
|
|||
refetch: inputsModel.Refetch;
|
||||
}
|
||||
|
||||
export const useLastEventTimeQuery = (
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
children: (args: LastEventTimeArgs) => React.ReactNode;
|
||||
indexKey: LastEventIndexKey;
|
||||
}
|
||||
|
||||
export function useLastEventTimeQuery<TCache = object>(
|
||||
indexKey: LastEventIndexKey,
|
||||
details: LastTimeDetails,
|
||||
sourceId: string
|
||||
) => {
|
||||
) {
|
||||
const [loading, updateLoading] = useState(false);
|
||||
const [lastSeen, updateLastSeen] = useState<number | null>(null);
|
||||
const [errorMessage, updateErrorMessage] = useState<string | null>(null);
|
||||
const [currentIndexKey, updateCurrentIndexKey] = useState<LastEventIndexKey | null>(null);
|
||||
const [defaultIndex] = useUiSetting$<string[]>(DEFAULT_INDEX_KEY);
|
||||
const options = {
|
||||
query: LastEventTimeGqlQuery,
|
||||
fetchPolicy: 'cache-first' as FetchPolicy,
|
||||
variables: {
|
||||
sourceId,
|
||||
indexKey,
|
||||
details,
|
||||
defaultIndex,
|
||||
},
|
||||
};
|
||||
const apolloClient = useApolloClient();
|
||||
async function fetchLastEventTime(signal: AbortSignal) {
|
||||
updateLoading(true);
|
||||
if (apolloClient) {
|
||||
apolloClient
|
||||
.query<GetLastEventTimeQuery.Query, GetLastEventTimeQuery.Variables>({
|
||||
query: LastEventTimeGqlQuery,
|
||||
fetchPolicy: 'cache-first',
|
||||
variables: {
|
||||
sourceId,
|
||||
indexKey,
|
||||
details,
|
||||
defaultIndex,
|
||||
},
|
||||
context: {
|
||||
fetchOptions: {
|
||||
signal,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
updateLoading(false);
|
||||
updateLastSeen(get('data.source.LastEventTime.lastSeen', result));
|
||||
updateErrorMessage(null);
|
||||
updateCurrentIndexKey(currentIndexKey);
|
||||
},
|
||||
error => {
|
||||
updateLoading(false);
|
||||
updateLastSeen(null);
|
||||
updateErrorMessage(error.message);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const { data, loading, error } = useGetLastEventTimeQueryQuery(options);
|
||||
const lastSeen = get('source.LastEventTime.lastSeen', data);
|
||||
useEffect(() => {
|
||||
const abortCtrl = new AbortController();
|
||||
const signal = abortCtrl.signal;
|
||||
fetchLastEventTime(signal);
|
||||
return () => abortCtrl.abort();
|
||||
}, [apolloClient, indexKey, details.hostName, details.ip]);
|
||||
|
||||
return {
|
||||
lastSeen,
|
||||
loading,
|
||||
errorMessage: error?.message,
|
||||
};
|
||||
};
|
||||
return { lastSeen, loading, errorMessage };
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const LastEventTimeGqlQuery = gql`
|
||||
query GetLastEventTimeQuery(
|
||||
|
|
|
@ -4,14 +4,16 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { MockedResponse } from '@apollo/client/testing';
|
||||
|
||||
import { defaultIndexPattern } from '../../../../default_index_pattern';
|
||||
import { LastEventIndexKey } from '../../../graphql/types';
|
||||
import { GetLastEventTimeQuery, LastEventIndexKey } from '../../../graphql/types';
|
||||
|
||||
import { LastEventTimeGqlQuery } from './last_event_time.gql_query';
|
||||
|
||||
interface MockLastEventTimeQuery extends MockedResponse {
|
||||
interface MockLastEventTimeQuery {
|
||||
request: {
|
||||
query: GetLastEventTimeQuery.Query;
|
||||
variables: GetLastEventTimeQuery.Variables;
|
||||
};
|
||||
result: {
|
||||
data?: {
|
||||
source: {
|
||||
|
@ -22,6 +24,7 @@ interface MockLastEventTimeQuery extends MockedResponse {
|
|||
};
|
||||
};
|
||||
};
|
||||
errors?: [{ message: string }];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { useCallback, useState, useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import React, { useCallback, useState, useEffect } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
||||
import { inputsModel, inputsSelectors } from '../../store';
|
||||
import { inputsModel, inputsSelectors, State } from '../../store';
|
||||
import { inputsActions } from '../../store/actions';
|
||||
|
||||
interface SetQuery {
|
||||
|
@ -25,24 +25,31 @@ export interface GlobalTimeArgs {
|
|||
isInitializing: boolean;
|
||||
}
|
||||
|
||||
export const useGlobalTime = () => {
|
||||
const [isInitializing, setIsInitializing] = useState(true);
|
||||
const dispatch = useDispatch();
|
||||
const { from, to } = useSelector(inputsSelectors.globalTimeRangeSelector);
|
||||
interface OwnProps {
|
||||
children: (args: GlobalTimeArgs) => React.ReactNode;
|
||||
}
|
||||
|
||||
const deleteAllQuery = useCallback(props => dispatch(inputsActions.deleteAllQuery(props)), [
|
||||
dispatch,
|
||||
]);
|
||||
type GlobalTimeProps = OwnProps & PropsFromRedux;
|
||||
|
||||
export const GlobalTimeComponent: React.FC<GlobalTimeProps> = ({
|
||||
children,
|
||||
deleteAllQuery,
|
||||
deleteOneQuery,
|
||||
from,
|
||||
to,
|
||||
setGlobalQuery,
|
||||
}) => {
|
||||
const [isInitializing, setIsInitializing] = useState(true);
|
||||
|
||||
const setQuery = useCallback(
|
||||
({ id, inspect, loading, refetch }: SetQuery) =>
|
||||
dispatch(inputsActions.setQuery({ inputId: 'global', id, inspect, loading, refetch })),
|
||||
[dispatch]
|
||||
setGlobalQuery({ inputId: 'global', id, inspect, loading, refetch }),
|
||||
[setGlobalQuery]
|
||||
);
|
||||
|
||||
const deleteQuery = useCallback(
|
||||
({ id }: { id: string }) => dispatch(inputsActions.deleteOneQuery({ inputId: 'global', id })),
|
||||
[dispatch]
|
||||
({ id }: { id: string }) => deleteOneQuery({ inputId: 'global', id }),
|
||||
[deleteOneQuery]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -52,13 +59,37 @@ export const useGlobalTime = () => {
|
|||
return () => {
|
||||
deleteAllQuery({ id: 'global' });
|
||||
};
|
||||
}, [isInitializing, deleteAllQuery]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children({
|
||||
isInitializing,
|
||||
from,
|
||||
to,
|
||||
setQuery,
|
||||
deleteQuery,
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: State) => {
|
||||
const timerange: inputsModel.TimeRange = inputsSelectors.globalTimeRangeSelector(state);
|
||||
return {
|
||||
isInitializing,
|
||||
from,
|
||||
to,
|
||||
setQuery,
|
||||
deleteQuery,
|
||||
from: timerange.from,
|
||||
to: timerange.to,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = {
|
||||
deleteAllQuery: inputsActions.deleteAllQuery,
|
||||
deleteOneQuery: inputsActions.deleteOneQuery,
|
||||
setGlobalQuery: inputsActions.setQuery,
|
||||
};
|
||||
|
||||
export const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
type PropsFromRedux = ConnectedProps<typeof connector>;
|
||||
|
||||
export const GlobalTime = connector(React.memo(GlobalTimeComponent));
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { WatchQueryFetchPolicy } from '@apollo/client';
|
||||
import { FetchPolicy } from 'apollo-client';
|
||||
import { isString } from 'lodash/fp';
|
||||
|
||||
import { ESQuery } from '../../common/typed_json';
|
||||
|
@ -12,4 +12,4 @@ import { ESQuery } from '../../common/typed_json';
|
|||
export const createFilter = (filterQuery: ESQuery | string | undefined) =>
|
||||
isString(filterQuery) ? filterQuery : JSON.stringify(filterQuery);
|
||||
|
||||
export const getDefaultFetchPolicy = (): WatchQueryFetchPolicy => 'cache-and-network';
|
||||
export const getDefaultFetchPolicy = (): FetchPolicy => 'cache-and-network';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const HostFirstLastSeenGqlQuery = gql`
|
||||
query GetHostFirstLastSeenQuery($sourceId: ID!, $hostName: String!, $defaultIndex: [String!]!) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import ApolloClient from 'apollo-client';
|
||||
import { get } from 'lodash/fp';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
|
@ -26,16 +26,19 @@ export interface FirstLastSeenHostArgs {
|
|||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
children: (args: FirstLastSeenHostArgs) => React.ReactElement;
|
||||
children: (args: FirstLastSeenHostArgs) => React.ReactNode;
|
||||
hostName: string;
|
||||
}
|
||||
|
||||
export function useFirstLastSeenHostQuery(hostName: string, sourceId: string) {
|
||||
export function useFirstLastSeenHostQuery<TCache = object>(
|
||||
hostName: string,
|
||||
sourceId: string,
|
||||
apolloClient: ApolloClient<TCache>
|
||||
) {
|
||||
const [loading, updateLoading] = useState(false);
|
||||
const [firstSeen, updateFirstSeen] = useState<Date | null>(null);
|
||||
const [lastSeen, updateLastSeen] = useState<Date | null>(null);
|
||||
const [errorMessage, updateErrorMessage] = useState<string | null>(null);
|
||||
const apolloClient = useApolloClient();
|
||||
const [defaultIndex] = useUiSetting$<string[]>(DEFAULT_INDEX_KEY);
|
||||
|
||||
async function fetchFirstLastSeenHost(signal: AbortSignal) {
|
||||
|
|
|
@ -4,12 +4,16 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { MockedResponse } from '@apollo/client/testing';
|
||||
import { defaultIndexPattern } from '../../../../default_index_pattern';
|
||||
import { GetHostFirstLastSeenQuery } from '../../../graphql/types';
|
||||
|
||||
import { HostFirstLastSeenGqlQuery } from './first_last_seen.gql_query';
|
||||
|
||||
interface MockedProvidedQuery extends MockedResponse {
|
||||
interface MockedProvidedQuery {
|
||||
request: {
|
||||
query: GetHostFirstLastSeenQuery.Query;
|
||||
variables: GetHostFirstLastSeenQuery.Variables;
|
||||
};
|
||||
result: {
|
||||
data?: {
|
||||
source: {
|
||||
|
@ -20,9 +24,9 @@ interface MockedProvidedQuery extends MockedResponse {
|
|||
};
|
||||
};
|
||||
};
|
||||
errors?: [{ message: string }];
|
||||
};
|
||||
}
|
||||
|
||||
export const mockFirstLastSeenHostQuery: MockedProvidedQuery[] = [
|
||||
{
|
||||
request: {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const HostsTableQuery = gql`
|
||||
query GetHostsTableQuery(
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { get, getOr } from 'lodash/fp';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
|
@ -14,7 +15,6 @@ import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
|||
import {
|
||||
Direction,
|
||||
GetHostsTableQuery,
|
||||
GetHostsTableQueryComponent,
|
||||
HostsEdges,
|
||||
HostsFields,
|
||||
PageInfoPaginated,
|
||||
|
@ -24,6 +24,7 @@ import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
|||
import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated';
|
||||
import { withKibana, WithKibanaProps } from '../../lib/kibana';
|
||||
|
||||
import { HostsTableQuery } from './hosts_table.gql_query';
|
||||
import { generateTablePaginationOptions } from '../../components/paginated_table/helpers';
|
||||
|
||||
const ID = 'hostsQuery';
|
||||
|
@ -43,7 +44,7 @@ export interface HostsArgs {
|
|||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplatePaginatedProps {
|
||||
children: (args: HostsArgs) => React.ReactElement;
|
||||
children: (args: HostsArgs) => React.ReactNode;
|
||||
type: hostsModel.HostsType;
|
||||
startDate: number;
|
||||
endDate: number;
|
||||
|
@ -109,7 +110,8 @@ class HostsComponentQuery extends QueryTemplatePaginated<
|
|||
inspect: isInspected,
|
||||
};
|
||||
return (
|
||||
<GetHostsTableQueryComponent
|
||||
<Query<GetHostsTableQuery.Query, GetHostsTableQuery.Variables>
|
||||
query={HostsTableQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -152,7 +154,7 @@ class HostsComponentQuery extends QueryTemplatePaginated<
|
|||
totalCount: getOr(-1, 'source.Hosts.totalCount', data),
|
||||
});
|
||||
}}
|
||||
</GetHostsTableQueryComponent>
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const HostOverviewQuery = gql`
|
||||
query GetHostOverviewQuery(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
|
@ -15,11 +16,8 @@ import { getDefaultFetchPolicy } from '../../helpers';
|
|||
import { QueryTemplate, QueryTemplateProps } from '../../query_template';
|
||||
import { withKibana, WithKibanaProps } from '../../../lib/kibana';
|
||||
|
||||
import {
|
||||
GetHostOverviewQuery,
|
||||
GetHostOverviewQueryComponent,
|
||||
HostItem,
|
||||
} from '../../../graphql/types';
|
||||
import { HostOverviewQuery } from './host_overview.gql_query';
|
||||
import { GetHostOverviewQuery, HostItem } from '../../../graphql/types';
|
||||
|
||||
const ID = 'hostOverviewQuery';
|
||||
|
||||
|
@ -38,7 +36,7 @@ export interface HostOverviewReduxProps {
|
|||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
children: (args: HostOverviewArgs) => React.ReactElement;
|
||||
children: (args: HostOverviewArgs) => React.ReactNode;
|
||||
hostName: string;
|
||||
startDate: number;
|
||||
endDate: number;
|
||||
|
@ -64,7 +62,8 @@ class HostOverviewByNameComponentQuery extends QueryTemplate<
|
|||
endDate,
|
||||
} = this.props;
|
||||
return (
|
||||
<GetHostOverviewQueryComponent
|
||||
<Query<GetHostOverviewQuery.Query, GetHostOverviewQuery.Variables>
|
||||
query={HostOverviewQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -92,7 +91,7 @@ class HostOverviewByNameComponentQuery extends QueryTemplate<
|
|||
endDate,
|
||||
});
|
||||
}}
|
||||
</GetHostOverviewQueryComponent>
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const ipOverviewQuery = gql`
|
||||
query GetIpOverviewQuery(
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import { GetIpOverviewQueryComponent, IpOverviewData } from '../../graphql/types';
|
||||
import { GetIpOverviewQuery, IpOverviewData } from '../../graphql/types';
|
||||
import { networkModel, inputsModel, inputsSelectors, State } from '../../store';
|
||||
import { useUiSetting } from '../../lib/kibana';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplateProps } from '../query_template';
|
||||
|
||||
import { ipOverviewQuery } from './index.gql_query';
|
||||
|
||||
const ID = 'ipOverviewQuery';
|
||||
|
||||
export interface IpOverviewArgs {
|
||||
|
@ -26,14 +29,15 @@ export interface IpOverviewArgs {
|
|||
}
|
||||
|
||||
export interface IpOverviewProps extends QueryTemplateProps {
|
||||
children: (args: IpOverviewArgs) => React.ReactElement;
|
||||
children: (args: IpOverviewArgs) => React.ReactNode;
|
||||
type: networkModel.NetworkType;
|
||||
ip: string;
|
||||
}
|
||||
|
||||
const IpOverviewComponentQuery = React.memo<IpOverviewProps & PropsFromRedux>(
|
||||
({ id = ID, isInspected, children, filterQuery, skip, sourceId, ip }) => (
|
||||
<GetIpOverviewQueryComponent
|
||||
<Query<GetIpOverviewQuery.Query, GetIpOverviewQuery.Variables>
|
||||
query={ipOverviewQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -56,7 +60,7 @@ const IpOverviewComponentQuery = React.memo<IpOverviewProps & PropsFromRedux>(
|
|||
refetch,
|
||||
});
|
||||
}}
|
||||
</GetIpOverviewQueryComponent>
|
||||
</Query>
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const kpiHostDetailsQuery = gql`
|
||||
fragment KpiHostDetailsChartFields on KpiHostHistogramData {
|
|
@ -6,15 +6,18 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import { KpiHostDetailsData, GetKpiHostDetailsQueryComponent } from '../../graphql/types';
|
||||
import { KpiHostDetailsData, GetKpiHostDetailsQuery } from '../../graphql/types';
|
||||
import { inputsModel, inputsSelectors, State } from '../../store';
|
||||
import { useUiSetting } from '../../lib/kibana';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplateProps } from '../query_template';
|
||||
|
||||
import { kpiHostDetailsQuery } from './index.gql_query';
|
||||
|
||||
const ID = 'kpiHostDetailsQuery';
|
||||
|
||||
export interface KpiHostDetailsArgs {
|
||||
|
@ -26,12 +29,13 @@ export interface KpiHostDetailsArgs {
|
|||
}
|
||||
|
||||
export interface QueryKpiHostDetailsProps extends QueryTemplateProps {
|
||||
children: (args: KpiHostDetailsArgs) => React.ReactElement;
|
||||
children: (args: KpiHostDetailsArgs) => React.ReactNode;
|
||||
}
|
||||
|
||||
const KpiHostDetailsComponentQuery = React.memo<QueryKpiHostDetailsProps & PropsFromRedux>(
|
||||
({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => (
|
||||
<GetKpiHostDetailsQueryComponent
|
||||
<Query<GetKpiHostDetailsQuery.Query, GetKpiHostDetailsQuery.Variables>
|
||||
query={kpiHostDetailsQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -57,7 +61,7 @@ const KpiHostDetailsComponentQuery = React.memo<QueryKpiHostDetailsProps & Props
|
|||
refetch,
|
||||
});
|
||||
}}
|
||||
</GetKpiHostDetailsQueryComponent>
|
||||
</Query>
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const kpiHostsQuery = gql`
|
||||
fragment KpiHostChartFields on KpiHostHistogramData {
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import { GetKpiHostsQueryComponent, KpiHostsData } from '../../graphql/types';
|
||||
import { GetKpiHostsQuery, KpiHostsData } from '../../graphql/types';
|
||||
import { inputsModel, inputsSelectors, State } from '../../store';
|
||||
import { useUiSetting } from '../../lib/kibana';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplateProps } from '../query_template';
|
||||
|
||||
import { kpiHostsQuery } from './index.gql_query';
|
||||
|
||||
const ID = 'kpiHostsQuery';
|
||||
|
||||
export interface KpiHostsArgs {
|
||||
|
@ -26,12 +29,13 @@ export interface KpiHostsArgs {
|
|||
}
|
||||
|
||||
export interface KpiHostsProps extends QueryTemplateProps {
|
||||
children: (args: KpiHostsArgs) => React.ReactElement;
|
||||
children: (args: KpiHostsArgs) => React.ReactNode;
|
||||
}
|
||||
|
||||
const KpiHostsComponentQuery = React.memo<KpiHostsProps & PropsFromRedux>(
|
||||
({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => (
|
||||
<GetKpiHostsQueryComponent
|
||||
<Query<GetKpiHostsQuery.Query, GetKpiHostsQuery.Variables>
|
||||
query={kpiHostsQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -57,7 +61,7 @@ const KpiHostsComponentQuery = React.memo<KpiHostsProps & PropsFromRedux>(
|
|||
refetch,
|
||||
});
|
||||
}}
|
||||
</GetKpiHostsQueryComponent>
|
||||
</Query>
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const kpiNetworkQuery = gql`
|
||||
fragment KpiNetworkChartFields on KpiNetworkHistogramData {
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import { GetKpiNetworkQueryComponent, KpiNetworkData } from '../../graphql/types';
|
||||
import { GetKpiNetworkQuery, KpiNetworkData } from '../../graphql/types';
|
||||
import { inputsModel, inputsSelectors, State } from '../../store';
|
||||
import { useUiSetting } from '../../lib/kibana';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplateProps } from '../query_template';
|
||||
|
||||
import { kpiNetworkQuery } from './index.gql_query';
|
||||
|
||||
const ID = 'kpiNetworkQuery';
|
||||
|
||||
export interface KpiNetworkArgs {
|
||||
|
@ -26,12 +29,13 @@ export interface KpiNetworkArgs {
|
|||
}
|
||||
|
||||
export interface KpiNetworkProps extends QueryTemplateProps {
|
||||
children: (args: KpiNetworkArgs) => React.ReactElement;
|
||||
children: (args: KpiNetworkArgs) => React.ReactNode;
|
||||
}
|
||||
|
||||
const KpiNetworkComponentQuery = React.memo<KpiNetworkProps & PropsFromRedux>(
|
||||
({ id = ID, children, filterQuery, isInspected, skip, sourceId, startDate, endDate }) => (
|
||||
<GetKpiNetworkQueryComponent
|
||||
<Query<GetKpiNetworkQuery.Query, GetKpiNetworkQuery.Variables>
|
||||
query={kpiNetworkQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
skip={skip}
|
||||
|
@ -57,7 +61,7 @@ const KpiNetworkComponentQuery = React.memo<KpiNetworkProps & PropsFromRedux>(
|
|||
refetch,
|
||||
});
|
||||
}}
|
||||
</GetKpiNetworkQueryComponent>
|
||||
</Query>
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const MatrixHistogramGqlQuery = gql`
|
||||
query GetMatrixHistogramQuery(
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
import { useQuery } from '.';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
|
||||
import { useApolloClient } from '../../utils/apollo_context';
|
||||
import { errorToToaster } from '../../components/ml/api/error_to_toaster';
|
||||
import { MatrixOverTimeHistogramData, HistogramType } from '../../graphql/types';
|
||||
import { InspectQuery, Refetch } from '../../store/inputs/model';
|
||||
|
@ -26,7 +25,7 @@ const mockQuery = jest.fn().mockResolvedValue({
|
|||
});
|
||||
|
||||
const mockRejectQuery = jest.fn().mockRejectedValue(new Error());
|
||||
jest.mock('@apollo/client', () => ({
|
||||
jest.mock('../../utils/apollo_context', () => ({
|
||||
useApolloClient: jest.fn(),
|
||||
}));
|
||||
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
|
||||
import { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types';
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import { useStateToaster } from '../../components/toasters';
|
||||
import { errorToToaster } from '../../components/ml/api/error_to_toaster';
|
||||
import { useUiSetting$ } from '../../lib/kibana';
|
||||
import { createFilter } from '../helpers';
|
||||
import { useApolloClient } from '../../utils/apollo_context';
|
||||
import { inputsModel } from '../../store';
|
||||
import { MatrixHistogramGqlQuery } from './index.gql_query';
|
||||
import { GetMatrixHistogramQuery, MatrixOverTimeHistogramData } from '../../graphql/types';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const networkDnsQuery = gql`
|
||||
query GetNetworkDnsQuery(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
|
@ -14,7 +15,6 @@ import { ScaleType } from '@elastic/charts';
|
|||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import {
|
||||
GetNetworkDnsQuery,
|
||||
GetNetworkDnsQueryComponent,
|
||||
NetworkDnsEdges,
|
||||
NetworkDnsSortField,
|
||||
PageInfoPaginated,
|
||||
|
@ -25,6 +25,7 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana';
|
|||
import { generateTablePaginationOptions } from '../../components/paginated_table/helpers';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated';
|
||||
import { networkDnsQuery } from './index.gql_query';
|
||||
import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from '../../store/constants';
|
||||
import { MatrixHistogram } from '../../components/matrix_histogram';
|
||||
import { MatrixHistogramOption, GetSubTitle } from '../../components/matrix_histogram/types';
|
||||
|
@ -48,7 +49,7 @@ export interface NetworkDnsArgs {
|
|||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplatePaginatedProps {
|
||||
children: (args: NetworkDnsArgs) => React.ReactElement;
|
||||
children: (args: NetworkDnsArgs) => React.ReactNode;
|
||||
type: networkModel.NetworkType;
|
||||
}
|
||||
|
||||
|
@ -116,9 +117,10 @@ export class NetworkDnsComponentQuery extends QueryTemplatePaginated<
|
|||
};
|
||||
|
||||
return (
|
||||
<GetNetworkDnsQueryComponent
|
||||
<Query<GetNetworkDnsQuery.Query, GetNetworkDnsQuery.Variables>
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
query={networkDnsQuery}
|
||||
skip={skip}
|
||||
variables={variables}
|
||||
>
|
||||
|
@ -159,7 +161,7 @@ export class NetworkDnsComponentQuery extends QueryTemplatePaginated<
|
|||
histogram: getOr(null, 'source.NetworkDns.histogram', data),
|
||||
});
|
||||
}}
|
||||
</GetNetworkDnsQueryComponent>
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const networkHttpQuery = gql`
|
||||
query GetNetworkHttpQuery(
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import {
|
||||
GetNetworkHttpQuery,
|
||||
GetNetworkHttpQueryComponent,
|
||||
NetworkHttpEdges,
|
||||
NetworkHttpSortField,
|
||||
PageInfoPaginated,
|
||||
|
@ -22,6 +22,7 @@ import { withKibana, WithKibanaProps } from '../../lib/kibana';
|
|||
import { generateTablePaginationOptions } from '../../components/paginated_table/helpers';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated';
|
||||
import { networkHttpQuery } from './index.gql_query';
|
||||
|
||||
const ID = 'networkHttpQuery';
|
||||
|
||||
|
@ -39,7 +40,7 @@ export interface NetworkHttpArgs {
|
|||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplatePaginatedProps {
|
||||
children: (args: NetworkHttpArgs) => React.ReactElement;
|
||||
children: (args: NetworkHttpArgs) => React.ReactNode;
|
||||
ip?: string;
|
||||
type: networkModel.NetworkType;
|
||||
}
|
||||
|
@ -89,9 +90,10 @@ class NetworkHttpComponentQuery extends QueryTemplatePaginated<
|
|||
},
|
||||
};
|
||||
return (
|
||||
<GetNetworkHttpQueryComponent
|
||||
<Query<GetNetworkHttpQuery.Query, GetNetworkHttpQuery.Variables>
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
query={networkHttpQuery}
|
||||
skip={skip}
|
||||
variables={variables}
|
||||
>
|
||||
|
@ -131,7 +133,7 @@ class NetworkHttpComponentQuery extends QueryTemplatePaginated<
|
|||
totalCount: getOr(-1, 'source.NetworkHttp.totalCount', data),
|
||||
});
|
||||
}}
|
||||
</GetNetworkHttpQueryComponent>
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const networkTopCountriesQuery = gql`
|
||||
query GetNetworkTopCountriesQuery(
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue