Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Restores [SIEM][CASE] Init Configure Case Page (#58121) #58924

Merged
merged 25 commits into from
Mar 1, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
01dc2ee
[SIEM][CASE] Init configure cases
cnasikas Feb 19, 2020
7705ca9
[SIEM][CASE] Translate header title
cnasikas Feb 19, 2020
559407f
[SIEM][CASE] Add back link
cnasikas Feb 19, 2020
ff22214
[SIEM][CASE] Add default options to header page
cnasikas Feb 20, 2020
bb14de6
[SIEM][CASE] Create configure cases page redirections and links
cnasikas Feb 20, 2020
27d220e
[SIEM][CASE] Add configure cases button
cnasikas Feb 20, 2020
0539575
[SIEM][CASE] Change translation variable
cnasikas Feb 20, 2020
cc80dc3
Create wrappers
cnasikas Feb 22, 2020
44d9cb9
Create section wrapper
cnasikas Feb 22, 2020
f9f042b
Switch to new wrapper
cnasikas Feb 22, 2020
e7cff39
Add translations
cnasikas Feb 23, 2020
61e7dc3
Add connectors dropdown component
cnasikas Feb 23, 2020
20f9928
Add connectors component
cnasikas Feb 23, 2020
2e51360
Show connectors
cnasikas Feb 23, 2020
2a7cc6d
Create add new connector button
cnasikas Feb 24, 2020
fad34bf
Change values
cnasikas Feb 27, 2020
2678045
Use state for connectors dropdown
cnasikas Feb 27, 2020
e3d3dc7
Remove unnecessary attribute
cnasikas Feb 27, 2020
2ba9679
Remove timeline in configuration page
cnasikas Feb 27, 2020
5c6407a
Remove text from gear button
cnasikas Feb 27, 2020
3bd2e27
make show timeline more generic so we can re-use if need it
XavierM Feb 27, 2020
5224292
Merge branch 'master' into configure_cases_restore
elasticmachine Feb 29, 2020
98b8964
Merge branch 'master' into configure_cases_restore
elasticmachine Feb 29, 2020
70b6cd8
Merge branch 'master' into configure_cases_restore
elasticmachine Feb 29, 2020
2f6d314
Merge branch 'master' into configure_cases_restore
elasticmachine Mar 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/siem/public/components/link_to/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export {
getCaseDetailsUrl,
getCaseUrl,
getCreateCaseUrl,
getConfigureCasesUrl,
RedirectToCasePage,
RedirectToCreatePage,
RedirectToConfigureCasesPage,
} from './redirect_to_case';
11 changes: 10 additions & 1 deletion x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import { RedirectToHostsPage, RedirectToHostDetailsPage } from './redirect_to_ho
import { RedirectToNetworkPage } from './redirect_to_network';
import { RedirectToOverviewPage } from './redirect_to_overview';
import { RedirectToTimelinesPage } from './redirect_to_timelines';
import { RedirectToCasePage, RedirectToCreatePage } from './redirect_to_case';
import {
RedirectToCasePage,
RedirectToCreatePage,
RedirectToConfigureCasesPage,
} from './redirect_to_case';
import { DetectionEngineTab } from '../../pages/detection_engine/types';

interface LinkToPageProps {
Expand All @@ -43,6 +47,11 @@ export const LinkToPage = React.memo<LinkToPageProps>(({ match }) => (
component={RedirectToCreatePage}
path={`${match.url}/:pageName(${SiemPageName.case})/create`}
/>
<Route
exact
component={RedirectToConfigureCasesPage}
path={`${match.url}/:pageName(${SiemPageName.case})/configure`}
/>
<Route
component={RedirectToCasePage}
path={`${match.url}/:pageName(${SiemPageName.case})/:detailName`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ export const RedirectToCasePage = ({
);

export const RedirectToCreatePage = () => <RedirectWrapper to={`/${SiemPageName.case}/create`} />;
export const RedirectToConfigureCasesPage = () => (
<RedirectWrapper to={`/${SiemPageName.case}/configure`} />
);

const baseCaseUrl = `#/link-to/${SiemPageName.case}`;

export const getCaseUrl = () => baseCaseUrl;
export const getCaseDetailsUrl = (detailName: string) => `${baseCaseUrl}/${detailName}`;
export const getCreateCaseUrl = () => `${baseCaseUrl}/create`;
export const getConfigureCasesUrl = () => `${baseCaseUrl}/configure`;
27 changes: 13 additions & 14 deletions x-pack/legacy/plugins/siem/public/pages/case/case.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,29 @@

import React from 'react';

import { EuiButton, EuiFlexGroup } from '@elastic/eui';
import { HeaderPage } from '../../components/header_page';
import { EuiButton, EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { CaseHeaderPage } from './components/case_header_page';
import { WrapperPage } from '../../components/wrapper_page';
import { AllCases } from './components/all_cases';
import { SpyRoute } from '../../utils/route/spy_routes';
import * as i18n from './translations';
import { getCreateCaseUrl } from '../../components/link_to';

const badgeOptions = {
beta: true,
text: i18n.PAGE_BADGE_LABEL,
tooltip: i18n.PAGE_BADGE_TOOLTIP,
};
import { getCreateCaseUrl, getConfigureCasesUrl } from '../../components/link_to';

export const CasesPage = React.memo(() => (
<>
<WrapperPage>
<HeaderPage badgeOptions={badgeOptions} subtitle={i18n.PAGE_SUBTITLE} title={i18n.PAGE_TITLE}>
<CaseHeaderPage subtitle={i18n.PAGE_SUBTITLE} title={i18n.PAGE_TITLE}>
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false} wrap={true}>
<EuiButton fill href={getCreateCaseUrl()} iconType="plusInCircle">
{i18n.CREATE_TITLE}
</EuiButton>
<EuiFlexItem grow={false}>
<EuiButton fill href={getCreateCaseUrl()} iconType="plusInCircle">
{i18n.CREATE_TITLE}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon href={getConfigureCasesUrl()} iconType="gear" />
</EuiFlexItem>
</EuiFlexGroup>
</HeaderPage>
</CaseHeaderPage>
<AllCases />
</WrapperPage>
<SpyRoute />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';

import { HeaderPage, HeaderPageProps } from '../../../../components/header_page';
import * as i18n from './translations';

const CaseHeaderPageComponent: React.FC<HeaderPageProps> = props => <HeaderPage {...props} />;

CaseHeaderPageComponent.defaultProps = {
badgeOptions: {
beta: true,
text: i18n.PAGE_BADGE_LABEL,
tooltip: i18n.PAGE_BADGE_TOOLTIP,
},
};

export const CaseHeaderPage = React.memo(CaseHeaderPageComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';

export const PAGE_BADGE_LABEL = i18n.translate('xpack.siem.case.caseView.pageBadgeLabel', {
defaultMessage: 'Beta',
});

export const PAGE_BADGE_TOOLTIP = i18n.translate('xpack.siem.case.caseView.pageBadgeTooltip', {
defaultMessage:
'Case Workflow is still in beta. Please help us improve by reporting issues or bugs in the Kibana repo.',
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { UserActionTree } from '../user_action_tree';
import { UserList } from '../user_list';
import { useUpdateCase } from '../../../../containers/case/use_update_case';
import { WrapperPage } from '../../../../components/wrapper_page';
import { WhitePageWrapper } from '../wrappers';

interface Props {
caseId: string;
Expand All @@ -52,14 +53,6 @@ const MyWrapper = styled(WrapperPage)`
padding-bottom: 0;
`;

const BackgroundWrapper = styled.div`
${({ theme }) => css`
background-color: ${theme.eui.euiColorEmptyShade};
border-top: ${theme.eui.euiBorderThin};
height: 100%;
`}
`;

export interface CaseProps {
caseId: string;
initialData: Case;
Expand Down Expand Up @@ -279,7 +272,7 @@ export const CaseComponent = React.memo<CaseProps>(({ caseId, initialData, isLoa
</EuiFlexGroup>
</HeaderPage>
</MyWrapper>
<BackgroundWrapper>
<WhitePageWrapper>
<MyWrapper>
<EuiFlexGroup>
<EuiFlexItem grow={6}>
Expand All @@ -305,7 +298,7 @@ export const CaseComponent = React.memo<CaseProps>(({ caseId, initialData, isLoa
</EuiFlexItem>
</EuiFlexGroup>
</MyWrapper>
</BackgroundWrapper>
</WhitePageWrapper>
</>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import {
EuiDescribedFormGroup,
EuiFormRow,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
} from '@elastic/eui';

import styled from 'styled-components';

import { ConnectorsDropdown } from './connectors_dropdown';
import * as i18n from './translations';

const EuiFormRowExtended = styled(EuiFormRow)`
.euiFormRow__labelWrapper {
.euiFormRow__label {
width: 100%;
}
}
`;

const ConnectorsComponent: React.FC = () => {
const dropDownLabel = (
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>{i18n.INCIDENT_MANAGEMENT_SYSTEM_LABEL}</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiLink>{i18n.ADD_NEW_CONNECTOR}</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
);

return (
<EuiDescribedFormGroup
fullWidth
title={<h3>{i18n.INCIDENT_MANAGEMENT_SYSTEM_TITLE}</h3>}
description={i18n.INCIDENT_MANAGEMENT_SYSTEM_DESC}
>
<EuiFormRowExtended fullWidth label={dropDownLabel}>
<ConnectorsDropdown />
</EuiFormRowExtended>
</EuiDescribedFormGroup>
);
};

export const Connectors = React.memo(ConnectorsComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useState, useCallback } from 'react';
import { EuiSuperSelect, EuiIcon, EuiSuperSelectOption } from '@elastic/eui';
import styled from 'styled-components';

import * as i18n from '../translations';

const ICON_SIZE = 'm';

const EuiIconExtended = styled(EuiIcon)`
margin-right: 13px;
`;

const connectors: Array<EuiSuperSelectOption<string>> = [
{
value: 'no-connector',
inputDisplay: (
<>
<EuiIconExtended type="minusInCircle" size={ICON_SIZE} />
<span>{i18n.NO_CONNECTOR}</span>
</>
),
'data-test-subj': 'no-connector',
},
{
value: 'servicenow-connector',
inputDisplay: (
<>
<EuiIconExtended type="logoWebhook" size={ICON_SIZE} />
<span>{'My ServiceNow connector'}</span>
</>
),
'data-test-subj': 'servicenow-connector',
},
];

const ConnectorsDropdownComponent: React.FC = () => {
const [selectedConnector, selectConnector] = useState(connectors[0].value);
const onChange = useCallback(connector => selectConnector(connector), [selectedConnector]);

return (
<EuiSuperSelect
options={connectors}
valueOfSelected={selectedConnector}
fullWidth
onChange={onChange}
/>
);
};

export const ConnectorsDropdown = React.memo(ConnectorsDropdownComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';

export const INCIDENT_MANAGEMENT_SYSTEM_TITLE = i18n.translate(
'xpack.siem.case.configureCases.incidentManagementSystemTitle',
{
defaultMessage: 'Connect to third-party incident management system',
}
);

export const INCIDENT_MANAGEMENT_SYSTEM_DESC = i18n.translate(
'xpack.siem.case.configureCases.incidentManagementSystemDesc',
{
defaultMessage:
'You may optionally connect SIEM cases to a third-party incident management system of your choosing. This will allow you to push case data as an incident in your chosen third-party system.',
}
);

export const INCIDENT_MANAGEMENT_SYSTEM_LABEL = i18n.translate(
'xpack.siem.case.configureCases.incidentManagementSystemLabel',
{
defaultMessage: 'Incident management system',
}
);

export const NO_CONNECTOR = i18n.translate('xpack.siem.case.configureCases.noConnector', {
defaultMessage: 'No connector selected',
});

export const ADD_NEW_CONNECTOR = i18n.translate('xpack.siem.case.configureCases.addNewConnector', {
defaultMessage: 'Add new connector option',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import styled, { css } from 'styled-components';

export const WhitePageWrapper = styled.div`
${({ theme }) => css`
background-color: ${theme.eui.euiColorEmptyShade};
border-top: ${theme.eui.euiBorderThin};
height: 100%;
min-height: 100vh;
`}
`;

export const SectionWrapper = styled.div`
box-sizing: content-box;
margin: 0 auto;
max-width: 1175px;
`;
54 changes: 54 additions & 0 deletions x-pack/legacy/plugins/siem/public/pages/case/configure_cases.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import styled, { css } from 'styled-components';

import { WrapperPage } from '../../components/wrapper_page';
import { CaseHeaderPage } from './components/case_header_page';
import { SpyRoute } from '../../utils/route/spy_routes';
import { getCaseUrl } from '../../components/link_to';
import { WhitePageWrapper, SectionWrapper } from './components/wrappers';
import { Connectors } from './components/configure_cases/connectors';
import * as i18n from './translations';

const backOptions = {
href: getCaseUrl(),
text: i18n.BACK_TO_ALL,
};

const wrapperPageStyle: Record<string, string> = {
paddingLeft: '0',
paddingRight: '0',
paddingBottom: '0',
};

export const FormWrapper = styled.div`
${({ theme }) => css`
padding-top: ${theme.eui.paddingSizes.l};
padding-bottom: ${theme.eui.paddingSizes.l};
`}
`;

const ConfigureCasesPageComponent: React.FC = () => (
<>
<WrapperPage style={wrapperPageStyle}>
<SectionWrapper>
<CaseHeaderPage title={i18n.CONFIGURE_CASES_PAGE_TITLE} backOptions={backOptions} />
</SectionWrapper>
<WhitePageWrapper>
<FormWrapper>
<SectionWrapper>
<Connectors />
</SectionWrapper>
</FormWrapper>
</WhitePageWrapper>
</WrapperPage>
<SpyRoute />
</>
);

export const ConfigureCasesPage = React.memo(ConfigureCasesPageComponent);
Loading