mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Lens] Supports multi rows headers for the table visualization (#127447)
* [Lens] Supports multi rows headers * Apply design changes * Use emotion instead * column styling implementation entirely with emotion * Merge the 2 funstions into one Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
e71b9b1566
commit
4e63701fcb
9 changed files with 322 additions and 109 deletions
|
@ -29,6 +29,8 @@ export interface DatatableArgs {
|
|||
sortingDirection: SortingState['direction'];
|
||||
fitRowToContent?: boolean;
|
||||
rowHeightLines?: number;
|
||||
headerRowHeight?: 'auto' | 'single' | 'custom';
|
||||
headerRowHeightLines?: number;
|
||||
pageSize?: PagingState['size'];
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,14 @@ export const getDatatable = (
|
|||
types: ['number'],
|
||||
help: '',
|
||||
},
|
||||
headerRowHeight: {
|
||||
types: ['string'],
|
||||
help: '',
|
||||
},
|
||||
headerRowHeightLines: {
|
||||
types: ['number'],
|
||||
help: '',
|
||||
},
|
||||
pageSize: {
|
||||
types: ['number'],
|
||||
help: '',
|
||||
|
|
|
@ -126,7 +126,15 @@ exports[`DatatableComponent it renders actions column when there are row actions
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--left"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "13brihr",
|
||||
"next": undefined,
|
||||
"styles": "text-align:left;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
a
|
||||
</div>,
|
||||
|
@ -167,7 +175,15 @@ exports[`DatatableComponent it renders actions column when there are row actions
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--left"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "13brihr",
|
||||
"next": undefined,
|
||||
"styles": "text-align:left;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
b
|
||||
</div>,
|
||||
|
@ -208,7 +224,15 @@ exports[`DatatableComponent it renders actions column when there are row actions
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--right"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "s2uf1z",
|
||||
"next": undefined,
|
||||
"styles": "text-align:right;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
c
|
||||
</div>,
|
||||
|
@ -378,7 +402,15 @@ exports[`DatatableComponent it renders the title and value 1`] = `
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--left"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "13brihr",
|
||||
"next": undefined,
|
||||
"styles": "text-align:left;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
a
|
||||
</div>,
|
||||
|
@ -419,7 +451,15 @@ exports[`DatatableComponent it renders the title and value 1`] = `
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--left"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "13brihr",
|
||||
"next": undefined,
|
||||
"styles": "text-align:left;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
b
|
||||
</div>,
|
||||
|
@ -460,7 +500,15 @@ exports[`DatatableComponent it renders the title and value 1`] = `
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--right"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "s2uf1z",
|
||||
"next": undefined,
|
||||
"styles": "text-align:right;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
c
|
||||
</div>,
|
||||
|
@ -625,7 +673,15 @@ exports[`DatatableComponent it should render hide, reset, and sort actions on he
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--left"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "13brihr",
|
||||
"next": undefined,
|
||||
"styles": "text-align:left;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
a
|
||||
</div>,
|
||||
|
@ -666,7 +722,15 @@ exports[`DatatableComponent it should render hide, reset, and sort actions on he
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--left"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "13brihr",
|
||||
"next": undefined,
|
||||
"styles": "text-align:left;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
b
|
||||
</div>,
|
||||
|
@ -707,7 +771,15 @@ exports[`DatatableComponent it should render hide, reset, and sort actions on he
|
|||
},
|
||||
"cellActions": undefined,
|
||||
"display": <div
|
||||
className="lnsTableCell--right"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "s2uf1z",
|
||||
"next": undefined,
|
||||
"styles": "text-align:right;",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
c
|
||||
</div>,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { css } from '@emotion/react';
|
||||
import {
|
||||
EuiDataGridColumn,
|
||||
EuiDataGridColumnCellActionProps,
|
||||
|
@ -40,7 +41,9 @@ export const createGridColumns = (
|
|||
formatFactory: FormatFactory,
|
||||
onColumnResize: (eventData: { columnId: string; width: number | undefined }) => void,
|
||||
onColumnHide: ((eventData: { columnId: string }) => void) | undefined,
|
||||
alignments: Record<string, 'left' | 'right' | 'center'>
|
||||
alignments: Record<string, 'left' | 'right' | 'center'>,
|
||||
headerRowHeight: 'auto' | 'single' | 'custom',
|
||||
headerRowLines: number
|
||||
) => {
|
||||
const columnsReverseLookup = table.columns.reduce<
|
||||
Record<string, { name: string; index: number; meta?: DatatableColumnMeta }>
|
||||
|
@ -209,12 +212,24 @@ export const createGridColumns = (
|
|||
}
|
||||
}
|
||||
const currentAlignment = alignments && alignments[field];
|
||||
const alignmentClassName = `lnsTableCell--${currentAlignment}`;
|
||||
const hasMultipleRows = headerRowHeight === 'auto' || headerRowHeight === 'custom';
|
||||
|
||||
const columnStyle = css({
|
||||
...(headerRowHeight === 'custom' && {
|
||||
WebkitLineClamp: headerRowLines,
|
||||
}),
|
||||
...(hasMultipleRows && {
|
||||
whiteSpace: 'normal',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
}),
|
||||
textAlign: currentAlignment,
|
||||
});
|
||||
|
||||
const columnDefinition: EuiDataGridColumn = {
|
||||
id: field,
|
||||
cellActions,
|
||||
display: <div className={alignmentClassName}>{name}</div>,
|
||||
display: <div css={columnStyle}>{name}</div>,
|
||||
displayAsText: name,
|
||||
actions: {
|
||||
showHide: false,
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiButtonGroup, EuiFormRow, EuiRange, htmlIdGenerator, EuiSpacer } from '@elastic/eui';
|
||||
import type { DatatableVisualizationState } from '../visualization';
|
||||
|
||||
export interface RowHeightSettingsProps {
|
||||
rowHeight?: 'auto' | 'single' | 'custom';
|
||||
rowHeightLines?: number;
|
||||
maxRowHeight?: number;
|
||||
label: string;
|
||||
onChangeRowHeight: (newHeightMode: 'auto' | 'single' | 'custom' | undefined) => void;
|
||||
onChangeRowHeightLines: (newRowHeightLines: number) => void;
|
||||
'data-test-subj'?: string;
|
||||
}
|
||||
|
||||
const idPrefix = htmlIdGenerator()();
|
||||
|
||||
export function RowHeightSettings(props: RowHeightSettingsProps) {
|
||||
const {
|
||||
label,
|
||||
rowHeight,
|
||||
rowHeightLines,
|
||||
onChangeRowHeight,
|
||||
onChangeRowHeightLines,
|
||||
maxRowHeight,
|
||||
} = props;
|
||||
|
||||
const rowHeightModeOptions = [
|
||||
{
|
||||
id: `${idPrefix}single`,
|
||||
label: i18n.translate('xpack.lens.table.rowHeight.single', {
|
||||
defaultMessage: 'Single',
|
||||
}),
|
||||
'data-test-subj': 'lnsDatatable_rowHeight_single',
|
||||
},
|
||||
{
|
||||
id: `${idPrefix}auto`,
|
||||
label: i18n.translate('xpack.lens.table.rowHeight.auto', {
|
||||
defaultMessage: 'Auto fit',
|
||||
}),
|
||||
'data-test-subj': 'lnsDatatable_rowHeight_auto',
|
||||
},
|
||||
{
|
||||
id: `${idPrefix}custom`,
|
||||
label: i18n.translate('xpack.lens.table.rowHeight.custom', {
|
||||
defaultMessage: 'Custom',
|
||||
}),
|
||||
'data-test-subj': 'lnsDatatable_rowHeight_custom',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFormRow label={label} display="columnCompressed" data-test-subj={props['data-test-subj']}>
|
||||
<>
|
||||
<EuiButtonGroup
|
||||
isFullWidth
|
||||
legend={label}
|
||||
name="legendLocation"
|
||||
buttonSize="compressed"
|
||||
options={rowHeightModeOptions}
|
||||
idSelected={`${idPrefix}${rowHeight ?? 'single'}`}
|
||||
onChange={(optionId) => {
|
||||
const newMode = optionId.replace(
|
||||
idPrefix,
|
||||
''
|
||||
) as DatatableVisualizationState['rowHeight'];
|
||||
onChangeRowHeight(newMode);
|
||||
}}
|
||||
/>
|
||||
{rowHeight === 'custom' ? (
|
||||
<>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiRange
|
||||
compressed
|
||||
fullWidth
|
||||
showInput
|
||||
min={1}
|
||||
max={maxRowHeight ?? 20}
|
||||
step={1}
|
||||
value={rowHeightLines ?? 2}
|
||||
onChange={(e) => {
|
||||
const lineCount = Number(e.currentTarget.value);
|
||||
onChangeRowHeightLines(lineCount);
|
||||
}}
|
||||
data-test-subj="lens-table-row-height-lineCountNumber"
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -255,6 +255,9 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
|
|||
);
|
||||
}, [firstTable, isNumericMap, columnConfig]);
|
||||
|
||||
const headerRowHeight = props.args.headerRowHeight ?? 'single';
|
||||
const headerRowLines = props.args.headerRowHeightLines ?? 1;
|
||||
|
||||
const columns: EuiDataGridColumn[] = useMemo(
|
||||
() =>
|
||||
createGridColumns(
|
||||
|
@ -268,7 +271,9 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
|
|||
formatFactory,
|
||||
onColumnResize,
|
||||
onColumnHide,
|
||||
alignments
|
||||
alignments,
|
||||
headerRowHeight,
|
||||
headerRowLines
|
||||
),
|
||||
[
|
||||
bucketColumns,
|
||||
|
@ -282,6 +287,8 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
|
|||
onColumnResize,
|
||||
onColumnHide,
|
||||
alignments,
|
||||
headerRowHeight,
|
||||
headerRowLines,
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
@ -39,13 +39,21 @@ class Harness {
|
|||
}
|
||||
|
||||
public get rowHeight() {
|
||||
return this.wrapper.find(EuiButtonGroup);
|
||||
return this.wrapper.find('[data-test-subj="lnsRowHeightSettings"]').find(EuiButtonGroup);
|
||||
}
|
||||
|
||||
public get headerRowHeight() {
|
||||
return this.wrapper.find('[data-test-subj="lnsHeaderHeightSettings"]').find(EuiButtonGroup);
|
||||
}
|
||||
|
||||
changeRowHeight(newMode: 'single' | 'auto' | 'custom') {
|
||||
this.rowHeight.prop('onChange')!(newMode);
|
||||
}
|
||||
|
||||
changeHeaderRowHeight(newMode: 'single' | 'auto' | 'custom') {
|
||||
this.headerRowHeight.prop('onChange')!(newMode);
|
||||
}
|
||||
|
||||
public get rowHeightLines() {
|
||||
return this.wrapper.find(EuiRange);
|
||||
}
|
||||
|
@ -83,6 +91,7 @@ describe('datatable toolbar', () => {
|
|||
frame: {} as FramePublicAPI,
|
||||
state: {
|
||||
rowHeight: 'single',
|
||||
headerRowHeight: 'single',
|
||||
} as DatatableVisualizationState,
|
||||
};
|
||||
|
||||
|
@ -93,6 +102,7 @@ describe('datatable toolbar', () => {
|
|||
harness.togglePopover();
|
||||
|
||||
expect(harness.rowHeight.prop('idSelected')).toBe('single');
|
||||
expect(harness.headerRowHeight.prop('idSelected')).toBe('single');
|
||||
expect(harness.paginationSwitch.prop('checked')).toBe(false);
|
||||
|
||||
harness.wrapper.setProps({
|
||||
|
@ -113,16 +123,17 @@ describe('datatable toolbar', () => {
|
|||
|
||||
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
|
||||
expect(defaultProps.setState).toHaveBeenNthCalledWith(1, {
|
||||
headerRowHeight: 'single',
|
||||
rowHeight: 'auto',
|
||||
rowHeightLines: undefined,
|
||||
});
|
||||
|
||||
harness.wrapper.setProps({ state: { rowHeight: 'auto' } }); // update state manually
|
||||
harness.changeRowHeight('single'); // turn it off
|
||||
|
||||
expect(defaultProps.setState).toHaveBeenCalledTimes(2);
|
||||
expect(defaultProps.setState).toHaveBeenNthCalledWith(2, {
|
||||
rowHeight: 'single',
|
||||
headerRowHeight: 'single',
|
||||
rowHeightLines: 1,
|
||||
});
|
||||
});
|
||||
|
@ -135,12 +146,22 @@ describe('datatable toolbar', () => {
|
|||
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
|
||||
expect(defaultProps.setState).toHaveBeenNthCalledWith(1, {
|
||||
rowHeight: 'custom',
|
||||
headerRowHeight: 'single',
|
||||
rowHeightLines: 2,
|
||||
});
|
||||
});
|
||||
|
||||
harness.wrapper.setProps({ state: { rowHeight: 'custom' } }); // update state manually
|
||||
it('should change header height to "Custom" mode', async () => {
|
||||
harness.togglePopover();
|
||||
|
||||
expect(harness.rowHeightLines.prop('value')).toBe(2);
|
||||
harness.changeHeaderRowHeight('custom');
|
||||
|
||||
expect(defaultProps.setState).toHaveBeenCalledTimes(1);
|
||||
expect(defaultProps.setState).toHaveBeenNthCalledWith(1, {
|
||||
rowHeight: 'single',
|
||||
headerRowHeight: 'custom',
|
||||
headerRowHeightLines: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should toggle table pagination', async () => {
|
||||
|
@ -152,17 +173,19 @@ describe('datatable toolbar', () => {
|
|||
expect(defaultProps.setState).toHaveBeenNthCalledWith(1, {
|
||||
paging: defaultPagingState,
|
||||
rowHeight: 'single',
|
||||
headerRowHeight: 'single',
|
||||
});
|
||||
|
||||
// update state manually
|
||||
harness.wrapper.setProps({
|
||||
state: { rowHeight: 'single', paging: defaultPagingState },
|
||||
state: { rowHeight: 'single', headerRowHeight: 'single', paging: defaultPagingState },
|
||||
});
|
||||
harness.togglePagination(); // turn it off. this should disable pagination but preserve the default page size
|
||||
|
||||
expect(defaultProps.setState).toHaveBeenCalledTimes(2);
|
||||
expect(defaultProps.setState).toHaveBeenNthCalledWith(2, {
|
||||
rowHeight: 'single',
|
||||
headerRowHeight: 'single',
|
||||
paging: { ...defaultPagingState, enabled: false },
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,46 +7,36 @@
|
|||
|
||||
import React, { useCallback } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiButtonGroup,
|
||||
EuiFlexGroup,
|
||||
EuiFormRow,
|
||||
EuiRange,
|
||||
EuiSwitch,
|
||||
EuiToolTip,
|
||||
htmlIdGenerator,
|
||||
} from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFormRow, EuiSwitch, EuiToolTip } from '@elastic/eui';
|
||||
import { ToolbarPopover } from '../../shared_components';
|
||||
import type { VisualizationToolbarProps } from '../../types';
|
||||
import type { DatatableVisualizationState } from '../visualization';
|
||||
import { RowHeightSettings } from './row_height_settings';
|
||||
import { DEFAULT_PAGE_SIZE } from './table_basic';
|
||||
|
||||
const idPrefix = htmlIdGenerator()();
|
||||
|
||||
export function DataTableToolbar(props: VisualizationToolbarProps<DatatableVisualizationState>) {
|
||||
const { state, setState } = props;
|
||||
|
||||
const onChangeRowHeight = useCallback(
|
||||
(newHeightMode) => {
|
||||
const onChangeHeight = useCallback(
|
||||
(newHeightMode, heightProperty, heightLinesProperty) => {
|
||||
const rowHeightLines =
|
||||
newHeightMode === 'single' ? 1 : newHeightMode !== 'auto' ? 2 : undefined;
|
||||
setState({
|
||||
...state,
|
||||
rowHeight: newHeightMode,
|
||||
rowHeightLines,
|
||||
[heightProperty]: newHeightMode,
|
||||
[heightLinesProperty]: rowHeightLines,
|
||||
});
|
||||
},
|
||||
[setState, state]
|
||||
);
|
||||
|
||||
const onChangeRowHeightLines = useCallback(
|
||||
(newRowHeightLines) => {
|
||||
const onChangeHeightLines = useCallback(
|
||||
(newRowHeightLines, heightLinesProperty) => {
|
||||
setState({
|
||||
...state,
|
||||
rowHeightLines: newRowHeightLines,
|
||||
[heightLinesProperty]: newRowHeightLines,
|
||||
});
|
||||
},
|
||||
[state, setState]
|
||||
[setState, state]
|
||||
);
|
||||
|
||||
const onTogglePagination = useCallback(() => {
|
||||
|
@ -58,30 +48,6 @@ export function DataTableToolbar(props: VisualizationToolbarProps<DatatableVisua
|
|||
});
|
||||
}, [setState, state]);
|
||||
|
||||
const rowHeightModeOptions = [
|
||||
{
|
||||
id: `${idPrefix}single`,
|
||||
label: i18n.translate('xpack.lens.table.rowHeight.single', {
|
||||
defaultMessage: 'Single',
|
||||
}),
|
||||
'data-test-subj': 'lnsDatatable_rowHeight_single',
|
||||
},
|
||||
{
|
||||
id: `${idPrefix}auto`,
|
||||
label: i18n.translate('xpack.lens.table.rowHeight.auto', {
|
||||
defaultMessage: 'Auto fit',
|
||||
}),
|
||||
'data-test-subj': 'lnsDatatable_rowHeight_auto',
|
||||
},
|
||||
{
|
||||
id: `${idPrefix}custom`,
|
||||
label: i18n.translate('xpack.lens.table.rowHeight.custom', {
|
||||
defaultMessage: 'Custom',
|
||||
}),
|
||||
'data-test-subj': 'lnsDatatable_rowHeight_custom',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="none" justifyContent="spaceBetween" responsive={false}>
|
||||
<ToolbarPopover
|
||||
|
@ -92,54 +58,33 @@ export function DataTableToolbar(props: VisualizationToolbarProps<DatatableVisua
|
|||
groupPosition="none"
|
||||
buttonDataTestSubj="lnsVisualOptionsButton"
|
||||
>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.lens.table.visualOptionsFitRowToContentLabel', {
|
||||
defaultMessage: 'Row height',
|
||||
<RowHeightSettings
|
||||
rowHeight={state.headerRowHeight}
|
||||
rowHeightLines={state.headerRowHeightLines}
|
||||
label={i18n.translate('xpack.lens.table.visualOptionsHeaderRowHeightLabel', {
|
||||
defaultMessage: 'Header row height',
|
||||
})}
|
||||
display="columnCompressed"
|
||||
>
|
||||
<EuiButtonGroup
|
||||
isFullWidth
|
||||
legend={i18n.translate('xpack.lens.table.visualOptionsRowHeight', {
|
||||
defaultMessage: 'Row height',
|
||||
})}
|
||||
data-test-subj="lens-table-row-height"
|
||||
name="legendLocation"
|
||||
buttonSize="compressed"
|
||||
options={rowHeightModeOptions}
|
||||
idSelected={`${idPrefix}${state.rowHeight ?? 'single'}`}
|
||||
onChange={(optionId) => {
|
||||
const newMode = optionId.replace(
|
||||
idPrefix,
|
||||
''
|
||||
) as DatatableVisualizationState['rowHeight'];
|
||||
onChangeRowHeight(newMode);
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{state.rowHeight === 'custom' ? (
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.lens.table.visualOptionsCustomRowHeight', {
|
||||
defaultMessage: 'Lines per row',
|
||||
})}
|
||||
display="columnCompressed"
|
||||
>
|
||||
<EuiRange
|
||||
compressed
|
||||
fullWidth
|
||||
showInput
|
||||
min={1}
|
||||
max={20}
|
||||
step={1}
|
||||
value={state.rowHeightLines ?? 2}
|
||||
onChange={(e) => {
|
||||
const lineCount = Number(e.currentTarget.value);
|
||||
onChangeRowHeightLines(lineCount);
|
||||
}}
|
||||
data-test-subj="lens-table-row-height-lineCountNumber"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
) : null}
|
||||
onChangeRowHeight={(mode) =>
|
||||
onChangeHeight(mode, 'headerRowHeight', 'headerRowHeightLines')
|
||||
}
|
||||
onChangeRowHeightLines={(lines) => {
|
||||
onChangeHeightLines(lines, 'headerRowHeightLines');
|
||||
}}
|
||||
data-test-subj="lnsHeaderHeightSettings"
|
||||
maxRowHeight={5}
|
||||
/>
|
||||
<RowHeightSettings
|
||||
rowHeight={state.rowHeight}
|
||||
rowHeightLines={state.rowHeightLines}
|
||||
label={i18n.translate('xpack.lens.table.visualOptionsFitRowToContentLabel', {
|
||||
defaultMessage: 'Cell row height',
|
||||
})}
|
||||
onChangeRowHeight={(mode) => onChangeHeight(mode, 'rowHeight', 'rowHeightLines')}
|
||||
onChangeRowHeightLines={(lines) => {
|
||||
onChangeHeightLines(lines, 'rowHeightLines');
|
||||
}}
|
||||
data-test-subj="lnsRowHeightSettings"
|
||||
/>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.lens.table.visualOptionsPaginateTable', {
|
||||
defaultMessage: 'Paginate table',
|
||||
|
|
|
@ -653,6 +653,38 @@ describe('Datatable Visualization', () => {
|
|||
}).rowHeightLines
|
||||
).toEqual([2]);
|
||||
});
|
||||
|
||||
it('sets headerRowHeight && headerRowHeightLines correctly', () => {
|
||||
expect(
|
||||
getDatatableExpressionArgs({ ...defaultExpressionTableState }).headerRowHeightLines
|
||||
).toEqual([1]);
|
||||
|
||||
// should fallback to single in case it's not set
|
||||
expect(
|
||||
getDatatableExpressionArgs({ ...defaultExpressionTableState }).headerRowHeight
|
||||
).toEqual(['single']);
|
||||
|
||||
expect(
|
||||
getDatatableExpressionArgs({ ...defaultExpressionTableState, headerRowHeight: 'single' })
|
||||
.headerRowHeightLines
|
||||
).toEqual([1]);
|
||||
|
||||
expect(
|
||||
getDatatableExpressionArgs({
|
||||
...defaultExpressionTableState,
|
||||
headerRowHeight: 'custom',
|
||||
headerRowHeightLines: 5,
|
||||
}).headerRowHeightLines
|
||||
).toEqual([5]);
|
||||
|
||||
// should fallback to 2 for custom in case it's not set
|
||||
expect(
|
||||
getDatatableExpressionArgs({
|
||||
...defaultExpressionTableState,
|
||||
headerRowHeight: 'custom',
|
||||
}).headerRowHeightLines
|
||||
).toEqual([2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getErrorMessages', () => {
|
||||
|
|
|
@ -33,7 +33,9 @@ export interface DatatableVisualizationState {
|
|||
layerType: LayerType;
|
||||
sorting?: SortingState;
|
||||
rowHeight?: 'auto' | 'single' | 'custom';
|
||||
headerRowHeight?: 'auto' | 'single' | 'custom';
|
||||
rowHeightLines?: number;
|
||||
headerRowHeightLines?: number;
|
||||
paging?: PagingState;
|
||||
}
|
||||
|
||||
|
@ -402,9 +404,15 @@ export const getDatatableVisualization = ({
|
|||
sortingColumnId: [state.sorting?.columnId || ''],
|
||||
sortingDirection: [state.sorting?.direction || 'none'],
|
||||
fitRowToContent: [state.rowHeight === 'auto'],
|
||||
headerRowHeight: [state.headerRowHeight ?? 'single'],
|
||||
rowHeightLines: [
|
||||
!state.rowHeight || state.rowHeight === 'single' ? 1 : state.rowHeightLines ?? 2,
|
||||
],
|
||||
headerRowHeightLines: [
|
||||
!state.headerRowHeight || state.headerRowHeight === 'single'
|
||||
? 1
|
||||
: state.headerRowHeightLines ?? 2,
|
||||
],
|
||||
pageSize: state.paging?.enabled ? [state.paging.size] : [],
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue