From 037d7aeb8f11057e0b4696e9f6aeafd321b32220 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Wed, 16 Jun 2021 12:23:10 +0200 Subject: [PATCH] Enhance cases bulk deletion action dialog message (#101403) Differentiate the dialog message on the deletion of one item from the deletion of multiple items. Simplifies CasesTableUtilityBar by handling the selection of multiple and single cases in the same way. --- x-pack/plugins/cases/common/ui/types.ts | 2 +- .../cases/public/common/translations.ts | 12 +++---- .../public/components/all_cases/actions.tsx | 4 +-- .../public/components/all_cases/columns.tsx | 1 - .../components/all_cases/utility_bar.tsx | 33 +++++-------------- .../components/case_action_bar/actions.tsx | 3 +- .../components/confirm_delete_case/index.tsx | 18 ++++------ .../confirm_delete_case/translations.ts | 26 +++++---------- .../containers/use_delete_cases.test.tsx | 6 ++-- 9 files changed, 36 insertions(+), 69 deletions(-) diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 284f5e706292cc..1dbb633e32adf0 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -153,7 +153,7 @@ export interface ActionLicense { export interface DeleteCase { id: string; type: CaseType | null; - title?: string; + title: string; } export interface FieldMappings { diff --git a/x-pack/plugins/cases/public/common/translations.ts b/x-pack/plugins/cases/public/common/translations.ts index 85cfb60b1d6b81..f1bfde4cc44851 100644 --- a/x-pack/plugins/cases/public/common/translations.ts +++ b/x-pack/plugins/cases/public/common/translations.ts @@ -30,13 +30,11 @@ export const CANCEL = i18n.translate('xpack.cases.caseView.cancel', { defaultMessage: 'Cancel', }); -export const DELETE_CASE = i18n.translate('xpack.cases.confirmDeleteCase.deleteCase', { - defaultMessage: 'Delete case', -}); - -export const DELETE_CASES = i18n.translate('xpack.cases.confirmDeleteCase.deleteCases', { - defaultMessage: 'Delete cases', -}); +export const DELETE_CASE = (quantity: number = 1) => + i18n.translate('xpack.cases.confirmDeleteCase.deleteCase', { + values: { quantity }, + defaultMessage: `Delete {quantity, plural, =1 {case} other {cases}}`, + }); export const NAME = i18n.translate('xpack.cases.caseView.name', { defaultMessage: 'Name', diff --git a/x-pack/plugins/cases/public/components/all_cases/actions.tsx b/x-pack/plugins/cases/public/components/all_cases/actions.tsx index 8742b8fea23a42..4820b10308934f 100644 --- a/x-pack/plugins/cases/public/components/all_cases/actions.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/actions.tsx @@ -80,9 +80,9 @@ export const getActions = ({ makeInProgressAction, closeCaseAction, { - description: i18n.DELETE_CASE, + description: i18n.DELETE_CASE(), icon: 'trash', - name: i18n.DELETE_CASE, + name: i18n.DELETE_CASE(), onClick: deleteCaseOnClick, type: 'icon', 'data-test-subj': 'action-delete', diff --git a/x-pack/plugins/cases/public/components/all_cases/columns.tsx b/x-pack/plugins/cases/public/components/all_cases/columns.tsx index 947d405d188cf0..a5a299851d975a 100644 --- a/x-pack/plugins/cases/public/components/all_cases/columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/columns.tsx @@ -306,7 +306,6 @@ export const useCasesColumns = ({ diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx index d0981c38385e96..a2b4c14c0278a8 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx @@ -41,12 +41,8 @@ export const CasesTableUtilityBar: FunctionComponent = ({ refreshCases, selectedCases, }) => { - const [deleteBulk, setDeleteBulk] = useState([]); - const [deleteThisCase, setDeleteThisCase] = useState({ - title: '', - id: '', - type: null, - }); + const [deleteCases, setDeleteCases] = useState([]); + // Delete case const { dispatchResetIsDeleted, @@ -86,24 +82,15 @@ export const CasesTableUtilityBar: FunctionComponent = ({ const toggleBulkDeleteModal = useCallback( (cases: Case[]) => { handleToggleModal(); - if (cases.length === 1) { - const singleCase = cases[0]; - if (singleCase) { - return setDeleteThisCase({ - id: singleCase.id, - title: singleCase.title, - type: singleCase.type, - }); - } - } + const convertToDeleteCases: DeleteCase[] = cases.map(({ id, title, type }) => ({ id, title, type, })); - setDeleteBulk(convertToDeleteCases); + setDeleteCases(convertToDeleteCases); }, - [setDeleteBulk, handleToggleModal] + [setDeleteCases, handleToggleModal] ); const handleUpdateCaseStatus = useCallback( @@ -128,6 +115,7 @@ export const CasesTableUtilityBar: FunctionComponent = ({ ), [selectedCases, filterOptions.status, toggleBulkDeleteModal, handleUpdateCaseStatus] ); + return ( @@ -159,14 +147,11 @@ export const CasesTableUtilityBar: FunctionComponent = ({ 0} + caseQuantity={deleteCases.length} onCancel={handleToggleModal} - onConfirm={handleOnDeleteConfirm.bind( - null, - deleteBulk.length > 0 ? deleteBulk : [deleteThisCase] - )} + onConfirm={handleOnDeleteConfirm.bind(null, deleteCases)} /> ); diff --git a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx index 922ffd09aaac9d..c2578dc3debdb6 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx @@ -41,7 +41,7 @@ const ActionsComponent: React.FC = ({ { disabled, iconType: 'trash', - label: i18n.DELETE_CASE, + label: i18n.DELETE_CASE(), onClick: handleToggleModal, }, ...(currentExternalIncident != null && !isEmpty(currentExternalIncident?.externalUrl) @@ -67,7 +67,6 @@ const ActionsComponent: React.FC = ({ void; onConfirm: () => void; } @@ -20,7 +20,7 @@ interface ConfirmDeleteCaseModalProps { const ConfirmDeleteCaseModalComp: React.FC = ({ caseTitle, isModalVisible, - isPlural, + caseQuantity = 1, onCancel, onConfirm, }) => { @@ -31,20 +31,14 @@ const ConfirmDeleteCaseModalComp: React.FC = ({ - {isPlural ? i18n.CONFIRM_QUESTION_PLURAL : i18n.CONFIRM_QUESTION} + {i18n.CONFIRM_QUESTION(caseQuantity)} ); }; diff --git a/x-pack/plugins/cases/public/components/confirm_delete_case/translations.ts b/x-pack/plugins/cases/public/components/confirm_delete_case/translations.ts index 0400c4c7fef413..f8e4ab2a83a738 100644 --- a/x-pack/plugins/cases/public/components/confirm_delete_case/translations.ts +++ b/x-pack/plugins/cases/public/components/confirm_delete_case/translations.ts @@ -14,23 +14,15 @@ export const DELETE_TITLE = (caseTitle: string) => defaultMessage: 'Delete "{caseTitle}"', }); -export const DELETE_THIS_CASE = (caseTitle: string) => - i18n.translate('xpack.cases.confirmDeleteCase.deleteThisCase', { - defaultMessage: 'Delete this case', +export const DELETE_SELECTED_CASES = (quantity: number, title: string) => + i18n.translate('xpack.cases.confirmDeleteCase.selectedCases', { + values: { quantity, title }, + defaultMessage: 'Delete "{quantity, plural, =1 {{title}} other {Selected {quantity} cases}}"', }); -export const CONFIRM_QUESTION = i18n.translate('xpack.cases.confirmDeleteCase.confirmQuestion', { - defaultMessage: - 'By deleting this case, all related case data will be permanently removed and you will no longer be able to push data to an external incident management system. Are you sure you wish to proceed?', -}); -export const DELETE_SELECTED_CASES = i18n.translate('xpack.cases.confirmDeleteCase.selectedCases', { - defaultMessage: 'Delete selected cases', -}); - -export const CONFIRM_QUESTION_PLURAL = i18n.translate( - 'xpack.cases.confirmDeleteCase.confirmQuestionPlural', - { +export const CONFIRM_QUESTION = (quantity: number) => + i18n.translate('xpack.cases.confirmDeleteCase.confirmQuestion', { + values: { quantity }, defaultMessage: - 'By deleting these cases, all related case data will be permanently removed and you will no longer be able to push data to an external incident management system. Are you sure you wish to proceed?', - } -); + 'By deleting {quantity, plural, =1 {this case} other {these cases}}, all related case data will be permanently removed and you will no longer be able to push data to an external incident management system. Are you sure you wish to proceed?', + }); diff --git a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx index e86ed0c036974a..691af580b333a8 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx @@ -17,9 +17,9 @@ jest.mock('../common/lib/kibana'); describe('useDeleteCases', () => { const abortCtrl = new AbortController(); const deleteObj = [ - { id: '1', type: CaseType.individual }, - { id: '2', type: CaseType.individual }, - { id: '3', type: CaseType.individual }, + { id: '1', type: CaseType.individual, title: 'case 1' }, + { id: '2', type: CaseType.individual, title: 'case 2' }, + { id: '3', type: CaseType.individual, title: 'case 3' }, ]; const deleteArr = ['1', '2', '3']; it('init', async () => {