diff --git a/x-pack/plugins/security_solution/public/notes/components/note_content.test.tsx b/x-pack/plugins/security_solution/public/notes/components/note_content.test.tsx new file mode 100644 index 0000000000000..6cc9d33d886b7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/notes/components/note_content.test.tsx @@ -0,0 +1,28 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; +import { NoteContent } from './note_content'; +import { NOTE_CONTENT_BUTTON_TEST_ID, NOTE_CONTENT_POPOVER_TEST_ID } from './test_ids'; + +const note = 'note-text'; + +describe('NoteContent', () => { + it('should render a note and the popover', () => { + const { getByTestId, getByText } = render(); + + const button = getByTestId(NOTE_CONTENT_BUTTON_TEST_ID); + + expect(button).toBeInTheDocument(); + expect(getByText(note)).toBeInTheDocument(); + + button.click(); + + expect(getByTestId(NOTE_CONTENT_POPOVER_TEST_ID)).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/notes/components/note_content.tsx b/x-pack/plugins/security_solution/public/notes/components/note_content.tsx new file mode 100644 index 0000000000000..ba8710e85c215 --- /dev/null +++ b/x-pack/plugins/security_solution/public/notes/components/note_content.tsx @@ -0,0 +1,73 @@ +/* + * 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, useCallback, useMemo, useState } from 'react'; +import { EuiButtonEmpty, EuiMarkdownFormat, EuiPopover, useEuiTheme } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import { NOTE_CONTENT_BUTTON_TEST_ID, NOTE_CONTENT_POPOVER_TEST_ID } from './test_ids'; + +const OPEN_POPOVER = i18n.translate('xpack.securitySolution.notes.expandRow.buttonLabel', { + defaultMessage: 'Expand', +}); + +export interface NoteContentProps { + /** + * The note content to display + */ + note: string; +} + +/** + * Renders the note content to be displayed in the notes management table. + * The content is truncated with an expand button to show the full content within the row. + */ +export const NoteContent = memo(({ note }: NoteContentProps) => { + const { euiTheme } = useEuiTheme(); + + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const togglePopover = useCallback(() => setIsPopoverOpen((value) => !value), []); + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + + const button = useMemo( + () => ( + + {note} + + ), + [euiTheme.size.l, note, togglePopover] + ); + + return ( + + + {note} + + + ); +}); + +NoteContent.displayName = 'NoteContent'; diff --git a/x-pack/plugins/security_solution/public/notes/components/test_ids.ts b/x-pack/plugins/security_solution/public/notes/components/test_ids.ts index 6c63a43f365ac..ac4eeb1948748 100644 --- a/x-pack/plugins/security_solution/public/notes/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/notes/components/test_ids.ts @@ -17,3 +17,5 @@ export const DELETE_NOTE_BUTTON_TEST_ID = `${PREFIX}DeleteNotesButton` as const; export const OPEN_TIMELINE_BUTTON_TEST_ID = `${PREFIX}OpenTimelineButton` as const; export const OPEN_FLYOUT_BUTTON_TEST_ID = `${PREFIX}OpenFlyoutButton` as const; export const TIMELINE_DESCRIPTION_COMMENT_TEST_ID = `${PREFIX}TimelineDescriptionComment` as const; +export const NOTE_CONTENT_BUTTON_TEST_ID = `${PREFIX}NoteContentButton` as const; +export const NOTE_CONTENT_POPOVER_TEST_ID = `${PREFIX}NoteContentPopover` as const; 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 9c2900ca4d599..2b7f0f690532c 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 @@ -44,6 +44,7 @@ import { DeleteConfirmModal } from '../components/delete_confirm_modal'; import * as i18n from './translations'; import { OpenFlyoutButtonIcon } from '../components/open_flyout_button'; import { OpenTimelineButtonIcon } from '../components/open_timeline_button'; +import { NoteContent } from '../components/note_content'; const columns: Array> = [ { @@ -94,6 +95,7 @@ const columns: Array> = [ { field: 'note', name: i18n.NOTE_CONTENT_COLUMN, + render: (note: Note['note']) => <>{note && }, }, { field: 'created',