Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UnifiedDataTable] Add stripes configuration #188793

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/kbn-unified-data-table/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ Props description:
| **externalCustomRenderers** | (optional)Record<string,(props: EuiDataGridCellValueElementProps) => React.ReactNode>; | An optional settings for a specified fields rendering like links. Applied only for the listed fields rendering. |
| **consumer** | (optional)string | Name of the UnifiedDataTable consumer component or application. |
| **componentsTourSteps** | (optional)Record<string,string> | Optional key/value pairs to set guided onboarding steps ids for a data table components included to guided tour. |
| **showDensitySelector** | (optional)boolean | Optional boolean to toggle whether or not to show the density selector. |
| **onUpdateGridStyle** | (optional)(EuiDataGridStyle) => void; | Optional callback when the data grid style is modified. |
| **showStripesSelector** | (optional)boolean | Optional boolean to toggle whether or not to show the stripes~~~~ selector. |

*Required **services** list:
```
Expand Down
85 changes: 64 additions & 21 deletions packages/kbn-unified-data-table/src/components/data_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
EuiDataGridProps,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
} from '@elastic/eui';
import type { DataView } from '@kbn/data-views-plugin/public';
import {
Expand Down Expand Up @@ -75,7 +76,6 @@ import {
import { useRowHeightsOptions } from '../hooks/use_row_heights_options';
import {
DEFAULT_ROWS_PER_PAGE,
GRID_STYLE,
ROWS_HEIGHT_OPTIONS,
toolbarVisibility as toolbarVisibilityDefaults,
} from '../constants';
Expand All @@ -90,6 +90,7 @@ import {
getColorIndicatorControlColumn,
type ColorIndicatorControlColumnParams,
} from './custom_control_columns';
import { useDataGridStyle } from '../hooks/use_data_grid_style';

export type SortOrder = [string, string];

Expand Down Expand Up @@ -232,6 +233,18 @@ export interface UnifiedDataTableProps {
* Update row height state
*/
onUpdateRowHeight?: (rowHeight: number) => void;
/**
* Whether or not to show the density selector
*/
showDensitySelector?: boolean;
/**
* Whether or not to show the stripes selector
*/
showStripesSelector?: boolean;
/**
* Callback when the data grid style configuration is modified
*/
onUpdateDataGridStyle?: (dataGridStyle: EuiDataGridStyle) => void;
/**
* Is text base lang mode enabled
*/
Expand Down Expand Up @@ -467,6 +480,9 @@ export const UnifiedDataTable = ({
cellContext,
renderCellPopover,
getRowIndicator,
showDensitySelector = false,
showStripesSelector = false,
onUpdateDataGridStyle,
}: UnifiedDataTableProps) => {
const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings, storage, data } =
services;
Expand Down Expand Up @@ -610,6 +626,12 @@ export const UnifiedDataTable = ({
return getShouldShowFieldHandler(dataViewFields, dataView, showMultiFields);
}, [dataView, showMultiFields]);

const { dataGridStyle, onChangeDataGridStyle } = useDataGridStyle({
storage,
consumer,
onUpdateDataGridStyle,
});

/**
* Cell rendering
*/
Expand All @@ -625,6 +647,7 @@ export const UnifiedDataTable = ({
maxEntries: maxDocFieldsDisplayed,
externalCustomRenderers,
isPlainRecord,
isCompressed: dataGridStyle.fontSize === 's',
}),
[
dataView,
Expand All @@ -635,6 +658,7 @@ export const UnifiedDataTable = ({
fieldFormats,
externalCustomRenderers,
isPlainRecord,
dataGridStyle,
]
);

Expand Down Expand Up @@ -939,30 +963,39 @@ export const UnifiedDataTable = ({
[renderCustomToolbar, additionalControls]
);

const showDisplaySelector = useMemo(() => {
const options: EuiDataGridToolBarVisibilityDisplaySelectorOptions = {};
const onChangeShowStripes = useMemo(() => {
return !showStripesSelector
? undefined
: (stripes: boolean) => onChangeDataGridStyle({ ...dataGridStyle, stripes });
}, [showStripesSelector, onChangeDataGridStyle, dataGridStyle]);

if (onUpdateRowHeight) {
options.allowDensity = false;
}
const showDisplaySelector = useMemo(() => {
const options: EuiDataGridToolBarVisibilityDisplaySelectorOptions = {
allowDensity: showDensitySelector,
};

if (onUpdateRowHeight || onUpdateHeaderRowHeight || onUpdateSampleSize) {
if (onUpdateRowHeight || onUpdateHeaderRowHeight || onUpdateSampleSize || showStripesSelector) {
options.allowRowHeight = false;
options.allowResetButton = false;
options.additionalDisplaySettings = (
<UnifiedDataTableAdditionalDisplaySettings
rowHeight={rowHeight}
rowHeightLines={rowHeightLines}
onChangeRowHeight={onChangeRowHeight}
onChangeRowHeightLines={onChangeRowHeightLines}
headerRowHeight={headerRowHeight}
headerRowHeightLines={headerRowHeightLines}
onChangeHeaderRowHeight={onChangeHeaderRowHeight}
onChangeHeaderRowHeightLines={onChangeHeaderRowHeightLines}
maxAllowedSampleSize={maxAllowedSampleSize}
sampleSize={sampleSizeState}
onChangeSampleSize={onUpdateSampleSize}
/>
<>
{showDensitySelector ? <EuiHorizontalRule margin="s" /> : ''}
<UnifiedDataTableAdditionalDisplaySettings
rowHeight={rowHeight}
rowHeightLines={rowHeightLines}
onChangeRowHeight={onChangeRowHeight}
onChangeRowHeightLines={onChangeRowHeightLines}
headerRowHeight={headerRowHeight}
headerRowHeightLines={headerRowHeightLines}
onChangeHeaderRowHeight={onChangeHeaderRowHeight}
onChangeHeaderRowHeightLines={onChangeHeaderRowHeightLines}
maxAllowedSampleSize={maxAllowedSampleSize}
sampleSize={sampleSizeState}
onChangeSampleSize={onUpdateSampleSize}
showStripes={dataGridStyle.stripes}
onChangeShowStripes={onChangeShowStripes}
/>
</>
);
}

Expand All @@ -981,6 +1014,10 @@ export const UnifiedDataTable = ({
rowHeight,
rowHeightLines,
sampleSizeState,
showDensitySelector,
dataGridStyle,
onChangeShowStripes,
onUpdateDataGridStyle,
]);

const inMemory = useMemo(() => {
Expand Down Expand Up @@ -1053,6 +1090,12 @@ export const UnifiedDataTable = ({
);
}

const gridStyle: EuiDataGridStyle = {
...dataGridStyle,
onChange: onChangeDataGridStyle,
...gridStyleOverride,
};

return (
<UnifiedDataTableContext.Provider value={unifiedDataTableContextValue}>
<span className="unifiedDataTable__inner">
Expand Down Expand Up @@ -1106,7 +1149,7 @@ export const UnifiedDataTable = ({
toolbarVisibility={toolbarVisibility}
rowHeightsOptions={rowHeightsOptions}
inMemory={inMemory}
gridStyle={gridStyleOverride ?? GRID_STYLE}
gridStyle={gridStyle}
renderCustomGridBody={renderCustomGridBody}
renderCustomToolbar={renderCustomToolbarFn}
trailingControlColumns={customTrailingControlColumn}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,28 @@ describe('UnifiedDataTableAdditionalDisplaySettings', function () {
expect(onChangeHeaderRowHeight).toHaveBeenCalledWith('auto');
});
});

describe('showStripes', () => {
it('should render showStripes if onChangeShowStripes is defined', () => {
renderDisplaySettings({
onChangeShowStripes: jest.fn(),
});
expect(screen.queryByText('Show row stripes')).toBeInTheDocument();
});

it('should not render showStripes if onChangeShowStripes is undefined', () => {
renderDisplaySettings();
expect(screen.queryByText('Show row stripes')).not.toBeInTheDocument();
});

it('should call onChangeShowStripes when showStripes changes', () => {
const onChangeShowStripes = jest.fn();
renderDisplaySettings({
showStripes: false,
onChangeShowStripes,
});
userEvent.click(screen.getByTestId('unifiedDataTableShowStripes'));
expect(onChangeShowStripes).toHaveBeenCalledWith(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { EuiFormRow, EuiHorizontalRule, EuiRange } from '@elastic/eui';
import { EuiFormRow, EuiHorizontalRule, EuiRange, EuiSwitch } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { debounce } from 'lodash';
import { RowHeightSettings, RowHeightSettingsProps } from './row_height_settings';
Expand All @@ -29,6 +29,8 @@ export interface UnifiedDataTableAdditionalDisplaySettingsProps {
maxAllowedSampleSize?: number;
sampleSize: number;
onChangeSampleSize?: (sampleSize: number) => void;
showStripes?: boolean;
onChangeShowStripes?: (showStripes: boolean) => void;
}

const defaultOnChangeSampleSize = () => {};
Expand All @@ -47,6 +49,8 @@ export const UnifiedDataTableAdditionalDisplaySettings: React.FC<
maxAllowedSampleSize = DEFAULT_MAX_ALLOWED_SAMPLE_SIZE,
sampleSize,
onChangeSampleSize,
showStripes = true,
onChangeShowStripes,
}) => {
const [activeSampleSize, setActiveSampleSize] = useState<number | ''>(sampleSize);
const minRangeSampleSize = Math.max(
Expand Down Expand Up @@ -141,6 +145,21 @@ export const UnifiedDataTableAdditionalDisplaySettings: React.FC<
);
}

if (onChangeShowStripes) {
settings.push(
<EuiFormRow>
<EuiSwitch
label={i18n.translate('unifiedDataTable.showStripesLabel', {
defaultMessage: 'Show row stripes',
})}
checked={showStripes}
onChange={(e) => onChangeShowStripes(e.target.checked)}
data-test-subj="unifiedDataTableShowStripes"
/>
</EuiFormRow>
);
}

return (
<>
{settings.map((setting, index) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function SourceDocument({
fieldFormats,
dataTestSubj = 'discoverCellDescriptionList',
className,
isCompressed = true,
}: {
useTopLevelObjectColumns: boolean;
row: DataTableRecord;
Expand All @@ -48,6 +49,7 @@ export function SourceDocument({
fieldFormats: FieldFormatsStart;
dataTestSubj?: string;
className?: string;
isCompressed?: boolean;
}) {
const pairs: FormattedHit = useTopLevelObjectColumns
? getTopLevelObjectPairs(row.raw, columnId, dataView, shouldShowFieldHandler).slice(
Expand All @@ -59,7 +61,7 @@ export function SourceDocument({
return (
<EuiDescriptionList
type="inline"
compressed
compressed={isCompressed}
className={classnames('unifiedDataTable__descriptionList', CELL_CLASS, className)}
data-test-subj={dataTestSubj}
>
Expand Down
3 changes: 2 additions & 1 deletion packages/kbn-unified-data-table/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ export const defaultMonacoEditorWidth = 370;
export const defaultTimeColumnWidth = 212;
export const kibanaJSON = 'kibana-json';

// Matches the EuiDataGrid "compact" density options
export const GRID_STYLE: EuiDataGridStyle = {
border: 'horizontal',
fontSize: 's',
cellPadding: 'l',
cellPadding: 's',
rowHover: 'highlight',
header: 'underline',
stripes: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type { EuiDataGridStyle } from '@elastic/eui';
import type { Storage } from '@kbn/kibana-utils-plugin/public';
import { renderHook } from '@testing-library/react-hooks';
import { useDataGridStyle } from './use_data_grid_style';

const localStorageMock = {
get: jest.fn(),
set: jest.fn(),
};

describe('useDataGridStyle', () => {
beforeEach(() => {
localStorageMock.get.mockClear();
localStorageMock.set.mockClear();
});

it('should read from local storage', () => {
localStorageMock.get.mockReturnValue({ foo: 'bar' });
const { result } = renderHook(() =>
useDataGridStyle({
storage: localStorageMock as unknown as Storage,
consumer: 'discover',
})
);
const {
current: { dataGridStyle },
} = result;
expect(dataGridStyle).toMatchInlineSnapshot(`
Object {
"foo": "bar",
}
`);
});

it('should update local storage when onChangeDataGridStyle is called', () => {
const { result } = renderHook(() =>
useDataGridStyle({
storage: localStorageMock as unknown as Storage,
consumer: 'discover',
})
);
const {
current: { onChangeDataGridStyle },
} = result;

const newValue: EuiDataGridStyle = { border: 'all', footer: 'shade' };
onChangeDataGridStyle(newValue);

expect(localStorageMock.set).toBeCalledWith('discover:dataGridStyle', newValue);
});

it('should call provided onUpdateDataGridStyle with the updated value', () => {
const onUpdateDataGridStyle = jest.fn();
const { result } = renderHook(() =>
useDataGridStyle({
storage: localStorageMock as unknown as Storage,
consumer: 'discover',
onUpdateDataGridStyle,
})
);
const {
current: { onChangeDataGridStyle },
} = result;

const newValue: EuiDataGridStyle = { border: 'all', footer: 'shade' };
onChangeDataGridStyle(newValue);

expect(onUpdateDataGridStyle).toBeCalledWith(newValue);
});
});
Loading