mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Discover] Don't truncate long field descriptions if user expanded them previously (#188841)
- Closes https://github.com/elastic/kibana/issues/188508 ## Summary This is a follow up PR for https://github.com/elastic/kibana/pull/187160#pullrequestreview-2181768414. It stores the toggle state in local storage under `fieldDescription:truncateByDefault`. To test, open field popover from a sidebar to see ECS field description or a custom field description. By default it should be truncated. But after expanding (by clicking on the short description), it will expand automatically when opening another field popover next time. Please note that it does not affect field descriptions in DocViewer popover as they are always shown in full length there. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
145f65275c
commit
db6886fb03
2 changed files with 57 additions and 4 deletions
|
@ -10,8 +10,27 @@ import React from 'react';
|
|||
import { FieldDescription } from './field_description';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public';
|
||||
import { SHOULD_TRUNCATE_FIELD_DESCRIPTION_LOCALSTORAGE_KEY } from './field_description';
|
||||
|
||||
const mockSetLocalStorage = jest.fn();
|
||||
const mockLocalStorageKey = SHOULD_TRUNCATE_FIELD_DESCRIPTION_LOCALSTORAGE_KEY;
|
||||
let mockTestInitialLocalStorageValue: boolean | undefined;
|
||||
|
||||
jest.mock('react-use/lib/useLocalStorage', () => {
|
||||
return jest.fn((key: string, initialValue: number) => {
|
||||
if (key !== mockLocalStorageKey) {
|
||||
throw new Error(`Unexpected key: ${key}`);
|
||||
}
|
||||
return [mockTestInitialLocalStorageValue ?? initialValue, mockSetLocalStorage];
|
||||
});
|
||||
});
|
||||
|
||||
describe('FieldDescription', () => {
|
||||
afterEach(() => {
|
||||
mockSetLocalStorage.mockReset();
|
||||
mockTestInitialLocalStorageValue = undefined;
|
||||
});
|
||||
|
||||
it('should render correctly when no custom description', async () => {
|
||||
render(<FieldDescription field={{ name: 'bytes', type: 'number' }} />);
|
||||
const desc = screen.queryByTestId('fieldDescription-bytes');
|
||||
|
@ -35,8 +54,23 @@ describe('FieldDescription', () => {
|
|||
expect(screen.queryByTestId('fieldDescription-bytes')).toHaveTextContent(
|
||||
`${customDescription}View less`
|
||||
);
|
||||
expect(mockSetLocalStorage).toHaveBeenCalledWith(false);
|
||||
screen.queryByTestId('toggleFieldDescription-bytes')?.click();
|
||||
expect(screen.queryByTestId('fieldDescription-bytes')).toHaveTextContent(customDescription);
|
||||
expect(mockSetLocalStorage).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('should render correctly with a long custom description and do not truncate it by default as per local storage', async () => {
|
||||
mockTestInitialLocalStorageValue = false;
|
||||
const customDescription = 'test this long desc '.repeat(8).trim();
|
||||
render(<FieldDescription field={{ name: 'bytes', type: 'number', customDescription }} />);
|
||||
expect(screen.queryByTestId('fieldDescription-bytes')).toHaveTextContent(
|
||||
`${customDescription}View less`
|
||||
);
|
||||
expect(mockSetLocalStorage).not.toHaveBeenCalled();
|
||||
screen.queryByTestId('toggleFieldDescription-bytes')?.click();
|
||||
expect(screen.queryByTestId('fieldDescription-bytes')).toHaveTextContent(customDescription);
|
||||
expect(mockSetLocalStorage).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('should render a long custom description without truncation', async () => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Markdown } from '@kbn/shared-ux-markdown';
|
||||
import {
|
||||
|
@ -19,6 +19,11 @@ import {
|
|||
import { css } from '@emotion/react';
|
||||
import type { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public';
|
||||
import { esFieldTypeToKibanaFieldType } from '@kbn/field-types';
|
||||
import useLocalStorage from 'react-use/lib/useLocalStorage';
|
||||
|
||||
const SHOULD_TRUNCATE_FIELD_DESCRIPTION_BY_DEFAULT = true;
|
||||
export const SHOULD_TRUNCATE_FIELD_DESCRIPTION_LOCALSTORAGE_KEY =
|
||||
'fieldDescription:truncateByDefault';
|
||||
|
||||
const MAX_VISIBLE_LENGTH = 110;
|
||||
|
||||
|
@ -81,10 +86,24 @@ const EcsFieldDescriptionFallback: React.FC<
|
|||
export const FieldDescriptionContent: React.FC<
|
||||
FieldDescriptionContentProps & { ecsFieldDescription?: string }
|
||||
> = ({ field, color, truncate = true, ecsFieldDescription, Wrapper }) => {
|
||||
const [shouldTruncateByDefault, setShouldTruncateByDefault] = useLocalStorage<boolean>(
|
||||
SHOULD_TRUNCATE_FIELD_DESCRIPTION_LOCALSTORAGE_KEY,
|
||||
SHOULD_TRUNCATE_FIELD_DESCRIPTION_BY_DEFAULT
|
||||
);
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const customDescription = (field?.customDescription || ecsFieldDescription || '').trim();
|
||||
const isTooLong = Boolean(truncate && customDescription.length > MAX_VISIBLE_LENGTH);
|
||||
const [isTruncated, setIsTruncated] = useState<boolean>(isTooLong);
|
||||
const [isTruncated, setIsTruncated] = useState<boolean>(
|
||||
(shouldTruncateByDefault ?? SHOULD_TRUNCATE_FIELD_DESCRIPTION_BY_DEFAULT) && isTooLong
|
||||
);
|
||||
|
||||
const truncateFieldDescription = useCallback(
|
||||
(nextValue) => {
|
||||
setIsTruncated(nextValue);
|
||||
setShouldTruncateByDefault(nextValue);
|
||||
},
|
||||
[setIsTruncated, setShouldTruncateByDefault]
|
||||
);
|
||||
|
||||
if (!customDescription) {
|
||||
return null;
|
||||
|
@ -100,7 +119,7 @@ export const FieldDescriptionContent: React.FC<
|
|||
defaultMessage: 'View full field description',
|
||||
})}
|
||||
className="eui-textBreakWord eui-textLeft"
|
||||
onClick={() => setIsTruncated(false)}
|
||||
onClick={() => truncateFieldDescription(false)}
|
||||
css={css`
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
@ -130,7 +149,7 @@ export const FieldDescriptionContent: React.FC<
|
|||
size="xs"
|
||||
flush="both"
|
||||
data-test-subj={`toggleFieldDescription-${field.name}`}
|
||||
onClick={() => setIsTruncated(true)}
|
||||
onClick={() => truncateFieldDescription(true)}
|
||||
>
|
||||
{i18n.translate('fieldUtils.fieldDescription.viewLessButton', {
|
||||
defaultMessage: 'View less',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue