mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* [SIEM] [Cases] Insert timeline and reporters/tags in table bug fixes (#63642) * fix type err
This commit is contained in:
parent
9ef8a99779
commit
a9b3d3036c
6 changed files with 70 additions and 16 deletions
|
@ -26,6 +26,7 @@ const mockLocationWithState = {
|
|||
state: {
|
||||
insertTimeline: {
|
||||
timelineId: 'timeline-id',
|
||||
timelineSavedObjectId: '34578-3497-5893-47589-34759',
|
||||
timelineTitle: 'Timeline title',
|
||||
},
|
||||
},
|
||||
|
@ -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);
|
||||
|
|
|
@ -23,6 +23,7 @@ interface InsertTimelinePopoverProps {
|
|||
interface RouterState {
|
||||
insertTimeline: {
|
||||
timelineId: string;
|
||||
timelineSavedObjectId: string;
|
||||
timelineTitle: string;
|
||||
};
|
||||
}
|
||||
|
@ -46,7 +47,7 @@ export const InsertTimelinePopoverComponent: React.FC<Props> = ({
|
|||
);
|
||||
onTimelineChange(
|
||||
routerState.insertTimeline.timelineTitle,
|
||||
routerState.insertTimeline.timelineId
|
||||
routerState.insertTimeline.timelineSavedObjectId
|
||||
);
|
||||
setRouterState(null);
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -121,6 +124,9 @@ 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({
|
||||
|
@ -128,6 +134,7 @@ export const NewCase = React.memo<NewCaseProps>(({ onClosePopover, timelineId, t
|
|||
state: {
|
||||
insertTimeline: {
|
||||
timelineId,
|
||||
timelineSavedObjectId: savedObjectId,
|
||||
timelineTitle: timelineTitle.length > 0 ? timelineTitle : i18n.UNTITLED_TIMELINE,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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':
|
||||
|
@ -47,7 +51,7 @@ 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,
|
||||
|
@ -55,7 +59,7 @@ export const useGetTags = (): TagsState => {
|
|||
});
|
||||
const [, dispatchToaster] = useStateToaster();
|
||||
|
||||
useEffect(() => {
|
||||
const callFetch = () => {
|
||||
let didCancel = false;
|
||||
const abortCtrl = new AbortController();
|
||||
|
||||
|
@ -82,6 +86,9 @@ export const useGetTags = (): TagsState => {
|
|||
abortCtrl.abort();
|
||||
didCancel = true;
|
||||
};
|
||||
};
|
||||
useEffect(() => {
|
||||
callFetch();
|
||||
}, []);
|
||||
return state;
|
||||
return { ...state, fetchTags: callFetch };
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -247,6 +259,7 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
|
|||
};
|
||||
}
|
||||
setQueryParams(newQueryParams);
|
||||
refreshCases(false);
|
||||
},
|
||||
[queryParams]
|
||||
);
|
||||
|
@ -259,6 +272,7 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
|
|||
setQueryParams({ sortField: SortFieldCase.createdAt });
|
||||
}
|
||||
setFilters(newFilterOptions);
|
||||
refreshCases(false);
|
||||
},
|
||||
[filterOptions, queryParams]
|
||||
);
|
||||
|
@ -347,6 +361,7 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
|
|||
tags: filterOptions.tags,
|
||||
status: filterOptions.status,
|
||||
}}
|
||||
setFilterRefetch={setFilterRefetch}
|
||||
/>
|
||||
{isCasesLoading && isDataEmpty ? (
|
||||
<Div>
|
||||
|
|
|
@ -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,
|
||||
|
@ -25,6 +25,7 @@ interface CasesTableFiltersProps {
|
|||
countOpenCases: number | null;
|
||||
onFilterChanged: (filterOptions: Partial<FilterOptions>) => void;
|
||||
initial: FilterOptions;
|
||||
setFilterRefetch: (val: () => void) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,6 +42,7 @@ const CasesTableFiltersComponent = ({
|
|||
countOpenCases,
|
||||
onFilterChanged,
|
||||
initial = defaultInitial,
|
||||
setFilterRefetch,
|
||||
}: CasesTableFiltersProps) => {
|
||||
const [selectedReporters, setselectedReporters] = useState(
|
||||
initial.reporters.map(r => r.full_name ?? r.username ?? '')
|
||||
|
@ -48,8 +50,29 @@ const CasesTableFiltersComponent = ({
|
|||
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 => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue