mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Cases] Integrate routes and navigation (#117582)
* getCases function and router * all pages router * navigation hooks created * external navigations removed * basePath in cases context * context optimization * no privileges screen * new files * CasesDeepLinkIds constant renamed * remove props spreading * AllCasesList tests * Fix types and tests: Part 1 * Fix types and tests: Part 2 * Move glasses badge logic inside cases * Fix export types * Improve helpers * observability changes integrated * Small fixes * Fix timelines unit tests * Add readonly badge test * test fixed * form context test fixed * fix breadcrumbs test * fix types in o11y routes * Fix more tests * Fix bug * urlType fixes * Fix cypress tests * configure header conflict solved * Fix i18n * fix breadcrumbs test * tests and suggestions * Add navigation tests * README updated * update plugin list docs * Add more tests * Fix i18n * More tests * Fix README * Fix types * fix resolve redirect paths * fix flyout z-index on timeline * add flyout z-index class comment * use kibana currentAppId and application observables instead of passing props * Get application info from the hook * Fix tests * Fix more tests * tests fixed * Fix container tests * Fix container tests * test updated Co-authored-by: Christos Nasikas <christos.nasikas@elastic.co>
This commit is contained in:
parent
d6217470e6
commit
4eb797a8b2
210 changed files with 4031 additions and 6574 deletions
|
@ -7,7 +7,11 @@
|
|||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { TestProviders, mockGetAllCasesSelectorModal } from '../../../../mock';
|
||||
import {
|
||||
TestProviders,
|
||||
mockGetAllCasesSelectorModal,
|
||||
mockGetCreateCaseFlyout,
|
||||
} from '../../../../mock';
|
||||
import { AddToCaseAction } from './add_to_case_action';
|
||||
import { SECURITY_SOLUTION_OWNER } from '../../../../../../cases/common';
|
||||
import { AddToCaseActionButton } from './add_to_case_action_button';
|
||||
|
@ -68,7 +72,7 @@ describe('AddToCaseAction', () => {
|
|||
expect(wrapper.find(`[data-test-subj="add-existing-case-menu-item"]`).exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('it opens the create case modal', () => {
|
||||
it('it opens the create case flyout', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<AddToCaseActionButton {...props} />
|
||||
|
@ -78,7 +82,7 @@ describe('AddToCaseAction', () => {
|
|||
|
||||
wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().simulate('click');
|
||||
wrapper.find(`[data-test-subj="add-new-case-item"]`).first().simulate('click');
|
||||
expect(wrapper.find('[data-test-subj="create-case-flyout"]').exists()).toBeTruthy();
|
||||
expect(mockGetCreateCaseFlyout).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('it opens the all cases modal', () => {
|
||||
|
@ -92,7 +96,7 @@ describe('AddToCaseAction', () => {
|
|||
wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().simulate('click');
|
||||
wrapper.find(`[data-test-subj="add-existing-case-menu-item"]`).first().simulate('click');
|
||||
|
||||
expect(wrapper.find('[data-test-subj="all-cases-modal"]')).toBeTruthy();
|
||||
expect(mockGetAllCasesSelectorModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('it set rule information as null when missing', () => {
|
||||
|
|
|
@ -12,12 +12,9 @@ import { TimelineItem } from '../../../../../common/';
|
|||
import { useAddToCase, normalizedEventFields } from '../../../../hooks/use_add_to_case';
|
||||
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { TimelinesStartServices } from '../../../../types';
|
||||
import { CreateCaseFlyout } from './create/flyout';
|
||||
import { tGridActions } from '../../../../';
|
||||
import * as i18n from './translations';
|
||||
|
||||
export interface AddToCaseActionProps {
|
||||
ariaLabel?: string;
|
||||
event?: TimelineItem;
|
||||
useInsertTimeline?: Function;
|
||||
casePermissions: {
|
||||
|
@ -31,7 +28,6 @@ export interface AddToCaseActionProps {
|
|||
}
|
||||
|
||||
const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
||||
ariaLabel = i18n.ACTION_ADD_TO_CASE_ARIA_LABEL,
|
||||
event,
|
||||
useInsertTimeline,
|
||||
casePermissions,
|
||||
|
@ -46,15 +42,13 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
|||
const { cases } = useKibana<TimelinesStartServices>().services;
|
||||
const {
|
||||
onCaseClicked,
|
||||
goToCreateCase,
|
||||
onCaseSuccess,
|
||||
attachAlertToCase,
|
||||
createCaseUrl,
|
||||
isAllCaseModalOpen,
|
||||
isCreateCaseFlyoutOpen,
|
||||
} = useAddToCase({ event, useInsertTimeline, casePermissions, appId, owner, onClose });
|
||||
} = useAddToCase({ event, casePermissions, appId, owner, onClose });
|
||||
|
||||
const getAllCasesSelectorModalProps = useMemo(() => {
|
||||
const allCasesSelectorModalProps = useMemo(() => {
|
||||
const { ruleId, ruleName } = normalizedEventFields(event);
|
||||
return {
|
||||
alertData: {
|
||||
|
@ -66,10 +60,6 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
|||
},
|
||||
owner,
|
||||
},
|
||||
createCaseNavigation: {
|
||||
href: createCaseUrl,
|
||||
onClick: goToCreateCase,
|
||||
},
|
||||
hooks: {
|
||||
useInsertTimeline,
|
||||
},
|
||||
|
@ -85,8 +75,6 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
|||
casePermissions?.crud,
|
||||
onCaseSuccess,
|
||||
onCaseClicked,
|
||||
createCaseUrl,
|
||||
goToCreateCase,
|
||||
eventId,
|
||||
eventIndex,
|
||||
dispatch,
|
||||
|
@ -99,19 +87,30 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
|||
dispatch(tGridActions.setOpenAddToNewCase({ id: eventId, isOpen: false }));
|
||||
}, [dispatch, eventId]);
|
||||
|
||||
const createCaseFlyoutProps = useMemo(() => {
|
||||
return {
|
||||
afterCaseCreated: attachAlertToCase,
|
||||
onClose: closeCaseFlyoutOpen,
|
||||
onSuccess: onCaseSuccess,
|
||||
useInsertTimeline,
|
||||
owner: [owner],
|
||||
disableAlerts,
|
||||
userCanCrud: casePermissions?.crud ?? false,
|
||||
};
|
||||
}, [
|
||||
attachAlertToCase,
|
||||
closeCaseFlyoutOpen,
|
||||
onCaseSuccess,
|
||||
useInsertTimeline,
|
||||
owner,
|
||||
disableAlerts,
|
||||
casePermissions,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isCreateCaseFlyoutOpen && (
|
||||
<CreateCaseFlyout
|
||||
afterCaseCreated={attachAlertToCase}
|
||||
onCloseFlyout={closeCaseFlyoutOpen}
|
||||
onSuccess={onCaseSuccess}
|
||||
useInsertTimeline={useInsertTimeline}
|
||||
owner={owner}
|
||||
disableAlerts={disableAlerts}
|
||||
/>
|
||||
)}
|
||||
{isAllCaseModalOpen && cases.getAllCasesSelectorModal(getAllCasesSelectorModalProps)}
|
||||
{isCreateCaseFlyoutOpen && cases.getCreateCaseFlyout(createCaseFlyoutProps)}
|
||||
{isAllCaseModalOpen && cases.getAllCasesSelectorModal(allCasesSelectorModalProps)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -20,7 +20,6 @@ import { ActionIconItem } from '../../action_icon_item';
|
|||
import * as i18n from './translations';
|
||||
|
||||
const AddToCaseActionButtonComponent: React.FC<AddToCaseActionProps> = ({
|
||||
ariaLabel = i18n.ACTION_ADD_TO_CASE_ARIA_LABEL,
|
||||
event,
|
||||
useInsertTimeline,
|
||||
casePermissions,
|
||||
|
@ -71,16 +70,16 @@ const AddToCaseActionButtonComponent: React.FC<AddToCaseActionProps> = ({
|
|||
() => (
|
||||
<EuiToolTip data-test-subj="attach-alert-to-case-tooltip" content={tooltipContext}>
|
||||
<EuiButtonIcon
|
||||
aria-label={ariaLabel}
|
||||
data-test-subj="attach-alert-to-case-button"
|
||||
size="s"
|
||||
iconType="folderClosed"
|
||||
onClick={openPopover}
|
||||
isDisabled={isDisabled}
|
||||
aria-label={tooltipContext}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
),
|
||||
[ariaLabel, isDisabled, openPopover, tooltipContext]
|
||||
[isDisabled, openPopover, tooltipContext]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -12,7 +12,11 @@ import { useAddToCase } from '../../../../hooks/use_add_to_case';
|
|||
import { AddToCaseActionProps } from './add_to_case_action';
|
||||
import * as i18n from './translations';
|
||||
|
||||
const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
||||
interface AddToCaseActionButtonProps extends AddToCaseActionProps {
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
const AddToCaseActionButtonComponent: React.FC<AddToCaseActionButtonProps> = ({
|
||||
ariaLabel = i18n.ACTION_ADD_TO_CASE_ARIA_LABEL,
|
||||
event,
|
||||
useInsertTimeline,
|
||||
|
@ -47,7 +51,7 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const AddToExistingCaseButton = memo(AddToCaseActionComponent);
|
||||
export const AddToExistingCaseButton = memo(AddToCaseActionButtonComponent);
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default AddToExistingCaseButton;
|
||||
|
|
|
@ -12,7 +12,11 @@ import { useAddToCase } from '../../../../hooks/use_add_to_case';
|
|||
import { AddToCaseActionProps } from './add_to_case_action';
|
||||
import * as i18n from './translations';
|
||||
|
||||
const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
||||
export interface AddToNewCaseButtonProps extends AddToCaseActionProps {
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
const AddToNewCaseButtonComponent: React.FC<AddToNewCaseButtonProps> = ({
|
||||
ariaLabel = i18n.ACTION_ADD_TO_CASE_ARIA_LABEL,
|
||||
event,
|
||||
useInsertTimeline,
|
||||
|
@ -48,7 +52,7 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const AddToNewCaseButton = memo(AddToCaseActionComponent);
|
||||
export const AddToNewCaseButton = memo(AddToNewCaseButtonComponent);
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default AddToNewCaseButton;
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import { CreateCaseFlyout } from './flyout';
|
||||
import { TestProviders } from '../../../../../mock';
|
||||
|
||||
const onCloseFlyout = jest.fn();
|
||||
const onSuccess = jest.fn();
|
||||
const defaultProps = {
|
||||
onCloseFlyout,
|
||||
onSuccess,
|
||||
owner: 'securitySolution',
|
||||
};
|
||||
|
||||
describe('CreateCaseFlyout', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<CreateCaseFlyout {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(wrapper.find(`[data-test-subj='create-case-flyout']`).exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Closing modal calls onCloseCaseModal', () => {
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<CreateCaseFlyout {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper.find(`[data-test-subj='euiFlyoutCloseButton']`).first().simulate('click');
|
||||
expect(onCloseFlyout).toBeCalled();
|
||||
});
|
||||
});
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import styled, { createGlobalStyle } from 'styled-components';
|
||||
import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui';
|
||||
|
||||
import * as i18n from '../translations';
|
||||
import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { Case } from '../../../../../../../cases/common';
|
||||
import type { TimelinesStartServices } from '../../../../../types';
|
||||
|
||||
export interface CreateCaseModalProps {
|
||||
afterCaseCreated?: (theCase: Case) => Promise<void>;
|
||||
onCloseFlyout: () => void;
|
||||
onSuccess: (theCase: Case) => Promise<void>;
|
||||
useInsertTimeline?: Function;
|
||||
owner: string;
|
||||
disableAlerts?: boolean;
|
||||
}
|
||||
|
||||
const StyledFlyout = styled(EuiFlyout)`
|
||||
${({ theme }) => `
|
||||
z-index: ${theme.eui.euiZLevel5};
|
||||
`}
|
||||
`;
|
||||
|
||||
const maskOverlayClassName = 'create-case-flyout-mask-overlay';
|
||||
|
||||
/**
|
||||
* We need to target the mask overlay which is a parent element
|
||||
* of the flyout.
|
||||
* A global style is needed to target a parent element.
|
||||
*/
|
||||
|
||||
const GlobalStyle = createGlobalStyle<{ theme: { eui: { euiZLevel5: number } } }>`
|
||||
.${maskOverlayClassName} {
|
||||
${({ theme }) => `
|
||||
z-index: ${theme.eui.euiZLevel5};
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
// Adding bottom padding because timeline's
|
||||
// bottom bar gonna hide the submit button.
|
||||
const StyledEuiFlyoutBody = styled(EuiFlyoutBody)`
|
||||
${({ theme }) => `
|
||||
&& .euiFlyoutBody__overflow {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
&& .euiFlyoutBody__overflowContent {
|
||||
display: block;
|
||||
padding: ${theme.eui.paddingSizes.l} ${theme.eui.paddingSizes.l} 70px;
|
||||
height: auto;
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const FormWrapper = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const CreateCaseFlyoutComponent: React.FC<CreateCaseModalProps> = ({
|
||||
afterCaseCreated,
|
||||
onCloseFlyout,
|
||||
onSuccess,
|
||||
owner,
|
||||
disableAlerts,
|
||||
}) => {
|
||||
const { cases } = useKibana<TimelinesStartServices>().services;
|
||||
const createCaseProps = useMemo(() => {
|
||||
return {
|
||||
afterCaseCreated,
|
||||
onCancel: onCloseFlyout,
|
||||
onSuccess,
|
||||
withSteps: false,
|
||||
owner: [owner],
|
||||
disableAlerts,
|
||||
};
|
||||
}, [afterCaseCreated, onCloseFlyout, onSuccess, owner, disableAlerts]);
|
||||
return (
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<StyledFlyout
|
||||
onClose={onCloseFlyout}
|
||||
data-test-subj="create-case-flyout"
|
||||
maskProps={{ className: maskOverlayClassName }}
|
||||
>
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2>{i18n.CREATE_TITLE}</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<StyledEuiFlyoutBody>
|
||||
<FormWrapper>{cases.getCreateCase(createCaseProps)}</FormWrapper>
|
||||
</StyledEuiFlyoutBody>
|
||||
</StyledFlyout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const CreateCaseFlyout = memo(CreateCaseFlyoutComponent);
|
||||
|
||||
CreateCaseFlyout.displayName = 'CreateCaseFlyout';
|
|
@ -73,7 +73,3 @@ export const UNSUPPORTED_EVENTS_MSG = i18n.translate(
|
|||
defaultMessage: 'This event cannot be attached to a case',
|
||||
}
|
||||
);
|
||||
|
||||
export const CREATE_TITLE = i18n.translate('xpack.timelines.cases.caseView.create', {
|
||||
defaultMessage: 'Create new case',
|
||||
});
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
import { get, isEmpty } from 'lodash/fp';
|
||||
import { useState, useCallback, useMemo, SyntheticEvent } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils/technical_field_names';
|
||||
import { useKibana } from '../../../../../src/plugins/kibana_react/public';
|
||||
|
@ -17,21 +16,18 @@ import { tGridActions } from '../store/t_grid';
|
|||
import { useDeepEqualSelector } from './use_selector';
|
||||
import { createUpdateSuccessToaster } from '../components/actions/timeline/cases/helpers';
|
||||
import { AddToCaseActionProps } from '../components/actions';
|
||||
import { CasesDeepLinkId, generateCaseViewPath } from '../../../cases/public';
|
||||
|
||||
interface UseAddToCase {
|
||||
addNewCaseClick: () => void;
|
||||
addExistingCaseClick: () => void;
|
||||
onCaseClicked: (theCase?: Case | SubCase) => void;
|
||||
goToCreateCase: (
|
||||
arg: MouseEvent | React.MouseEvent<Element, MouseEvent> | null
|
||||
) => void | Promise<void>;
|
||||
onCaseSuccess: (theCase: Case) => Promise<void>;
|
||||
attachAlertToCase: (
|
||||
theCase: Case,
|
||||
postComment?: ((arg: PostCommentArg) => Promise<void>) | undefined,
|
||||
updateCase?: ((newCase: Case) => void) | undefined
|
||||
) => Promise<void>;
|
||||
createCaseUrl: string;
|
||||
isAllCaseModalOpen: boolean;
|
||||
isDisabled: boolean;
|
||||
userCanCrud: boolean;
|
||||
|
@ -42,27 +38,6 @@ interface UseAddToCase {
|
|||
isCreateCaseFlyoutOpen: boolean;
|
||||
}
|
||||
|
||||
const appendSearch = (search?: string) =>
|
||||
isEmpty(search) ? '' : `${search?.startsWith('?') ? search : `?${search}`}`;
|
||||
|
||||
const getCreateCaseUrl = (search?: string | null) => `/create${appendSearch(search ?? undefined)}`;
|
||||
|
||||
const getCaseDetailsUrl = ({
|
||||
id,
|
||||
search,
|
||||
subCaseId,
|
||||
}: {
|
||||
id: string;
|
||||
search?: string | null;
|
||||
subCaseId?: string;
|
||||
}) => {
|
||||
if (subCaseId) {
|
||||
return `/${encodeURIComponent(id)}/sub-cases/${encodeURIComponent(subCaseId)}${appendSearch(
|
||||
search ?? undefined
|
||||
)}`;
|
||||
}
|
||||
return `/${encodeURIComponent(id)}${appendSearch(search ?? undefined)}`;
|
||||
};
|
||||
interface PostCommentArg {
|
||||
caseId: string;
|
||||
data: {
|
||||
|
@ -78,7 +53,6 @@ interface PostCommentArg {
|
|||
|
||||
export const useAddToCase = ({
|
||||
event,
|
||||
useInsertTimeline,
|
||||
casePermissions,
|
||||
appId,
|
||||
owner,
|
||||
|
@ -111,42 +85,36 @@ export const useAddToCase = ({
|
|||
}
|
||||
}, [timelineById]);
|
||||
const {
|
||||
application: { navigateToApp, getUrlForApp, navigateToUrl },
|
||||
application: { navigateToApp },
|
||||
notifications: { toasts },
|
||||
} = useKibana<TimelinesStartServices>().services;
|
||||
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
const openPopover = useCallback(() => setIsPopoverOpen(true), []);
|
||||
const closePopover = useCallback(() => setIsPopoverOpen(false), []);
|
||||
const isAlert = useMemo(() => {
|
||||
|
||||
const isEventSupported = useMemo(() => {
|
||||
if (event !== undefined) {
|
||||
const data = [...event.data];
|
||||
return data.some(({ field }) => field === 'kibana.alert.rule.uuid');
|
||||
if (event.data.some(({ field }) => field === 'kibana.alert.rule.uuid')) {
|
||||
return true;
|
||||
}
|
||||
return !isEmpty(event.ecs.signal?.rule?.id ?? event.ecs.kibana?.alert?.rule?.uuid);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}, [event]);
|
||||
const isSecurityAlert = useMemo(() => {
|
||||
return !isEmpty(event?.ecs.signal?.rule?.id ?? event?.ecs.kibana?.alert?.rule?.uuid);
|
||||
}, [event]);
|
||||
const isEventSupported = isSecurityAlert || isAlert;
|
||||
|
||||
const userCanCrud = casePermissions?.crud ?? false;
|
||||
const isDisabled = !userCanCrud || !isEventSupported;
|
||||
|
||||
const onViewCaseClick = useCallback(
|
||||
(id) => {
|
||||
const caseDetailsUrl = getCaseDetailsUrl({ id });
|
||||
const appUrl = getUrlForApp(appId);
|
||||
const fullCaseUrl = `${appUrl}/cases/${caseDetailsUrl}`;
|
||||
navigateToUrl(fullCaseUrl);
|
||||
navigateToApp(appId, {
|
||||
deepLinkId: CasesDeepLinkId.cases,
|
||||
path: generateCaseViewPath({ detailName: id }),
|
||||
});
|
||||
},
|
||||
[navigateToUrl, appId, getUrlForApp]
|
||||
);
|
||||
const currentSearch = useLocation().search;
|
||||
const urlSearch = useMemo(() => currentSearch, [currentSearch]);
|
||||
const createCaseUrl = useMemo(
|
||||
() => getUrlForApp('cases') + getCreateCaseUrl(urlSearch),
|
||||
[getUrlForApp, urlSearch]
|
||||
[navigateToApp, appId]
|
||||
);
|
||||
|
||||
const attachAlertToCase = useCallback(
|
||||
|
@ -184,17 +152,6 @@ export const useAddToCase = ({
|
|||
[onViewCaseClick, toasts, dispatch, eventId]
|
||||
);
|
||||
|
||||
const goToCreateCase = useCallback(
|
||||
async (ev) => {
|
||||
ev.preventDefault();
|
||||
return navigateToApp(appId, {
|
||||
deepLinkId: appId === 'securitySolutionUI' ? 'case' : 'cases',
|
||||
path: getCreateCaseUrl(urlSearch),
|
||||
});
|
||||
},
|
||||
[navigateToApp, urlSearch, appId]
|
||||
);
|
||||
|
||||
const onCaseClicked = useCallback(
|
||||
(theCase?: Case | SubCase) => {
|
||||
/**
|
||||
|
@ -228,10 +185,8 @@ export const useAddToCase = ({
|
|||
addNewCaseClick,
|
||||
addExistingCaseClick,
|
||||
onCaseClicked,
|
||||
goToCreateCase,
|
||||
onCaseSuccess,
|
||||
attachAlertToCase,
|
||||
createCaseUrl,
|
||||
isAllCaseModalOpen,
|
||||
isDisabled,
|
||||
userCanCrud,
|
||||
|
|
|
@ -13,6 +13,7 @@ import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/p
|
|||
import { EuiTheme } from '../../../../../src/plugins/kibana_react/common';
|
||||
import { CoreStart } from '../../../../../src/core/public';
|
||||
|
||||
export const mockGetCreateCaseFlyout = jest.fn();
|
||||
export const mockGetAllCasesSelectorModal = jest.fn();
|
||||
export const mockNavigateToApp = jest.fn();
|
||||
|
||||
|
@ -26,6 +27,7 @@ export const createStartServicesMock = (): CoreStart => {
|
|||
getConfigureCases: jest.fn(),
|
||||
getCreateCase: jest.fn(),
|
||||
getRecentCases: jest.fn(),
|
||||
getCreateCaseFlyout: mockGetCreateCaseFlyout,
|
||||
getAllCasesSelectorModal: mockGetAllCasesSelectorModal,
|
||||
},
|
||||
application: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue