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

[7.7] [SIEM] [Cases] Insert timeline and reporters/tags in table bug fixes (#63642) #63658

Merged
merged 2 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const mockLocationWithState = {
state: {
insertTimeline: {
timelineId: 'timeline-id',
timelineSavedObjectId: '34578-3497-5893-47589-34759',
timelineTitle: 'Timeline title',
},
},
Expand All @@ -49,7 +50,7 @@ describe('Insert timeline popover ', () => {
payload: { id: 'timeline-id', show: false },
type: 'x-pack/siem/local/timeline/SHOW_TIMELINE',
});
expect(onTimelineChange).toBeCalledWith('Timeline title', 'timeline-id');
expect(onTimelineChange).toBeCalledWith('Timeline title', '34578-3497-5893-47589-34759');
});
it('should do nothing when router state', () => {
jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface InsertTimelinePopoverProps {
interface RouterState {
insertTimeline: {
timelineId: string;
timelineSavedObjectId: string;
timelineTitle: string;
};
}
Expand All @@ -46,7 +47,7 @@ export const InsertTimelinePopoverComponent: React.FC<Props> = ({
);
onTimelineChange(
routerState.insertTimeline.timelineTitle,
routerState.insertTimeline.timelineId
routerState.insertTimeline.timelineSavedObjectId
);
setRouterState(null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import React, { useCallback } from 'react';
import uuid from 'uuid';
import styled from 'styled-components';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';

import { Note } from '../../../lib/note';
import { Notes } from '../../notes';
Expand All @@ -29,6 +30,8 @@ import { NOTES_PANEL_WIDTH } from './notes_size';
import { ButtonContainer, DescriptionContainer, LabelText, NameField, StyledStar } from './styles';
import * as i18n from './translations';
import { SiemPageName } from '../../../pages/home/types';
import { timelineSelectors } from '../../../store/timeline';
import { State } from '../../../store';

export const historyToolTip = 'The chronological history of actions related to this timeline';
export const streamLiveToolTip = 'Update the Timeline as new data arrives';
Expand Down Expand Up @@ -121,13 +124,17 @@ interface NewCaseProps {

export const NewCase = React.memo<NewCaseProps>(({ onClosePopover, timelineId, timelineTitle }) => {
const history = useHistory();
const { savedObjectId } = useSelector((state: State) =>
timelineSelectors.selectTimeline(state, timelineId)
);
const handleClick = useCallback(() => {
onClosePopover();
history.push({
pathname: `/${SiemPageName.case}/create`,
state: {
insertTimeline: {
timelineId,
timelineSavedObjectId: savedObjectId,
timelineTitle: timelineTitle.length > 0 ? timelineTitle : i18n.UNTITLED_TIMELINE,
},
},
Expand Down
13 changes: 10 additions & 3 deletions x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ type Action =
| { type: 'FETCH_SUCCESS'; payload: string[] }
| { type: 'FETCH_FAILURE' };

export interface UseGetTags extends TagsState {
fetchTags: () => void;
}

const dataFetchReducer = (state: TagsState, action: Action): TagsState => {
switch (action.type) {
case 'FETCH_INIT':
Expand Down Expand Up @@ -47,15 +51,15 @@ const dataFetchReducer = (state: TagsState, action: Action): TagsState => {
};
const initialData: string[] = [];

export const useGetTags = (): TagsState => {
export const useGetTags = (): UseGetTags => {
const [state, dispatch] = useReducer(dataFetchReducer, {
isLoading: false,
isError: false,
tags: initialData,
});
const [, dispatchToaster] = useStateToaster();

useEffect(() => {
const callFetch = () => {
let didCancel = false;
const abortCtrl = new AbortController();

Expand All @@ -82,6 +86,9 @@ export const useGetTags = (): TagsState => {
abortCtrl.abort();
didCancel = true;
};
};
useEffect(() => {
callFetch();
}, []);
return state;
return { ...state, fetchTags: callFetch };
};
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 React, { useCallback, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
EuiBasicTable,
EuiButton,
Expand Down Expand Up @@ -129,13 +129,25 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
id: '',
});
const [deleteBulk, setDeleteBulk] = useState<DeleteCase[]>([]);

const refreshCases = useCallback(() => {
refetchCases(filterOptions, queryParams);
fetchCasesStatus();
setSelectedCases([]);
setDeleteBulk([]);
}, [filterOptions, queryParams]);
const filterRefetch = useRef<() => void>();
const setFilterRefetch = useCallback(
(refetchFilter: () => void) => {
filterRefetch.current = refetchFilter;
},
[filterRefetch.current]
);
const refreshCases = useCallback(
(dataRefresh = true) => {
if (dataRefresh) refetchCases(filterOptions, queryParams);
fetchCasesStatus();
setSelectedCases([]);
setDeleteBulk([]);
if (filterRefetch.current != null) {
filterRefetch.current();
}
},
[filterOptions, queryParams, filterRefetch.current]
);

useEffect(() => {
if (isDeleted) {
Expand Down Expand Up @@ -247,6 +259,7 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
};
}
setQueryParams(newQueryParams);
refreshCases(false);
},
[queryParams]
);
Expand All @@ -259,6 +272,7 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
setQueryParams({ sortField: SortFieldCase.createdAt });
}
setFilters(newFilterOptions);
refreshCases(false);
},
[filterOptions, queryParams]
);
Expand Down Expand Up @@ -347,6 +361,7 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
tags: filterOptions.tags,
status: filterOptions.status,
}}
setFilterRefetch={setFilterRefetch}
/>
{isCasesLoading && isDataEmpty ? (
<Div>
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 React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { isEqual } from 'lodash/fp';
import {
EuiFieldSearch,
Expand All @@ -25,6 +25,7 @@ interface CasesTableFiltersProps {
countOpenCases: number | null;
onFilterChanged: (filterOptions: Partial<FilterOptions>) => void;
initial: FilterOptions;
setFilterRefetch: (val: () => void) => void;
}

/**
Expand All @@ -41,15 +42,37 @@ const CasesTableFiltersComponent = ({
countOpenCases,
onFilterChanged,
initial = defaultInitial,
setFilterRefetch,
}: CasesTableFiltersProps) => {
const [selectedReporters, setselectedReporters] = useState(
initial.reporters.map(r => r.full_name ?? r.username ?? '')
);
const [search, setSearch] = useState(initial.search);
const [selectedTags, setSelectedTags] = useState(initial.tags);
const [showOpenCases, setShowOpenCases] = useState(initial.status === 'open');
const { tags } = useGetTags();
const { reporters, respReporters } = useGetReporters();
const { tags, fetchTags } = useGetTags();
const { reporters, respReporters, fetchReporters } = useGetReporters();
const refetch = useCallback(() => {
fetchTags();
fetchReporters();
}, [fetchReporters, fetchTags]);
useEffect(() => {
if (setFilterRefetch != null) {
setFilterRefetch(refetch);
}
}, [refetch, setFilterRefetch]);
useEffect(() => {
if (selectedReporters.length) {
const newReporters = selectedReporters.filter(r => reporters.includes(r));
handleSelectedReporters(newReporters);
}
}, [reporters]);
useEffect(() => {
if (selectedTags.length) {
const newTags = selectedTags.filter(t => tags.includes(t));
handleSelectedTags(newTags);
}
}, [tags]);

const handleSelectedReporters = useCallback(
newReporters => {
Expand Down