From 38f8453e3409b4252a9ba161225f0d02fa05d276 Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Wed, 9 Oct 2024 23:41:02 +0200 Subject: [PATCH] [Security Solution][Notes] - update notes management page columns (#194860) (cherry picked from commit 3fa70e122c6a3c77edea3f2c47980403c1835256) --- .../notes/components/delete_confirm_modal.tsx | 29 +++- .../notes/components/delete_note_button.tsx | 7 +- .../public/notes/components/notes_list.tsx | 85 ++++++---- .../components/open_event_in_timeline.tsx | 24 --- .../components/open_flyout_button.test.tsx | 15 +- .../notes/components/open_flyout_button.tsx | 71 ++++---- .../notes/components/open_timeline_button.tsx | 13 +- .../public/notes/components/translations.ts | 58 ------- .../public/notes/components/utility_bar.tsx | 32 +++- .../public/notes/hooks/use_fetch_notes.ts | 15 +- .../notes/pages/note_management_page.tsx | 155 +++++++++--------- .../public/notes/pages/translations.ts | 27 +-- .../public/notes/store/notes.slice.test.ts | 8 +- .../public/notes/store/notes.slice.ts | 4 +- .../translations/translations/fr-FR.json | 5 - .../translations/translations/ja-JP.json | 5 - .../translations/translations/zh-CN.json | 5 - 17 files changed, 263 insertions(+), 295 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/notes/components/open_event_in_timeline.tsx delete mode 100644 x-pack/plugins/security_solution/public/notes/components/translations.ts diff --git a/x-pack/plugins/security_solution/public/notes/components/delete_confirm_modal.tsx b/x-pack/plugins/security_solution/public/notes/components/delete_confirm_modal.tsx index cba7e81b0fb2b..3c6d6da08e190 100644 --- a/x-pack/plugins/security_solution/public/notes/components/delete_confirm_modal.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/delete_confirm_modal.tsx @@ -7,7 +7,7 @@ import React, { useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { EuiConfirmModal } from '@elastic/eui'; -import * as i18n from './translations'; +import { i18n } from '@kbn/i18n'; import { deleteNotes, userClosedDeleteModal, @@ -16,6 +16,25 @@ import { ReqStatus, } from '..'; +export const DELETE = i18n.translate('xpack.securitySolution.notes.management.deleteAction', { + defaultMessage: 'Delete', +}); +export const DELETE_NOTES_CONFIRM = (selectedNotes: number) => + i18n.translate('xpack.securitySolution.notes.management.deleteNotesConfirm', { + values: { selectedNotes }, + defaultMessage: + 'Are you sure you want to delete {selectedNotes} {selectedNotes, plural, one {note} other {notes}}?', + }); +export const DELETE_NOTES_CANCEL = i18n.translate( + 'xpack.securitySolution.notes.management.deleteNotesCancel', + { + defaultMessage: 'Cancel', + } +); + +/** + * Renders a confirmation modal to delete notes in the notes management page + */ export const DeleteConfirmModal = React.memo(() => { const dispatch = useDispatch(); const pendingDeleteIds = useSelector(selectNotesTablePendingDeleteIds); @@ -33,16 +52,16 @@ export const DeleteConfirmModal = React.memo(() => { return ( - {i18n.DELETE_NOTES_CONFIRM(pendingDeleteIds.length)} + {DELETE_NOTES_CONFIRM(pendingDeleteIds.length)} ); }); diff --git a/x-pack/plugins/security_solution/public/notes/components/delete_note_button.tsx b/x-pack/plugins/security_solution/public/notes/components/delete_note_button.tsx index 3f9e757d3f5a5..4744c362e469c 100644 --- a/x-pack/plugins/security_solution/public/notes/components/delete_note_button.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/delete_note_button.tsx @@ -13,10 +13,10 @@ import { DELETE_NOTE_BUTTON_TEST_ID } from './test_ids'; import type { State } from '../../common/store'; import type { Note } from '../../../common/api/timeline'; import { - deleteNotes, ReqStatus, selectDeleteNotesError, selectDeleteNotesStatus, + userSelectedNotesForDeletion, } from '../store/notes.slice'; import { useAppToasts } from '../../common/hooks/use_app_toasts'; @@ -42,7 +42,8 @@ export interface DeleteNoteButtonIconProps { } /** - * Renders a button to delete a note + * Renders a button to delete a note. + * This button works in combination with the DeleteConfirmModal. */ export const DeleteNoteButtonIcon = memo(({ note, index }: DeleteNoteButtonIconProps) => { const dispatch = useDispatch(); @@ -54,8 +55,8 @@ export const DeleteNoteButtonIcon = memo(({ note, index }: DeleteNoteButtonIconP const deleteNoteFc = useCallback( (noteId: string) => { + dispatch(userSelectedNotesForDeletion(noteId)); setDeletingNoteId(noteId); - dispatch(deleteNotes({ ids: [noteId] })); }, [dispatch] ); diff --git a/x-pack/plugins/security_solution/public/notes/components/notes_list.tsx b/x-pack/plugins/security_solution/public/notes/components/notes_list.tsx index 47dcf89b06452..344935413731e 100644 --- a/x-pack/plugins/security_solution/public/notes/components/notes_list.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/notes_list.tsx @@ -10,6 +10,7 @@ import { EuiAvatar, EuiComment, EuiCommentList, EuiLoadingElastic } from '@elast import { useSelector } from 'react-redux'; import { FormattedRelative } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { DeleteConfirmModal } from './delete_confirm_modal'; import { OpenFlyoutButtonIcon } from './open_flyout_button'; import { OpenTimelineButtonIcon } from './open_timeline_button'; import { DeleteNoteButtonIcon } from './delete_note_button'; @@ -17,7 +18,11 @@ import { MarkdownRenderer } from '../../common/components/markdown_editor'; import { ADD_NOTE_LOADING_TEST_ID, NOTE_AVATAR_TEST_ID, NOTES_COMMENT_TEST_ID } from './test_ids'; import type { State } from '../../common/store'; import type { Note } from '../../../common/api/timeline'; -import { ReqStatus, selectCreateNoteStatus } from '../store/notes.slice'; +import { + ReqStatus, + selectCreateNoteStatus, + selectNotesTablePendingDeleteIds, +} from '../store/notes.slice'; import { useUserPrivileges } from '../../common/components/user_privileges'; export const ADDED_A_NOTE = i18n.translate('xpack.securitySolution.notes.addedANoteLabel', { @@ -59,41 +64,51 @@ export const NotesList = memo(({ notes, options }: NotesListProps) => { const createStatus = useSelector((state: State) => selectCreateNoteStatus(state)); + const pendingDeleteIds = useSelector(selectNotesTablePendingDeleteIds); + const isDeleteModalVisible = pendingDeleteIds.length > 0; + return ( - - {notes.map((note, index) => ( - {note.created && }} - event={ADDED_A_NOTE} - actions={ - <> - {note.eventId && !options?.hideFlyoutIcon && ( - - )} - {note.timelineId && note.timelineId.length > 0 && !options?.hideTimelineIcon && ( - - )} - {canDeleteNotes && } - - } - timelineAvatar={ - - } - > - {note.note || ''} - - ))} - {createStatus === ReqStatus.Loading && ( - - )} - + <> + + {notes.map((note, index) => ( + {note.created && }} + event={ADDED_A_NOTE} + actions={ + <> + {note.eventId && !options?.hideFlyoutIcon && ( + + )} + {note.timelineId && note.timelineId.length > 0 && !options?.hideTimelineIcon && ( + + )} + {canDeleteNotes && } + + } + timelineAvatar={ + + } + > + {note.note || ''} + + ))} + {createStatus === ReqStatus.Loading && ( + + )} + + {isDeleteModalVisible && } + ); }); diff --git a/x-pack/plugins/security_solution/public/notes/components/open_event_in_timeline.tsx b/x-pack/plugins/security_solution/public/notes/components/open_event_in_timeline.tsx deleted file mode 100644 index 43f039836ccad..0000000000000 --- a/x-pack/plugins/security_solution/public/notes/components/open_event_in_timeline.tsx +++ /dev/null @@ -1,24 +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 } from 'react'; -import { EuiLink } from '@elastic/eui'; -import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -import { useInvestigateInTimeline } from '../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline'; -import * as i18n from './translations'; - -export const OpenEventInTimeline: React.FC<{ eventId?: string | null }> = memo(({ eventId }) => { - const ecsRowData = { event: { id: [eventId] }, _id: eventId } as Ecs; - const { investigateInTimelineAlertClick } = useInvestigateInTimeline({ ecsRowData }); - - return ( - - {i18n.VIEW_EVENT_IN_TIMELINE} - - ); -}); - -OpenEventInTimeline.displayName = 'OpenEventInTimeline'; diff --git a/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.test.tsx b/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.test.tsx index eed5e5bcbd5da..c22a0ebff3fce 100644 --- a/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.test.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.test.tsx @@ -13,6 +13,7 @@ import { OpenFlyoutButtonIcon } from './open_flyout_button'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { DocumentDetailsRightPanelKey } from '../../flyout/document_details/shared/constants/panel_keys'; import { useSourcererDataView } from '../../sourcerer/containers'; +import { TableId } from '@kbn/securitysolution-data-table'; jest.mock('@kbn/expandable-flyout'); jest.mock('../../sourcerer/containers'); @@ -27,7 +28,11 @@ describe('OpenFlyoutButtonIcon', () => { const { getByTestId } = render( - + ); @@ -41,7 +46,11 @@ describe('OpenFlyoutButtonIcon', () => { const { getByTestId } = render( - + ); @@ -54,7 +63,7 @@ describe('OpenFlyoutButtonIcon', () => { params: { id: mockEventId, indexName: 'test1,test2', - scopeId: mockTimelineId, + scopeId: TableId.alertsOnAlertsPage, }, }, }); diff --git a/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.tsx b/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.tsx index 0c541cc95740c..34ae9405fdf86 100644 --- a/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/open_flyout_button.tsx @@ -6,9 +6,11 @@ */ import React, { memo, useCallback } from 'react'; +import type { IconType } from '@elastic/eui'; import { EuiButtonIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { TableId } from '@kbn/securitysolution-data-table'; import { OPEN_FLYOUT_BUTTON_TEST_ID } from './test_ids'; import { useSourcererDataView } from '../../sourcerer/containers'; import { SourcererScopeName } from '../../sourcerer/store/model'; @@ -31,44 +33,51 @@ export interface OpenFlyoutButtonIconProps { * Id of the timeline to pass to the flyout for scope */ timelineId: string; + /** + * Icon type to render in the button + */ + iconType: IconType; } /** - * Renders a button to open the alert and event details flyout + * Renders a button to open the alert and event details flyout. + * This component is meant to be used in timeline and the notes management page, where the cell actions are more basic (no filter in/out). */ -export const OpenFlyoutButtonIcon = memo(({ eventId, timelineId }: OpenFlyoutButtonIconProps) => { - const { selectedPatterns } = useSourcererDataView(SourcererScopeName.timeline); +export const OpenFlyoutButtonIcon = memo( + ({ eventId, timelineId, iconType }: OpenFlyoutButtonIconProps) => { + const { selectedPatterns } = useSourcererDataView(SourcererScopeName.timeline); - const { telemetry } = useKibana().services; - const { openFlyout } = useExpandableFlyoutApi(); + const { telemetry } = useKibana().services; + const { openFlyout } = useExpandableFlyoutApi(); - const handleClick = useCallback(() => { - openFlyout({ - right: { - id: DocumentDetailsRightPanelKey, - params: { - id: eventId, - indexName: selectedPatterns.join(','), - scopeId: timelineId, + const handleClick = useCallback(() => { + openFlyout({ + right: { + id: DocumentDetailsRightPanelKey, + params: { + id: eventId, + indexName: selectedPatterns.join(','), + scopeId: TableId.alertsOnAlertsPage, // TODO we should update the flyout's code to separate scopeId and preview + }, }, - }, - }); - telemetry.reportDetailsFlyoutOpened({ - location: timelineId, - panel: 'right', - }); - }, [eventId, openFlyout, selectedPatterns, telemetry, timelineId]); + }); + telemetry.reportDetailsFlyoutOpened({ + location: timelineId, + panel: 'right', + }); + }, [eventId, openFlyout, selectedPatterns, telemetry, timelineId]); - return ( - - ); -}); + return ( + + ); + } +); OpenFlyoutButtonIcon.displayName = 'OpenFlyoutButtonIcon'; diff --git a/x-pack/plugins/security_solution/public/notes/components/open_timeline_button.tsx b/x-pack/plugins/security_solution/public/notes/components/open_timeline_button.tsx index 531983429acd1..b44ffd55a767a 100644 --- a/x-pack/plugins/security_solution/public/notes/components/open_timeline_button.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/open_timeline_button.tsx @@ -7,11 +7,16 @@ import React, { memo, useCallback } from 'react'; import { EuiButtonIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; import { useQueryTimelineById } from '../../timelines/components/open_timeline/helpers'; import { OPEN_TIMELINE_BUTTON_TEST_ID } from './test_ids'; import type { Note } from '../../../common/api/timeline'; +const OPEN_TIMELINE = i18n.translate('xpack.securitySolution.notes.management.openTimelineButton', { + defaultMessage: 'Open saved timeline', +}); + export interface OpenTimelineButtonIconProps { /** * The note that contains the id of the timeline to open @@ -20,7 +25,7 @@ export interface OpenTimelineButtonIconProps { /** * The index of the note in the list of notes (used to have unique data-test-subj) */ - index: number; + index?: number; } /** @@ -47,10 +52,10 @@ export const OpenTimelineButtonIcon = memo(({ note, index }: OpenTimelineButtonI return ( openTimeline(note)} /> ); diff --git a/x-pack/plugins/security_solution/public/notes/components/translations.ts b/x-pack/plugins/security_solution/public/notes/components/translations.ts deleted file mode 100644 index 8d7a5b4262815..0000000000000 --- a/x-pack/plugins/security_solution/public/notes/components/translations.ts +++ /dev/null @@ -1,58 +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 { i18n } from '@kbn/i18n'; - -export const BATCH_ACTIONS = i18n.translate( - 'xpack.securitySolution.notes.management.batchActionsTitle', - { - defaultMessage: 'Bulk actions', - } -); - -export const DELETE = i18n.translate('xpack.securitySolution.notes.management.deleteAction', { - defaultMessage: 'Delete', -}); - -export const DELETE_NOTES_MODAL_TITLE = i18n.translate( - 'xpack.securitySolution.notes.management.deleteNotesModalTitle', - { - defaultMessage: 'Delete notes?', - } -); - -export const DELETE_NOTES_CONFIRM = (selectedNotes: number) => - i18n.translate('xpack.securitySolution.notes.management.deleteNotesConfirm', { - values: { selectedNotes }, - defaultMessage: - 'Are you sure you want to delete {selectedNotes} {selectedNotes, plural, one {note} other {notes}}?', - }); - -export const DELETE_NOTES_CANCEL = i18n.translate( - 'xpack.securitySolution.notes.management.deleteNotesCancel', - { - defaultMessage: 'Cancel', - } -); - -export const DELETE_SELECTED = i18n.translate( - 'xpack.securitySolution.notes.management.deleteSelected', - { - defaultMessage: 'Delete selected notes', - } -); - -export const REFRESH = i18n.translate('xpack.securitySolution.notes.management.refresh', { - defaultMessage: 'Refresh', -}); - -export const VIEW_EVENT_IN_TIMELINE = i18n.translate( - 'xpack.securitySolution.notes.management.viewEventInTimeline', - { - defaultMessage: 'View event in timeline', - } -); diff --git a/x-pack/plugins/security_solution/public/notes/components/utility_bar.tsx b/x-pack/plugins/security_solution/public/notes/components/utility_bar.tsx index 0c09f6393f668..f0a337cb6c217 100644 --- a/x-pack/plugins/security_solution/public/notes/components/utility_bar.tsx +++ b/x-pack/plugins/security_solution/public/notes/components/utility_bar.tsx @@ -4,9 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import React, { useMemo, useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { EuiContextMenuItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { UtilityBarGroup, UtilityBarText, @@ -22,8 +24,28 @@ import { selectNotesTableSearch, userSelectedBulkDelete, } from '..'; -import * as i18n from './translations'; +export const BATCH_ACTIONS = i18n.translate( + 'xpack.securitySolution.notes.management.batchActionsTitle', + { + defaultMessage: 'Bulk actions', + } +); + +export const DELETE_SELECTED = i18n.translate( + 'xpack.securitySolution.notes.management.deleteSelected', + { + defaultMessage: 'Delete selected notes', + } +); + +export const REFRESH = i18n.translate('xpack.securitySolution.notes.management.refresh', { + defaultMessage: 'Refresh', +}); + +/** + * Renders the utility bar for the notes management page + */ export const NotesUtilityBar = React.memo(() => { const dispatch = useDispatch(); const pagination = useSelector(selectNotesPagination); @@ -49,7 +71,7 @@ export const NotesUtilityBar = React.memo(() => { icon="trash" key="DeleteItemKey" > - {i18n.DELETE_SELECTED} + {DELETE_SELECTED} ); }, [deleteSelectedNotes, selectedItems.length]); @@ -83,9 +105,7 @@ export const NotesUtilityBar = React.memo(() => { iconType="arrowDown" popoverContent={BulkActionPopoverContent} > - - {i18n.BATCH_ACTIONS} - + {BATCH_ACTIONS} { iconType="refresh" onClick={refresh} > - {i18n.REFRESH} + {REFRESH} diff --git a/x-pack/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts b/x-pack/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts index c9f64bc382454..2cf599e76bcc9 100644 --- a/x-pack/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts +++ b/x-pack/plugins/security_solution/public/notes/hooks/use_fetch_notes.ts @@ -4,12 +4,23 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; -import { fetchNotesByDocumentIds } from '..'; +import { fetchNotesByDocumentIds } from '../store/notes.slice'; + +export interface UseFetchNotesResult { + /** + * Function to fetch the notes for an array of documents + */ + onLoad: (events: Array>) => void; +} -export const useFetchNotes = () => { +/** + * Hook that returns a function to fetch the notes for an array of documents + */ +export const useFetchNotes = (): UseFetchNotesResult => { const dispatch = useDispatch(); const securitySolutionNotesEnabled = useIsExperimentalFeatureEnabled( 'securitySolutionNotesEnabled' diff --git a/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx b/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx index ddfed3fbb6287..9c2900ca4d599 100644 --- a/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx +++ b/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx @@ -6,11 +6,18 @@ */ import React, { useCallback, useMemo, useEffect } from 'react'; -import type { DefaultItemAction, EuiBasicTableColumn } from '@elastic/eui'; -import { EuiBasicTable, EuiEmptyPrompt, EuiLink, EuiSpacer } from '@elastic/eui'; +import type { EuiBasicTableColumn } from '@elastic/eui'; +import { + EuiAvatar, + EuiBasicTable, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, +} from '@elastic/eui'; import { useDispatch, useSelector } from 'react-redux'; -import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; -import { useQueryTimelineById } from '../../timelines/components/open_timeline/helpers'; +import { css } from '@emotion/react'; +import { DeleteNoteButtonIcon } from '../components/delete_note_button'; import { Title } from '../../common/components/header_page/title'; // TODO unify this type from the api with the one in public/common/lib/note import type { Note } from '../../../common/api/timeline'; @@ -27,7 +34,6 @@ import { selectNotesTableSearch, selectFetchNotesStatus, selectNotesTablePendingDeleteIds, - userSelectedRowForDeletion, selectFetchNotesError, ReqStatus, } from '..'; @@ -36,42 +42,67 @@ import { SearchRow } from '../components/search_row'; import { NotesUtilityBar } from '../components/utility_bar'; import { DeleteConfirmModal } from '../components/delete_confirm_modal'; import * as i18n from './translations'; -import { OpenEventInTimeline } from '../components/open_event_in_timeline'; - -const columns: ( - onOpenTimeline: (timelineId: string) => void -) => Array> = (onOpenTimeline) => { - return [ - { - field: 'created', - name: i18n.CREATED_COLUMN, - sortable: true, - render: (created: Note['created']) => , - }, - { - field: 'createdBy', - name: i18n.CREATED_BY_COLUMN, - }, - { - field: 'eventId', - name: i18n.EVENT_ID_COLUMN, - sortable: true, - render: (eventId: Note['eventId']) => , - }, - { - field: 'timelineId', - name: i18n.TIMELINE_ID_COLUMN, - render: (timelineId: Note['timelineId']) => - timelineId ? ( - onOpenTimeline(timelineId)}>{i18n.OPEN_TIMELINE} - ) : null, - }, - { - field: 'note', - name: i18n.NOTE_CONTENT_COLUMN, - }, - ]; -}; +import { OpenFlyoutButtonIcon } from '../components/open_flyout_button'; +import { OpenTimelineButtonIcon } from '../components/open_timeline_button'; + +const columns: Array> = [ + { + name: i18n.ACTIONS_COLUMN, + render: (note: Note) => ( + + + {note.eventId ? ( + + ) : null} + + + <>{note.timelineId ? : null} + + + + + + ), + width: '72px', + }, + { + field: 'createdBy', + name: i18n.CREATED_BY_COLUMN, + render: (createdBy: Note['createdBy']) => , + width: '100px', + align: 'center', + }, + { + field: 'note', + name: i18n.NOTE_CONTENT_COLUMN, + }, + { + field: 'created', + name: i18n.CREATED_COLUMN, + sortable: true, + render: (created: Note['created']) => , + width: '225px', + }, +]; const pageSizeOptions = [10, 25, 50, 100]; @@ -129,13 +160,6 @@ export const NoteManagementPage = () => { [dispatch] ); - const selectRowForDeletion = useCallback( - (id: string) => { - dispatch(userSelectedRowForDeletion(id)); - }, - [dispatch] - ); - const onSelectionChange = useCallback( (selection: Note[]) => { const rowIds = selection.map((item) => item.noteId); @@ -148,39 +172,6 @@ export const NoteManagementPage = () => { return item.noteId; }, []); - const unifiedComponentsInTimelineDisabled = useIsExperimentalFeatureEnabled( - 'unifiedComponentsInTimelineDisabled' - ); - const queryTimelineById = useQueryTimelineById(); - const openTimeline = useCallback( - (timelineId: string) => - queryTimelineById({ - timelineId, - unifiedComponentsInTimelineDisabled, - }), - [queryTimelineById, unifiedComponentsInTimelineDisabled] - ); - - const columnWithActions = useMemo(() => { - const actions: Array> = [ - { - name: i18n.DELETE, - description: i18n.DELETE_SINGLE_NOTE_DESCRIPTION, - color: 'primary', - icon: 'trash', - type: 'icon', - onClick: (note: Note) => selectRowForDeletion(note.noteId), - }, - ]; - return [ - ...columns(openTimeline), - { - name: 'actions', - actions, - }, - ]; - }, [selectRowForDeletion, openTimeline]); - const currentPagination = useMemo(() => { return { pageIndex: pagination.page - 1, @@ -223,7 +214,7 @@ export const NoteManagementPage = () => { { }); }); - describe('userSelectedRowForDeletion', () => { - it('should set correct id when user selects a row', () => { - const action = { type: userSelectedRowForDeletion.type, payload: '1' }; + describe('userSelectedNotesForDeletion', () => { + it('should set correct id when user selects a note to delete', () => { + const action = { type: userSelectedNotesForDeletion.type, payload: '1' }; expect(notesReducer(initalEmptyState, action)).toEqual({ ...initalEmptyState, diff --git a/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts b/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts index 6732f9491676e..2d24ab838ee06 100644 --- a/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts +++ b/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts @@ -193,7 +193,7 @@ const notesSlice = createSlice({ userClosedDeleteModal: (state) => { state.pendingDeleteIds = []; }, - userSelectedRowForDeletion: (state, action: { payload: string }) => { + userSelectedNotesForDeletion: (state, action: { payload: string }) => { state.pendingDeleteIds = [action.payload]; }, userSelectedBulkDelete: (state) => { @@ -391,6 +391,6 @@ export const { userSearchedNotes, userSelectedRow, userClosedDeleteModal, - userSelectedRowForDeletion, + userSelectedNotesForDeletion, userSelectedBulkDelete, } = notesSlice.actions; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 8cc1a3c11c7a0..98bb75268cac7 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -39634,18 +39634,13 @@ "xpack.securitySolution.notes.management.createdByColumnTitle": "Créé par", "xpack.securitySolution.notes.management.createdColumnTitle": "Créé", "xpack.securitySolution.notes.management.deleteAction": "Supprimer", - "xpack.securitySolution.notes.management.deleteDescription": "Supprimer cette note", "xpack.securitySolution.notes.management.deleteNotesCancel": "Annuler", "xpack.securitySolution.notes.management.deleteNotesConfirm": "Voulez-vous vraiment supprimer {selectedNotes} {selectedNotes, plural, one {note} other {notes}} ?", - "xpack.securitySolution.notes.management.deleteNotesModalTitle": "Supprimer les notes ?", "xpack.securitySolution.notes.management.deleteSelected": "Supprimer les notes sélectionnées", - "xpack.securitySolution.notes.management.eventIdColumnTitle": "Afficher le document", "xpack.securitySolution.notes.management.noteContentColumnTitle": "Contenu de la note", "xpack.securitySolution.notes.management.openTimeline": "Ouvrir la chronologie", "xpack.securitySolution.notes.management.refresh": "Actualiser", "xpack.securitySolution.notes.management.tableError": "Impossible de charger les notes", - "xpack.securitySolution.notes.management.timelineColumnTitle": "Chronologie", - "xpack.securitySolution.notes.management.viewEventInTimeline": "Afficher l'événement dans la chronologie", "xpack.securitySolution.notes.noteLabel": "Note", "xpack.securitySolution.notes.notesTitle": "Notes", "xpack.securitySolution.notes.search.FilterByUserOrNotePlaceholder": "Filtre par utilisateur ou note", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a9337cc088189..e512f0043493a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -39378,18 +39378,13 @@ "xpack.securitySolution.notes.management.createdByColumnTitle": "作成者", "xpack.securitySolution.notes.management.createdColumnTitle": "作成済み", "xpack.securitySolution.notes.management.deleteAction": "削除", - "xpack.securitySolution.notes.management.deleteDescription": "このメモを削除", "xpack.securitySolution.notes.management.deleteNotesCancel": "キャンセル", "xpack.securitySolution.notes.management.deleteNotesConfirm": "{selectedNotes} {selectedNotes, plural, other {件のメモ}}を削除しますか?", - "xpack.securitySolution.notes.management.deleteNotesModalTitle": "メモを削除しますか?", "xpack.securitySolution.notes.management.deleteSelected": "選択したメモを削除", - "xpack.securitySolution.notes.management.eventIdColumnTitle": "ドキュメンテーションを表示", "xpack.securitySolution.notes.management.noteContentColumnTitle": "メモコンテンツ", "xpack.securitySolution.notes.management.openTimeline": "タイムラインを開く", "xpack.securitySolution.notes.management.refresh": "更新", "xpack.securitySolution.notes.management.tableError": "メモを読み込めません", - "xpack.securitySolution.notes.management.timelineColumnTitle": "Timeline", - "xpack.securitySolution.notes.management.viewEventInTimeline": "タイムラインでイベントを表示", "xpack.securitySolution.notes.noteLabel": "注", "xpack.securitySolution.notes.notesTitle": "メモ", "xpack.securitySolution.notes.search.FilterByUserOrNotePlaceholder": "ユーザーまたはメモでフィルター", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e1445a676c414..34433ec376a70 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -39423,18 +39423,13 @@ "xpack.securitySolution.notes.management.createdByColumnTitle": "创建者", "xpack.securitySolution.notes.management.createdColumnTitle": "创建时间", "xpack.securitySolution.notes.management.deleteAction": "删除", - "xpack.securitySolution.notes.management.deleteDescription": "删除此备注", "xpack.securitySolution.notes.management.deleteNotesCancel": "取消", "xpack.securitySolution.notes.management.deleteNotesConfirm": "是否确定要删除 {selectedNotes} 个{selectedNotes, plural, other {备注}}?", - "xpack.securitySolution.notes.management.deleteNotesModalTitle": "删除备注?", "xpack.securitySolution.notes.management.deleteSelected": "删除所选备注", - "xpack.securitySolution.notes.management.eventIdColumnTitle": "查看文档", "xpack.securitySolution.notes.management.noteContentColumnTitle": "备注内容", "xpack.securitySolution.notes.management.openTimeline": "打开时间线", "xpack.securitySolution.notes.management.refresh": "刷新", "xpack.securitySolution.notes.management.tableError": "无法加载备注", - "xpack.securitySolution.notes.management.timelineColumnTitle": "时间线", - "xpack.securitySolution.notes.management.viewEventInTimeline": "在时间线中查看事件", "xpack.securitySolution.notes.noteLabel": "备注", "xpack.securitySolution.notes.notesTitle": "备注", "xpack.securitySolution.notes.search.FilterByUserOrNotePlaceholder": "按用户或备注筛选",