mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* Create closure options radio group * Create closure options component * Refactor structure * Create field mapping row * Create field component * Show closure options * Show field mapping * Translate editUpdate options * Add more siem fields * Remove unnecessary export * Leave spaces between sections * Fix callbacks * Better return * Fix callback * Move thirdPartyFields to parent component * Rename constant Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
4fa765e469
commit
609e996a56
7 changed files with 326 additions and 6 deletions
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 } from '@elastic/eui';
|
||||
|
||||
import * as i18n from './translations';
|
||||
import { ClosureOptionsRadio } from './closure_options_radio';
|
||||
|
||||
const ClosureOptionsComponent: React.FC = () => {
|
||||
return (
|
||||
<EuiDescribedFormGroup
|
||||
fullWidth
|
||||
title={<h3>{i18n.CASE_CLOSURE_OPTIONS_TITLE}</h3>}
|
||||
description={i18n.CASE_CLOSURE_OPTIONS_DESC}
|
||||
>
|
||||
<EuiFormRow fullWidth label={i18n.CASE_CLOSURE_OPTIONS_LABEL}>
|
||||
<ClosureOptionsRadio />
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const ClosureOptions = React.memo(ClosureOptionsComponent);
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 } from 'react';
|
||||
import { EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
||||
const ID_PREFIX = 'closure_options';
|
||||
const DEFAULT_RADIO = `${ID_PREFIX}_manual`;
|
||||
|
||||
const radios = [
|
||||
{
|
||||
id: DEFAULT_RADIO,
|
||||
label: i18n.CASE_CLOSURE_OPTIONS_MANUAL,
|
||||
},
|
||||
{
|
||||
id: `${ID_PREFIX}_new_incident`,
|
||||
label: i18n.CASE_CLOSURE_OPTIONS_NEW_INCIDENT,
|
||||
},
|
||||
{
|
||||
id: `${ID_PREFIX}_closed_incident`,
|
||||
label: i18n.CASE_CLOSURE_OPTIONS_CLOSED_INCIDENT,
|
||||
},
|
||||
];
|
||||
|
||||
const ClosureOptionsRadioComponent: React.FC = () => {
|
||||
const [selectedClosure, setSelectedClosure] = useState(DEFAULT_RADIO);
|
||||
|
||||
return (
|
||||
<EuiRadioGroup
|
||||
options={radios}
|
||||
idSelected={selectedClosure}
|
||||
onChange={setSelectedClosure}
|
||||
name="closure_options"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const ClosureOptionsRadio = React.memo(ClosureOptionsRadioComponent);
|
|
@ -4,11 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { EuiSuperSelect, EuiIcon, EuiSuperSelectOption } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import * as i18n from '../translations';
|
||||
import * as i18n from './translations';
|
||||
|
||||
const ICON_SIZE = 'm';
|
||||
|
||||
|
@ -40,15 +40,14 @@ const connectors: Array<EuiSuperSelectOption<string>> = [
|
|||
];
|
||||
|
||||
const ConnectorsDropdownComponent: React.FC = () => {
|
||||
const [selectedConnector, selectConnector] = useState(connectors[0].value);
|
||||
const onChange = useCallback(connector => selectConnector(connector), [selectedConnector]);
|
||||
const [selectedConnector, setSelectedConnector] = useState(connectors[0].value);
|
||||
|
||||
return (
|
||||
<EuiSuperSelect
|
||||
options={connectors}
|
||||
valueOfSelected={selectedConnector}
|
||||
fullWidth
|
||||
onChange={onChange}
|
||||
onChange={setSelectedConnector}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import * as i18n from './translations';
|
||||
import { FieldMappingRow } from './field_mapping_row';
|
||||
|
||||
const FieldRowWrapper = styled.div`
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const supportedThirdPartyFields = [
|
||||
{
|
||||
value: 'short_description',
|
||||
inputDisplay: <span>{'Short Description'}</span>,
|
||||
},
|
||||
{
|
||||
value: 'comment',
|
||||
inputDisplay: <span>{'Comment'}</span>,
|
||||
},
|
||||
{
|
||||
value: 'tags',
|
||||
inputDisplay: <span>{'Tags'}</span>,
|
||||
},
|
||||
{
|
||||
value: 'description',
|
||||
inputDisplay: <span>{'Description'}</span>,
|
||||
},
|
||||
];
|
||||
|
||||
const FieldMappingComponent: React.FC = () => (
|
||||
<EuiDescribedFormGroup
|
||||
fullWidth
|
||||
title={<h3>{i18n.FIELD_MAPPING_TITLE}</h3>}
|
||||
description={i18n.FIELD_MAPPING_DESC}
|
||||
>
|
||||
<EuiFormRow fullWidth>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<span className="euiFormLabel">{i18n.FIELD_MAPPING_FIRST_COL}</span>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<span className="euiFormLabel">{i18n.FIELD_MAPPING_SECOND_COL}</span>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<span className="euiFormLabel">{i18n.FIELD_MAPPING_THIRD_COL}</span>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFormRow>
|
||||
<FieldRowWrapper>
|
||||
<FieldMappingRow siemField="Name" thirdPartyOptions={supportedThirdPartyFields} />
|
||||
<FieldMappingRow siemField="Tags" thirdPartyOptions={supportedThirdPartyFields} />
|
||||
<FieldMappingRow siemField="Description" thirdPartyOptions={supportedThirdPartyFields} />
|
||||
<FieldMappingRow siemField="Comment" thirdPartyOptions={supportedThirdPartyFields} />
|
||||
</FieldRowWrapper>
|
||||
</EuiDescribedFormGroup>
|
||||
);
|
||||
|
||||
export const FieldMapping = React.memo(FieldMappingComponent);
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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 } from 'react';
|
||||
import { EuiFlexItem, EuiFlexGroup, EuiSuperSelect, EuiIcon } from '@elastic/eui';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
||||
interface ThirdPartyField {
|
||||
value: string;
|
||||
inputDisplay: JSX.Element;
|
||||
}
|
||||
interface RowProps {
|
||||
siemField: string;
|
||||
thirdPartyOptions: ThirdPartyField[];
|
||||
}
|
||||
|
||||
const editUpdateOptions = [
|
||||
{
|
||||
value: 'nothing',
|
||||
inputDisplay: <span>{i18n.FIELD_MAPPING_EDIT_NOTHING}</span>,
|
||||
'data-test-subj': 'edit-update-option-nothing',
|
||||
},
|
||||
{
|
||||
value: 'overwrite',
|
||||
inputDisplay: <span>{i18n.FIELD_MAPPING_EDIT_OVERWRITE}</span>,
|
||||
'data-test-subj': 'edit-update-option-overwrite',
|
||||
},
|
||||
{
|
||||
value: 'append',
|
||||
inputDisplay: <span>{i18n.FIELD_MAPPING_EDIT_APPEND}</span>,
|
||||
'data-test-subj': 'edit-update-option-append',
|
||||
},
|
||||
];
|
||||
|
||||
const FieldMappingRowComponent: React.FC<RowProps> = ({ siemField, thirdPartyOptions }) => {
|
||||
const [selectedEditUpdate, setSelectedEditUpdate] = useState(editUpdateOptions[0].value);
|
||||
const [selectedThirdParty, setSelectedThirdParty] = useState(thirdPartyOptions[0].value);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup component="span" justifyContent="spaceBetween">
|
||||
<EuiFlexItem component="span" grow={false}>
|
||||
{siemField}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem component="span" grow={false}>
|
||||
<EuiIcon type="sortRight" />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiSuperSelect
|
||||
options={thirdPartyOptions}
|
||||
valueOfSelected={selectedThirdParty}
|
||||
onChange={setSelectedThirdParty}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiSuperSelect
|
||||
options={editUpdateOptions}
|
||||
valueOfSelected={selectedEditUpdate}
|
||||
onChange={setSelectedEditUpdate}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const FieldMappingRow = React.memo(FieldMappingRowComponent);
|
|
@ -35,3 +35,103 @@ export const NO_CONNECTOR = i18n.translate('xpack.siem.case.configureCases.noCon
|
|||
export const ADD_NEW_CONNECTOR = i18n.translate('xpack.siem.case.configureCases.addNewConnector', {
|
||||
defaultMessage: 'Add new connector option',
|
||||
});
|
||||
|
||||
export const CASE_CLOSURE_OPTIONS_TITLE = i18n.translate(
|
||||
'xpack.siem.case.configureCases.caseClosureOptionsTitle',
|
||||
{
|
||||
defaultMessage: 'Cases Closures',
|
||||
}
|
||||
);
|
||||
|
||||
export const CASE_CLOSURE_OPTIONS_DESC = i18n.translate(
|
||||
'xpack.siem.case.configureCases.caseClosureOptionsDesc',
|
||||
{
|
||||
defaultMessage:
|
||||
'Define how you wish SIEM cases to be closed. Automated case closures require an established connection to a third-party incident management system.',
|
||||
}
|
||||
);
|
||||
|
||||
export const CASE_CLOSURE_OPTIONS_LABEL = i18n.translate(
|
||||
'xpack.siem.case.configureCases.caseClosureOptionsLabel',
|
||||
{
|
||||
defaultMessage: 'Case closure options',
|
||||
}
|
||||
);
|
||||
|
||||
export const CASE_CLOSURE_OPTIONS_MANUAL = i18n.translate(
|
||||
'xpack.siem.case.configureCases.caseClosureOptionsManual',
|
||||
{
|
||||
defaultMessage: 'Manually close SIEM cases',
|
||||
}
|
||||
);
|
||||
|
||||
export const CASE_CLOSURE_OPTIONS_NEW_INCIDENT = i18n.translate(
|
||||
'xpack.siem.case.configureCases.caseClosureOptionsNewIncident',
|
||||
{
|
||||
defaultMessage: 'Automatically close SIEM cases when pushing new incident to third-party',
|
||||
}
|
||||
);
|
||||
|
||||
export const CASE_CLOSURE_OPTIONS_CLOSED_INCIDENT = i18n.translate(
|
||||
'xpack.siem.case.configureCases.caseClosureOptionsClosedIncident',
|
||||
{
|
||||
defaultMessage: 'Automatically close SIEM cases when incident is closed in third-party',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_TITLE = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingTitle',
|
||||
{
|
||||
defaultMessage: 'Field mappings',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_DESC = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingDesc',
|
||||
{
|
||||
defaultMessage:
|
||||
'Map SIEM case fields when pushing data to a third-party. Field mappings require an established connection to a third-party incident management system.',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_FIRST_COL = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingFirstCol',
|
||||
{
|
||||
defaultMessage: 'SIEM case field',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_SECOND_COL = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingSecondCol',
|
||||
{
|
||||
defaultMessage: 'Third-party incident field',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_THIRD_COL = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingThirdCol',
|
||||
{
|
||||
defaultMessage: 'On edit and update',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_EDIT_NOTHING = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingEditNothing',
|
||||
{
|
||||
defaultMessage: 'Nothing',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_EDIT_OVERWRITE = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingEditOverwrite',
|
||||
{
|
||||
defaultMessage: 'Overwrite',
|
||||
}
|
||||
);
|
||||
|
||||
export const FIELD_MAPPING_EDIT_APPEND = i18n.translate(
|
||||
'xpack.siem.case.configureCases.fieldMappingEditAppend',
|
||||
{
|
||||
defaultMessage: 'Append',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -14,6 +14,8 @@ import { getCaseUrl } from '../../components/link_to';
|
|||
import { WhitePageWrapper, SectionWrapper } from './components/wrappers';
|
||||
import { Connectors } from './components/configure_cases/connectors';
|
||||
import * as i18n from './translations';
|
||||
import { ClosureOptions } from './components/configure_cases/closure_options';
|
||||
import { FieldMapping } from './components/configure_cases/field_mapping';
|
||||
|
||||
const backOptions = {
|
||||
href: getCaseUrl(),
|
||||
|
@ -26,8 +28,12 @@ const wrapperPageStyle: Record<string, string> = {
|
|||
paddingBottom: '0',
|
||||
};
|
||||
|
||||
export const FormWrapper = styled.div`
|
||||
const FormWrapper = styled.div`
|
||||
${({ theme }) => css`
|
||||
& > * {
|
||||
margin-top 40px;
|
||||
}
|
||||
|
||||
padding-top: ${theme.eui.paddingSizes.l};
|
||||
padding-bottom: ${theme.eui.paddingSizes.l};
|
||||
`}
|
||||
|
@ -44,6 +50,12 @@ const ConfigureCasesPageComponent: React.FC = () => (
|
|||
<SectionWrapper>
|
||||
<Connectors />
|
||||
</SectionWrapper>
|
||||
<SectionWrapper>
|
||||
<ClosureOptions />
|
||||
</SectionWrapper>
|
||||
<SectionWrapper>
|
||||
<FieldMapping />
|
||||
</SectionWrapper>
|
||||
</FormWrapper>
|
||||
</WhitePageWrapper>
|
||||
</WrapperPage>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue