Skip to content

Commit

Permalink
Merge branch 'master' into Tests_Host-Detail
Browse files Browse the repository at this point in the history
  • Loading branch information
charlie-pichette committed Mar 30, 2020
2 parents 69499d8 + a373677 commit b296c8b
Show file tree
Hide file tree
Showing 85 changed files with 740 additions and 459 deletions.
10 changes: 8 additions & 2 deletions x-pack/legacy/plugins/maps/public/angular/map_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,15 @@ app.controller(
const layerListConfigOnly = copyPersistentState(layerList);

const savedLayerList = savedMap.getLayerList();
const oldConfig = savedLayerList ? savedLayerList : initialLayerListConfig;

return !_.isEqual(layerListConfigOnly, oldConfig);
return !savedLayerList
? !_.isEqual(layerListConfigOnly, initialLayerListConfig)
: // savedMap stores layerList as a JSON string using JSON.stringify.
// JSON.stringify removes undefined properties from objects.
// savedMap.getLayerList converts the JSON string back into Javascript array of objects.
// Need to perform the same process for layerListConfigOnly to compare apples to apples
// and avoid undefined properties in layerListConfigOnly triggering unsaved changes.
!_.isEqual(JSON.parse(JSON.stringify(layerListConfigOnly)), savedLayerList);
}

function isOnMapNow() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ export function DynamicColorForm({
};
if (type === COLOR_MAP_TYPE.ORDINAL) {
newColorOptions.useCustomColorRamp = useCustomColorMap;
newColorOptions.customColorRamp = customColorMap;
newColorOptions.color = color;
if (customColorMap) {
newColorOptions.customColorRamp = customColorMap;
}
if (color) {
newColorOptions.color = color;
}
} else {
newColorOptions.useCustomColorPalette = useCustomColorMap;
newColorOptions.customColorPalette = customColorMap;
newColorOptions.colorCategory = color;
if (customColorMap) {
newColorOptions.customColorPalette = customColorMap;
}
if (color) {
newColorOptions.colorCategory = color;
}
}

onDynamicStyleChange(styleProperty.getStyleName(), newColorOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiButtonIcon, EuiPopover, EuiSelectableOption } from '@elastic/eui';
import { EuiButtonIcon, EuiPopover, EuiSelectableOption, EuiToolTip } from '@elastic/eui';
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useDispatch } from 'react-redux';
Expand Down Expand Up @@ -62,13 +62,15 @@ export const InsertTimelinePopoverComponent: React.FC<Props> = ({

const insertTimelineButton = useMemo(
() => (
<EuiButtonIcon
aria-label={i18n.INSERT_TIMELINE}
data-test-subj="insert-timeline-button"
iconType="timeline"
isDisabled={isDisabled}
onClick={handleOpenPopover}
/>
<EuiToolTip position="top" content={<p>{i18n.INSERT_TIMELINE}</p>}>
<EuiButtonIcon
aria-label={i18n.INSERT_TIMELINE}
data-test-subj="insert-timeline-button"
iconType="timeline"
isDisabled={isDisabled}
onClick={handleOpenPopover}
/>
</EuiToolTip>
),
[handleOpenPopover, isDisabled]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ export const SEARCH_BOX_TIMELINE_PLACEHOLDER = i18n.translate(
);

export const INSERT_TIMELINE = i18n.translate('xpack.siem.insert.timeline.insertTimelineButton', {
defaultMessage: 'Insert Timeline…',
defaultMessage: 'Insert timeline link',
});
40 changes: 40 additions & 0 deletions x-pack/legacy/plugins/siem/public/containers/case/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,46 @@ export const ERROR_TITLE = i18n.translate('xpack.siem.containers.case.errorTitle
defaultMessage: 'Error fetching data',
});

export const ERROR_DELETING = i18n.translate('xpack.siem.containers.case.errorDeletingTitle', {
defaultMessage: 'Error deleting data',
});

export const UPDATED_CASE = (caseTitle: string) =>
i18n.translate('xpack.siem.containers.case.updatedCase', {
values: { caseTitle },
defaultMessage: 'Updated "{caseTitle}"',
});

export const DELETED_CASES = (totalCases: number, caseTitle?: string) =>
i18n.translate('xpack.siem.containers.case.deletedCases', {
values: { caseTitle, totalCases },
defaultMessage: 'Deleted {totalCases, plural, =1 {"{caseTitle}"} other {{totalCases} cases}}',
});

export const CLOSED_CASES = ({
totalCases,
caseTitle,
}: {
totalCases: number;
caseTitle?: string;
}) =>
i18n.translate('xpack.siem.containers.case.closedCases', {
values: { caseTitle, totalCases },
defaultMessage: 'Closed {totalCases, plural, =1 {"{caseTitle}"} other {{totalCases} cases}}',
});

export const REOPENED_CASES = ({
totalCases,
caseTitle,
}: {
totalCases: number;
caseTitle?: string;
}) =>
i18n.translate('xpack.siem.containers.case.reopenedCases', {
values: { caseTitle, totalCases },
defaultMessage: 'Reopened {totalCases, plural, =1 {"{caseTitle}"} other {{totalCases} cases}}',
});

export const TAG_FETCH_FAILURE = i18n.translate(
'xpack.siem.containers.case.tagFetchFailDescription',
{
Expand Down
5 changes: 5 additions & 0 deletions x-pack/legacy/plugins/siem/public/containers/case/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,8 @@ export interface ActionLicense {
enabledInConfig: boolean;
enabledInLicense: boolean;
}

export interface DeleteCase {
id: string;
title?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { useCallback, useReducer } from 'react';
import { errorToToaster, useStateToaster } from '../../components/toasters';
import { displaySuccessToast, errorToToaster, useStateToaster } from '../../components/toasters';
import * as i18n from './translations';
import { patchCasesStatus } from './api';
import { BulkUpdateStatus, Case } from './types';
Expand Down Expand Up @@ -71,9 +71,22 @@ export const useUpdateCases = (): UseUpdateCase => {
const patchData = async () => {
try {
dispatch({ type: 'FETCH_INIT' });
await patchCasesStatus(cases, abortCtrl.signal);
const patchResponse = await patchCasesStatus(cases, abortCtrl.signal);
if (!cancel) {
const resultCount = Object.keys(patchResponse).length;
const firstTitle = patchResponse[0].title;

dispatch({ type: 'FETCH_SUCCESS', payload: true });
const messageArgs = {
totalCases: resultCount,
caseTitle: resultCount === 1 ? firstTitle : '',
};
const message =
resultCount && patchResponse[0].status === 'open'
? i18n.REOPENED_CASES(messageArgs)
: i18n.CLOSED_CASES(messageArgs);

displaySuccessToast(message, dispatchToaster);
}
} catch (error) {
if (!cancel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
*/

import { useCallback, useReducer } from 'react';
import { errorToToaster, useStateToaster } from '../../components/toasters';
import { displaySuccessToast, errorToToaster, useStateToaster } from '../../components/toasters';
import * as i18n from './translations';
import { deleteCases } from './api';
import { DeleteCase } from './types';

interface DeleteState {
isDisplayConfirmDeleteModal: boolean;
Expand Down Expand Up @@ -57,9 +58,10 @@ const dataFetchReducer = (state: DeleteState, action: Action): DeleteState => {
return state;
}
};

interface UseDeleteCase extends DeleteState {
dispatchResetIsDeleted: () => void;
handleOnDeleteConfirm: (caseIds: string[]) => void;
handleOnDeleteConfirm: (caseIds: DeleteCase[]) => void;
handleToggleModal: () => void;
}

Expand All @@ -72,21 +74,26 @@ export const useDeleteCases = (): UseDeleteCase => {
});
const [, dispatchToaster] = useStateToaster();

const dispatchDeleteCases = useCallback((caseIds: string[]) => {
const dispatchDeleteCases = useCallback((cases: DeleteCase[]) => {
let cancel = false;
const abortCtrl = new AbortController();

const deleteData = async () => {
try {
dispatch({ type: 'FETCH_INIT' });
const caseIds = cases.map(theCase => theCase.id);
await deleteCases(caseIds, abortCtrl.signal);
if (!cancel) {
dispatch({ type: 'FETCH_SUCCESS', payload: true });
displaySuccessToast(
i18n.DELETED_CASES(cases.length, cases.length === 1 ? cases[0].title : ''),
dispatchToaster
);
}
} catch (error) {
if (!cancel) {
errorToToaster({
title: i18n.ERROR_TITLE,
title: i18n.ERROR_DELETING,
error: error.body && error.body.message ? new Error(error.body.message) : error,
dispatchToaster,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/

import { useReducer, useCallback } from 'react';
import { displaySuccessToast, errorToToaster, useStateToaster } from '../../components/toasters';
import { CasePatchRequest } from '../../../../../../plugins/case/common/api';
import { errorToToaster, useStateToaster } from '../../components/toasters';

import { patchCase } from './api';
import * as i18n from './translations';
Expand Down Expand Up @@ -94,6 +94,7 @@ export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase =>
updateCase(response[0]);
}
dispatch({ type: 'FETCH_SUCCESS' });
displaySuccessToast(i18n.UPDATED_CASE(response[0].title), dispatchToaster);
}
} catch (error) {
if (!cancel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe('AllCases', () => {
.last()
.simulate('click');
expect(handleOnDeleteConfirm.mock.calls[0][0]).toStrictEqual(
useGetCasesMockState.data.cases.map(theCase => theCase.id)
useGetCasesMockState.data.cases.map(({ id }) => ({ id }))
);
});
it('Bulk close status update', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import styled, { css } from 'styled-components';
import * as i18n from './translations';

import { getCasesColumns } from './columns';
import { Case, FilterOptions, SortFieldCase } from '../../../../containers/case/types';
import { Case, DeleteCase, FilterOptions, SortFieldCase } from '../../../../containers/case/types';
import { useGetCases, UpdateCase } from '../../../../containers/case/use_get_cases';
import { useGetCasesStatus } from '../../../../containers/case/use_get_cases_status';
import { useDeleteCases } from '../../../../containers/case/use_delete_cases';
Expand Down Expand Up @@ -107,11 +107,24 @@ export const AllCases = React.memo(() => {
isDisplayConfirmDeleteModal,
} = useDeleteCases();

const { dispatchResetIsUpdated, isUpdated, updateBulkStatus } = useUpdateCases();
// Update case
const {
dispatchResetIsUpdated,
isLoading: isUpdating,
isUpdated,
updateBulkStatus,
} = useUpdateCases();
const [deleteThisCase, setDeleteThisCase] = useState({
title: '',
id: '',
});
const [deleteBulk, setDeleteBulk] = useState<DeleteCase[]>([]);

const refreshCases = useCallback(() => {
refetchCases(filterOptions, queryParams);
fetchCasesStatus();
setSelectedCases([]);
setDeleteBulk([]);
}, [filterOptions, queryParams]);

useEffect(() => {
Expand All @@ -124,11 +137,6 @@ export const AllCases = React.memo(() => {
dispatchResetIsUpdated();
}
}, [isDeleted, isUpdated]);
const [deleteThisCase, setDeleteThisCase] = useState({
title: '',
id: '',
});
const [deleteBulk, setDeleteBulk] = useState<string[]>([]);
const confirmDeleteModal = useMemo(
() => (
<ConfirmDeleteCaseModal
Expand All @@ -138,7 +146,7 @@ export const AllCases = React.memo(() => {
onCancel={handleToggleModal}
onConfirm={handleOnDeleteConfirm.bind(
null,
deleteBulk.length > 0 ? deleteBulk : [deleteThisCase.id]
deleteBulk.length > 0 ? deleteBulk : [deleteThisCase]
)}
/>
),
Expand All @@ -150,10 +158,20 @@ export const AllCases = React.memo(() => {
setDeleteThisCase(deleteCase);
}, []);

const toggleBulkDeleteModal = useCallback((deleteCases: string[]) => {
handleToggleModal();
setDeleteBulk(deleteCases);
}, []);
const toggleBulkDeleteModal = useCallback(
(caseIds: string[]) => {
handleToggleModal();
if (caseIds.length === 1) {
const singleCase = selectedCases.find(theCase => theCase.id === caseIds[0]);
if (singleCase) {
return setDeleteThisCase({ id: singleCase.id, title: singleCase.title });
}
}
const convertToDeleteCases: DeleteCase[] = caseIds.map(id => ({ id }));
setDeleteBulk(convertToDeleteCases);
},
[selectedCases]
);

const handleUpdateCaseStatus = useCallback(
(status: string) => {
Expand Down Expand Up @@ -289,7 +307,7 @@ export const AllCases = React.memo(() => {
</EuiFlexItem>
</EuiFlexGroup>
</CaseHeaderPage>
{(isCasesLoading || isDeleting) && !isDataEmpty && (
{(isCasesLoading || isDeleting || isUpdating) && !isDataEmpty && (
<ProgressLoader size="xs" color="accent" className="essentialAnimation" />
)}
<Panel loading={isCasesLoading}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ describe('CaseView actions', () => {

expect(wrapper.find('[data-test-subj="confirm-delete-case-modal"]').exists()).toBeTruthy();
wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click');
expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([data.id]);
expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([{ id: data.id, title: data.title }]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const CaseViewActionsComponent: React.FC<CaseViewActions> = ({ caseData }) => {
isModalVisible={isDisplayConfirmDeleteModal}
isPlural={false}
onCancel={handleToggleModal}
onConfirm={handleOnDeleteConfirm.bind(null, [caseData.id])}
onConfirm={handleOnDeleteConfirm.bind(null, [{ id: caseData.id, title: caseData.title }])}
/>
),
[isDisplayConfirmDeleteModal, caseData]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ export const REQUIRED_UPDATE_TO_SERVICE = i18n.translate(
}
);

export const COPY_LINK_COMMENT = i18n.translate('xpack.siem.case.caseView.copyCommentLinkAria', {
defaultMessage: 'click to copy comment link',
export const COPY_REFERENCE_LINK = i18n.translate('xpack.siem.case.caseView.copyCommentLinkAria', {
defaultMessage: 'Copy reference link',
});

export const MOVE_TO_ORIGINAL_COMMENT = i18n.translate(
'xpack.siem.case.caseView.moveToCommentAria',
{
defaultMessage: 'click to highlight the reference comment',
defaultMessage: 'Highlight the referenced comment',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export const UserActionItem = ({
labelQuoteAction={labelQuoteAction}
labelTitle={labelTitle ?? <></>}
linkId={linkId}
fullName={fullName}
username={username}
updatedAt={updatedAt}
onEdit={onEdit}
Expand Down
Loading

0 comments on commit b296c8b

Please sign in to comment.