From 126272072a544176600f4cf3377d145803d87265 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 13 Apr 2022 16:01:10 +0300 Subject: [PATCH 1/8] Create api --- x-pack/plugins/cases/public/containers/api.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index 9d250e2ae6e0c..796ff02764193 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -9,6 +9,7 @@ import { omit } from 'lodash'; import { StatusAll, ResolvedCase } from '../../common/ui/types'; import { + BulkCreateCommentRequest, CasePatchRequest, CasePostRequest, CaseResponse, @@ -32,6 +33,8 @@ import { CASE_STATUS_URL, CASE_TAGS_URL, CASES_URL, + CASES_INTERNAL_URL, + INTERNAL_BULK_CREATE_ATTACHMENTS_URL, } from '../../common/constants'; import { getAllConnectorTypesUrl } from '../../common/utils/connectors_api'; @@ -308,3 +311,19 @@ export const getActionLicense = async (signal: AbortSignal): Promise => { + const response = await KibanaServices.get().http.fetch( + INTERNAL_BULK_CREATE_ATTACHMENTS_URL.replace('{case_id}', caseId), + { + method: 'POST', + body: JSON.stringify(attachments), + signal, + } + ); + return convertToCamelCase(decodeCaseResponse(response)); +}; From 847e2502c367c304dcdf1afa5c9e14b853a27aa6 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 13 Apr 2022 16:03:40 +0300 Subject: [PATCH 2/8] Switch hook to use the new api --- x-pack/plugins/cases/public/containers/api.ts | 1 - .../cases/public/containers/use_post_comment.tsx | 13 +++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index 796ff02764193..e5606e6b020a9 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -33,7 +33,6 @@ import { CASE_STATUS_URL, CASE_TAGS_URL, CASES_URL, - CASES_INTERNAL_URL, INTERNAL_BULK_CREATE_ATTACHMENTS_URL, } from '../../common/constants'; import { getAllConnectorTypesUrl } from '../../common/utils/connectors_api'; diff --git a/x-pack/plugins/cases/public/containers/use_post_comment.tsx b/x-pack/plugins/cases/public/containers/use_post_comment.tsx index ebfcf607701ba..af996a0c34a8d 100644 --- a/x-pack/plugins/cases/public/containers/use_post_comment.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_comment.tsx @@ -6,9 +6,9 @@ */ import { useReducer, useCallback, useRef, useEffect } from 'react'; -import { CommentRequest } from '../../common/api'; +import { BulkCreateCommentRequest, CommentRequest } from '../../common/api'; -import { postComment } from './api'; +import { bulkCreateAttachments } from './api'; import * as i18n from './translations'; import { Case } from './types'; import { useToasts } from '../common/lib/kibana'; @@ -43,7 +43,7 @@ const dataFetchReducer = (state: NewCommentState, action: Action): NewCommentSta export interface PostComment { caseId: string; - data: CommentRequest; + data: CommentRequest | BulkCreateCommentRequest; updateCase?: (newCase: Case) => void; throwOnError?: boolean; } @@ -62,13 +62,18 @@ export const usePostComment = (): UsePostComment => { const postMyComment = useCallback( async ({ caseId, data, updateCase, throwOnError }: PostComment) => { + const attachments = Array.isArray(data) ? data : [data]; try { isCancelledRef.current = false; abortCtrlRef.current.abort(); abortCtrlRef.current = new AbortController(); dispatch({ type: 'FETCH_INIT' }); - const response = await postComment(data, caseId, abortCtrlRef.current.signal); + const response = await bulkCreateAttachments( + attachments, + caseId, + abortCtrlRef.current.signal + ); if (!isCancelledRef.current) { dispatch({ type: 'FETCH_SUCCESS' }); From 836a46b9d06c59b043eb6f06eba152c981be3513 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 13 Apr 2022 16:45:17 +0300 Subject: [PATCH 3/8] Rename hook --- .../components/add_comment/index.test.tsx | 31 +++++++---- .../public/components/add_comment/index.tsx | 8 +-- .../all_cases/all_cases_list.test.tsx | 11 ++-- ..._cases_add_to_existing_case_modal.test.tsx | 26 +++++----- .../use_cases_add_to_existing_case_modal.tsx | 10 ++-- .../create/flyout/create_case_flyout.tsx | 7 ++- .../cases/public/components/create/form.tsx | 7 ++- .../components/create/form_context.test.tsx | 22 ++++---- .../public/components/create/form_context.tsx | 18 ++++--- .../cases/public/containers/__mocks__/api.ts | 2 +- .../cases/public/containers/api.test.tsx | 8 +-- ...x => use_bulk_create_attachments.test.tsx} | 52 +++++++++---------- ...nt.tsx => use_bulk_create_attachments.tsx} | 10 ++-- 13 files changed, 118 insertions(+), 94 deletions(-) rename x-pack/plugins/cases/public/containers/{use_post_comment.test.tsx => use_bulk_create_attachments.test.tsx} (74%) rename x-pack/plugins/cases/public/containers/{use_post_comment.tsx => use_bulk_create_attachments.tsx} (90%) diff --git a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx index f7535e6f52071..4bf35c47e336b 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx @@ -14,17 +14,17 @@ import { TestProviders } from '../../common/mock'; import { CommentRequest, CommentType } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { usePostComment } from '../../containers/use_post_comment'; +import { useBulkCreateAttachments } from '../../containers/use_bulk_create_attachments'; import { AddComment, AddCommentProps, AddCommentRefObject } from '.'; import { CasesTimelineIntegrationProvider } from '../timeline_context'; import { timelineIntegrationMock } from '../__mock__/timeline'; -jest.mock('../../containers/use_post_comment'); +jest.mock('../../containers/use_bulk_create_attachments'); -const usePostCommentMock = usePostComment as jest.Mock; +const useBulkCreateAttachmentsMock = useBulkCreateAttachments as jest.Mock; const onCommentSaving = jest.fn(); const onCommentPosted = jest.fn(); -const postComment = jest.fn(); +const bulkCreateAttachments = jest.fn(); const addCommentProps: AddCommentProps = { id: 'newComment', @@ -36,10 +36,10 @@ const addCommentProps: AddCommentProps = { statusActionButton: null, }; -const defaultPostComment = { +const defaultResponse = { isLoading: false, isError: false, - postComment, + bulkCreateAttachments, }; const sampleData: CommentRequest = { @@ -51,7 +51,7 @@ const sampleData: CommentRequest = { describe('AddComment ', () => { beforeEach(() => { jest.clearAllMocks(); - usePostCommentMock.mockImplementation(() => defaultPostComment); + useBulkCreateAttachmentsMock.mockImplementation(() => defaultResponse); }); it('should post comment on submit click', async () => { @@ -72,7 +72,7 @@ describe('AddComment ', () => { wrapper.find(`[data-test-subj="submit-comment"]`).first().simulate('click'); await waitFor(() => { expect(onCommentSaving).toBeCalled(); - expect(postComment).toBeCalledWith({ + expect(bulkCreateAttachments).toBeCalledWith({ caseId: addCommentProps.caseId, data: sampleData, updateCase: onCommentPosted, @@ -82,7 +82,10 @@ describe('AddComment ', () => { }); it('should render spinner and disable submit when loading', () => { - usePostCommentMock.mockImplementation(() => ({ ...defaultPostComment, isLoading: true })); + useBulkCreateAttachmentsMock.mockImplementation(() => ({ + ...defaultResponse, + isLoading: true, + })); const wrapper = mount( @@ -96,7 +99,10 @@ describe('AddComment ', () => { }); it('should disable submit button when isLoading is true', () => { - usePostCommentMock.mockImplementation(() => ({ ...defaultPostComment, isLoading: true })); + useBulkCreateAttachmentsMock.mockImplementation(() => ({ + ...defaultResponse, + isLoading: true, + })); const wrapper = mount( @@ -109,7 +115,10 @@ describe('AddComment ', () => { }); it('should hide the component when the user does not have crud permissions', () => { - usePostCommentMock.mockImplementation(() => ({ ...defaultPostComment, isLoading: true })); + useBulkCreateAttachmentsMock.mockImplementation(() => ({ + ...defaultResponse, + isLoading: true, + })); const wrapper = mount( diff --git a/x-pack/plugins/cases/public/components/add_comment/index.tsx b/x-pack/plugins/cases/public/components/add_comment/index.tsx index dea692f7c71a1..6150aac1873c2 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -18,7 +18,7 @@ import styled from 'styled-components'; import { isEmpty } from 'lodash'; import { CommentType } from '../../../common/api'; -import { usePostComment } from '../../containers/use_post_comment'; +import { useBulkCreateAttachments } from '../../containers/use_bulk_create_attachments'; import { Case } from '../../containers/types'; import { EuiMarkdownEditorRef, MarkdownEditorForm } from '../markdown_editor'; import { Form, useForm, UseField, useFormData } from '../../common/shared_imports'; @@ -71,7 +71,7 @@ export const AddComment = React.memo( const editorRef = useRef(null); const [focusOnContext, setFocusOnContext] = useState(false); const { owner } = useCasesContext(); - const { isLoading, postComment } = usePostComment(); + const { isLoading, bulkCreateAttachments } = useBulkCreateAttachments(); const { form } = useForm({ defaultValue: initialCommentValue, @@ -112,14 +112,14 @@ export const AddComment = React.memo( if (onCommentSaving != null) { onCommentSaving(); } - postComment({ + bulkCreateAttachments({ caseId, data: { ...data, type: CommentType.user, owner: owner[0] }, updateCase: onCommentPosted, }); reset(); } - }, [submit, onCommentSaving, postComment, caseId, owner, onCommentPosted, reset]); + }, [submit, onCommentSaving, bulkCreateAttachments, caseId, owner, onCommentPosted, reset]); /** * Focus on the text area when a quote has been added. diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx index b1f5af86cf8ab..d9e233f57d16a 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx @@ -33,11 +33,11 @@ import { triggersActionsUiMock } from '../../../../triggers_actions_ui/public/mo import { registerConnectorsToMockActionRegistry } from '../../common/mock/register_connectors'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; import { waitForComponentToUpdate } from '../../common/test_utils'; -import { usePostComment } from '../../containers/use_post_comment'; +import { useBulkCreateAttachments } from '../../containers/use_bulk_create_attachments'; import { useGetTags } from '../../containers/use_get_tags'; import { useGetReporters } from '../../containers/use_get_reporters'; -jest.mock('../../containers/use_post_comment'); +jest.mock('../../containers/use_bulk_create_attachments'); jest.mock('../../containers/use_bulk_update_case'); jest.mock('../../containers/use_delete_cases'); jest.mock('../../containers/use_get_cases'); @@ -61,7 +61,7 @@ const useGetTagsMock = useGetTags as jest.Mock; const useGetReportersMock = useGetReporters as jest.Mock; const useKibanaMock = useKibana as jest.MockedFunction; const useConnectorsMock = useConnectors as jest.Mock; -const usePostCommentMock = usePostComment as jest.Mock; +const useBulkCreateAttachmentsMock = useBulkCreateAttachments as jest.Mock; const mockTriggersActionsUiService = triggersActionsUiMock.createStart(); @@ -88,7 +88,10 @@ describe('AllCasesListGeneric', () => { const fetchCasesStatus = jest.fn(); const onRowClick = jest.fn(); const emptyTag = getEmptyTagValue().props.children; - usePostCommentMock.mockReturnValue({ status: { isLoading: false }, postComment: jest.fn() }); + useBulkCreateAttachmentsMock.mockReturnValue({ + status: { isLoading: false }, + bulkCreateAttachments: jest.fn(), + }); const defaultGetCases = { ...useGetCasesMockState, diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx index 25360800554b2..0f11c32745df1 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx @@ -14,14 +14,14 @@ import { Case, CaseStatuses, StatusAll } from '../../../../common'; import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; import { useCasesToast } from '../../../common/use_cases_toast'; import { alertComment } from '../../../containers/mock'; -import { usePostComment } from '../../../containers/use_post_comment'; +import { useBulkCreateAttachments } from '../../../containers/use_bulk_create_attachments'; import { SupportedCaseAttachment } from '../../../types'; import { CasesContext } from '../../cases_context'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesAddToExistingCaseModal } from './use_cases_add_to_existing_case_modal'; jest.mock('../../../common/use_cases_toast'); -jest.mock('../../../containers/use_post_comment'); +jest.mock('../../../containers/use_bulk_create_attachments'); // dummy mock, will call onRowclick when rendering jest.mock('./all_cases_selector_modal', () => { return { @@ -46,11 +46,11 @@ const TestComponent: React.FC = () => { return