diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.tsx
index 93905eaf64213..baa15f1b47248 100644
--- a/x-pack/plugins/cases/public/common/use_cases_toast.tsx
+++ b/x-pack/plugins/cases/public/common/use_cases_toast.tsx
@@ -7,7 +7,7 @@
import type { ErrorToastOptions } from '@kbn/core/public';
import { EuiButtonEmpty, EuiText } from '@elastic/eui';
-import React from 'react';
+import React, { useMemo } from 'react';
import styled from 'styled-components';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { isValidOwner } from '../../common/utils/owner';
@@ -124,62 +124,65 @@ export const useCasesToast = () => {
const toasts = useToasts();
- return {
- showSuccessAttach: ({
- theCase,
- attachments,
- title,
- content,
- }: {
- theCase: CaseUI;
- attachments?: CaseAttachmentsWithoutOwner;
- title?: string;
- content?: string;
- }) => {
- const appIdToNavigateTo = isValidOwner(theCase.owner)
- ? OWNER_INFO[theCase.owner].appId
- : appId;
-
- const url = getUrlForApp(appIdToNavigateTo, {
- deepLinkId: 'cases',
- path: generateCaseViewPath({ detailName: theCase.id }),
- });
-
- const onViewCaseClick = () => {
- navigateToUrl(url);
- };
-
- const renderTitle = getToastTitle({ theCase, title, attachments });
- const renderContent = getToastContent({ theCase, content, attachments });
-
- return toasts.addSuccess({
- color: 'success',
- iconType: 'check',
- title: toMountPoint(
{renderTitle}),
- text: toMountPoint(
-
- ),
- });
- },
- showErrorToast: (error: Error | ServerError, opts?: ErrorToastOptions) => {
- if (error.name !== 'AbortError') {
- toasts.addError(getError(error), { title: getErrorMessage(error), ...opts });
- }
- },
- showSuccessToast: (title: string) => {
- toasts.addSuccess({ title, className: 'eui-textBreakWord' });
- },
- showDangerToast: (title: string) => {
- toasts.addDanger({ title, className: 'eui-textBreakWord' });
- },
- showInfoToast: (title: string, text?: string) => {
- toasts.addInfo({
+ return useMemo(
+ () => ({
+ showSuccessAttach: ({
+ theCase,
+ attachments,
title,
- text,
- className: 'eui-textBreakWord',
- });
- },
- };
+ content,
+ }: {
+ theCase: CaseUI;
+ attachments?: CaseAttachmentsWithoutOwner;
+ title?: string;
+ content?: string;
+ }) => {
+ const appIdToNavigateTo = isValidOwner(theCase.owner)
+ ? OWNER_INFO[theCase.owner].appId
+ : appId;
+
+ const url = getUrlForApp(appIdToNavigateTo, {
+ deepLinkId: 'cases',
+ path: generateCaseViewPath({ detailName: theCase.id }),
+ });
+
+ const onViewCaseClick = () => {
+ navigateToUrl(url);
+ };
+
+ const renderTitle = getToastTitle({ theCase, title, attachments });
+ const renderContent = getToastContent({ theCase, content, attachments });
+
+ return toasts.addSuccess({
+ color: 'success',
+ iconType: 'check',
+ title: toMountPoint({renderTitle}),
+ text: toMountPoint(
+
+ ),
+ });
+ },
+ showErrorToast: (error: Error | ServerError, opts?: ErrorToastOptions) => {
+ if (error.name !== 'AbortError') {
+ toasts.addError(getError(error), { title: getErrorMessage(error), ...opts });
+ }
+ },
+ showSuccessToast: (title: string) => {
+ toasts.addSuccess({ title, className: 'eui-textBreakWord' });
+ },
+ showDangerToast: (title: string) => {
+ toasts.addDanger({ title, className: 'eui-textBreakWord' });
+ },
+ showInfoToast: (title: string, text?: string) => {
+ toasts.addInfo({
+ title,
+ text,
+ className: 'eui-textBreakWord',
+ });
+ },
+ }),
+ [appId, getUrlForApp, navigateToUrl, toasts]
+ );
};
export const CaseToastSuccessContent = ({
diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx
index f311fdad66a47..ea60c43937346 100644
--- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx
@@ -30,16 +30,26 @@ export type AddToExistingCaseModalProps = Omit void;
};
-export const useCasesAddToExistingCaseModal = (props: AddToExistingCaseModalProps = {}) => {
- const createNewCaseFlyout = useCasesAddToNewCaseFlyout({
- onClose: props.onClose,
- onSuccess: (theCase?: CaseUI) => {
- if (props.onSuccess && theCase) {
- return props.onSuccess(theCase);
+export const useCasesAddToExistingCaseModal = ({
+ successToaster,
+ noAttachmentsToaster,
+ onSuccess,
+ onClose,
+ onCreateCaseClicked,
+}: AddToExistingCaseModalProps = {}) => {
+ const handleSuccess = useCallback(
+ (theCase?: CaseUI) => {
+ if (onSuccess && theCase) {
+ return onSuccess(theCase);
}
},
- toastTitle: props.successToaster?.title,
- toastContent: props.successToaster?.content,
+ [onSuccess]
+ );
+ const { open: openCreateNewCaseFlyout } = useCasesAddToNewCaseFlyout({
+ onClose,
+ onSuccess: handleSuccess,
+ toastTitle: successToaster?.title,
+ toastContent: successToaster?.content,
});
const { dispatch, appId } = useCasesContext();
@@ -69,15 +79,15 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingCaseModalProp
// the user clicked "create new case"
if (theCase === undefined) {
closeModal();
- createNewCaseFlyout.open({ attachments });
+ openCreateNewCaseFlyout({ attachments });
return;
}
try {
// add attachments to the case
if (attachments === undefined || attachments.length === 0) {
- const title = props.noAttachmentsToaster?.title ?? NO_ATTACHMENTS_ADDED;
- const content = props.noAttachmentsToaster?.content;
+ const title = noAttachmentsToaster?.title ?? NO_ATTACHMENTS_ADDED;
+ const content = noAttachmentsToaster?.content;
casesToasts.showInfoToast(title, content);
return;
@@ -91,15 +101,13 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingCaseModalProp
attachments,
});
- if (props.onSuccess) {
- props.onSuccess(theCase);
- }
+ onSuccess?.(theCase);
casesToasts.showSuccessAttach({
theCase,
attachments,
- title: props.successToaster?.title,
- content: props.successToaster?.content,
+ title: successToaster?.title,
+ content: successToaster?.content,
});
} catch (error) {
// error toast is handled
@@ -111,8 +119,12 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingCaseModalProp
casesToasts,
closeModal,
createAttachments,
- createNewCaseFlyout,
- props,
+ openCreateNewCaseFlyout,
+ successToaster?.title,
+ successToaster?.content,
+ noAttachmentsToaster?.title,
+ noAttachmentsToaster?.content,
+ onSuccess,
startTransaction,
]
);
@@ -126,22 +138,22 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingCaseModalProp
dispatch({
type: CasesContextStoreActionsList.OPEN_ADD_TO_CASE_MODAL,
payload: {
- ...props,
hiddenStatuses: [CaseStatuses.closed],
+ onCreateCaseClicked,
onRowClick: (theCase?: CaseUI) => {
handleOnRowClick(theCase, getAttachments);
},
onClose: (theCase?: CaseUI, isCreateCase?: boolean) => {
closeModal();
- if (props.onClose) {
- return props.onClose(theCase, isCreateCase);
+ if (onClose) {
+ return onClose(theCase, isCreateCase);
}
},
},
});
},
- [closeModal, dispatch, handleOnRowClick, props]
+ [closeModal, dispatch, handleOnRowClick, onClose, onCreateCaseClicked]
);
return {
diff --git a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx
index a8e234f9bb96a..e6d5bd2fc2a0b 100644
--- a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx
+++ b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx
@@ -19,7 +19,15 @@ type AddToNewCaseFlyoutProps = Omit & {
toastContent?: string;
};
-export const useCasesAddToNewCaseFlyout = (props: AddToNewCaseFlyoutProps = {}) => {
+export const useCasesAddToNewCaseFlyout = ({
+ initialValue,
+ toastTitle,
+ toastContent,
+
+ afterCaseCreated,
+ onSuccess,
+ onClose,
+}: AddToNewCaseFlyoutProps = {}) => {
const { dispatch } = useCasesContext();
const casesToasts = useCasesToast();
@@ -37,13 +45,13 @@ export const useCasesAddToNewCaseFlyout = (props: AddToNewCaseFlyoutProps = {})
dispatch({
type: CasesContextStoreActionsList.OPEN_CREATE_CASE_FLYOUT,
payload: {
- ...props,
+ initialValue,
attachments,
headerContent,
onClose: () => {
closeFlyout();
- if (props.onClose) {
- return props.onClose();
+ if (onClose) {
+ return onClose();
}
},
onSuccess: async (theCase: CaseUI) => {
@@ -51,24 +59,34 @@ export const useCasesAddToNewCaseFlyout = (props: AddToNewCaseFlyoutProps = {})
casesToasts.showSuccessAttach({
theCase,
attachments: attachments ?? [],
- title: props.toastTitle,
- content: props.toastContent,
+ title: toastTitle,
+ content: toastContent,
});
}
- if (props.onSuccess) {
- return props.onSuccess(theCase);
+ if (onSuccess) {
+ return onSuccess(theCase);
}
},
afterCaseCreated: async (...args) => {
closeFlyout();
- if (props.afterCaseCreated) {
- return props.afterCaseCreated(...args);
+ if (afterCaseCreated) {
+ return afterCaseCreated(...args);
}
},
},
});
},
- [casesToasts, closeFlyout, dispatch, props]
+ [
+ initialValue,
+ casesToasts,
+ closeFlyout,
+ dispatch,
+ toastTitle,
+ toastContent,
+ afterCaseCreated,
+ onSuccess,
+ onClose,
+ ]
);
return {
open: openFlyout,
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts
index 4d487dcd9186d..1a61042389911 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts
@@ -86,7 +86,7 @@ const ACTION_DEFINITION: Record<
export const useActions = ({
attributes,
lensMetadata,
- extraActions = [],
+ extraActions,
inspectActionProps,
timeRange,
withActions = DEFAULT_ACTIONS,
@@ -186,7 +186,7 @@ export const useActions = ({
canUseEditor() && withActions.includes(VisualizationContextMenuActions.openInLens),
order: 0,
}),
- ...extraActions,
+ ...(extraActions ?? []),
].map((a, i, totalActions) => {
const order = Math.max(totalActions.length - (1 + i), 0);
return {
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.test.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.test.tsx
index 2ed014ee69a37..5181d33370afe 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.test.tsx
@@ -15,31 +15,15 @@ import {
} from '../../../cases_test_utils';
import { AttachmentType } from '@kbn/cases-plugin/common';
-const mockedUseKibana = mockUseKibana();
-const mockGetUseCasesAddToExistingCaseModal = jest.fn();
-const mockCanUseCases = jest.fn();
-
-jest.mock('../../lib/kibana', () => {
- const original = jest.requireActual('../../lib/kibana');
-
- return {
- ...original,
- useKibana: () => ({
- ...mockedUseKibana,
- services: {
- ...mockedUseKibana.services,
- cases: {
- hooks: {
- useCasesAddToExistingCaseModal: mockGetUseCasesAddToExistingCaseModal,
- },
- helpers: { canUseCases: mockCanUseCases },
- },
- },
- }),
- };
-});
+jest.mock('../../lib/kibana');
describe('useAddToExistingCase', () => {
+ const mockedUseKibana = mockUseKibana();
+ const mockCanUseCases = jest.fn();
+ const mockUseCasesAddToExistingCaseModal = jest.fn().mockReturnValue({
+ open: jest.fn(),
+ close: jest.fn(),
+ });
const mockOnAddToCaseClicked = jest.fn();
const timeRange = {
from: '2022-03-06T16:00:00.000Z',
@@ -48,6 +32,9 @@ describe('useAddToExistingCase', () => {
beforeEach(() => {
mockCanUseCases.mockReturnValue(allCasesPermissions());
+ mockedUseKibana.services.cases.hooks.useCasesAddToExistingCaseModal =
+ mockUseCasesAddToExistingCaseModal;
+ mockedUseKibana.services.cases.helpers.canUseCases = mockCanUseCases;
});
it('useCasesAddToExistingCaseModal with attachments', () => {
@@ -59,7 +46,7 @@ describe('useAddToExistingCase', () => {
lensMetadata: undefined,
})
);
- expect(mockGetUseCasesAddToExistingCaseModal).toHaveBeenCalledWith({
+ expect(mockUseCasesAddToExistingCaseModal).toHaveBeenCalledWith({
onClose: mockOnAddToCaseClicked,
successToaster: {
title: 'Successfully added visualization to the case',
@@ -127,7 +114,7 @@ describe('useAddToExistingCase', () => {
description: 'test_description',
};
- mockGetUseCasesAddToExistingCaseModal.mockReturnValue({ open: mockOpenCaseModal });
+ mockUseCasesAddToExistingCaseModal.mockReturnValue({ open: mockOpenCaseModal });
const { result } = renderHook(() =>
useAddToExistingCase({
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.tsx
index 1675802b9953e..aa11ced2603a9 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_existing_case.tsx
@@ -40,7 +40,7 @@ export const useAddToExistingCase = ({
] as CaseAttachmentsWithoutOwner;
}, [lensAttributes, lensMetadata, timeRange]);
- const selectCaseModal = cases.hooks.useCasesAddToExistingCaseModal({
+ const { open: openSelectCaseModal } = cases.hooks.useCasesAddToExistingCaseModal({
onClose: onAddToCaseClicked,
successToaster: {
title: ADD_TO_CASE_SUCCESS,
@@ -51,8 +51,8 @@ export const useAddToExistingCase = ({
if (onAddToCaseClicked) {
onAddToCaseClicked();
}
- selectCaseModal.open({ getAttachments: () => attachments });
- }, [attachments, onAddToCaseClicked, selectCaseModal]);
+ openSelectCaseModal({ getAttachments: () => attachments });
+ }, [attachments, onAddToCaseClicked, openSelectCaseModal]);
return {
onAddToExistingCaseClicked,
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.test.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.test.tsx
index 91347dc9fe073..fceff5e6cdaae 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.test.tsx
@@ -17,37 +17,26 @@ import { AttachmentType } from '@kbn/cases-plugin/common';
jest.mock('../../lib/kibana/kibana_react');
-const mockedUseKibana = mockUseKibana();
-const mockGetUseCasesAddToNewCaseFlyout = jest.fn();
-const mockCanUseCases = jest.fn();
-
-jest.mock('../../lib/kibana', () => {
- const original = jest.requireActual('../../lib/kibana');
-
- return {
- ...original,
- useKibana: () => ({
- ...mockedUseKibana,
- services: {
- ...mockedUseKibana.services,
- cases: {
- hooks: {
- useCasesAddToNewCaseFlyout: mockGetUseCasesAddToNewCaseFlyout,
- },
- helpers: { canUseCases: mockCanUseCases },
- },
- },
- }),
- };
-});
+jest.mock('../../lib/kibana');
describe('useAddToNewCase', () => {
+ const mockedUseKibana = mockUseKibana();
+ const mockCanUseCases = jest.fn();
+ const mockGetUseCasesAddToNewCaseFlyout = jest.fn().mockReturnValue({
+ open: jest.fn(),
+ close: jest.fn(),
+ });
+
const timeRange = {
from: '2022-03-06T16:00:00.000Z',
to: '2022-03-07T15:59:59.999Z',
};
+
beforeEach(() => {
mockCanUseCases.mockReturnValue(allCasesPermissions());
+ mockedUseKibana.services.cases.hooks.useCasesAddToNewCaseFlyout =
+ mockGetUseCasesAddToNewCaseFlyout;
+ mockedUseKibana.services.cases.helpers.canUseCases = mockCanUseCases;
});
it('useCasesAddToNewCaseFlyout with attachments', () => {
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.tsx
index aca5ba88dc057..c2ac628000fa7 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_add_to_new_case.tsx
@@ -43,7 +43,7 @@ export const useAddToNewCase = ({
] as CaseAttachmentsWithoutOwner;
}, [lensAttributes, lensMetadata, timeRange]);
- const createCaseFlyout = cases.hooks.useCasesAddToNewCaseFlyout({
+ const { open: openCreateCaseFlyout } = cases.hooks.useCasesAddToNewCaseFlyout({
toastContent: ADD_TO_CASE_SUCCESS,
});
@@ -52,8 +52,8 @@ export const useAddToNewCase = ({
onClick();
}
- createCaseFlyout.open({ attachments });
- }, [attachments, createCaseFlyout, onClick]);
+ openCreateCaseFlyout({ attachments });
+ }, [attachments, openCreateCaseFlyout, onClick]);
return {
onAddToNewCaseClicked,