Skip to content

Commit ae84bb2

Browse files
authored
[Lens] Improve unclear UI for bucket aggregation grouping order (#77331)
1 parent 018c2bd commit ae84bb2

File tree

6 files changed

+57
-129
lines changed

6 files changed

+57
-129
lines changed

x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,8 @@ describe('BucketNestingEditor', () => {
5353
setColumns={jest.fn()}
5454
/>
5555
);
56-
const control1 = component.find('[data-test-subj="indexPattern-nesting-topLevel"]').first();
57-
const control2 = component.find('[data-test-subj="indexPattern-nesting-bottomLevel"]').first();
58-
59-
expect(control1.prop('checked')).toBeTruthy();
60-
expect(control2.prop('checked')).toBeFalsy();
56+
const nestingSwitch = component.find('[data-test-subj="indexPattern-nesting-switch"]').first();
57+
expect(nestingSwitch.prop('checked')).toBeTruthy();
6158
});
6259

6360
it('should display the bottom level grouping when appropriate', () => {
@@ -77,12 +74,8 @@ describe('BucketNestingEditor', () => {
7774
setColumns={jest.fn()}
7875
/>
7976
);
80-
81-
const control1 = component.find('[data-test-subj="indexPattern-nesting-topLevel"]').first();
82-
const control2 = component.find('[data-test-subj="indexPattern-nesting-bottomLevel"]').first();
83-
84-
expect(control1.prop('checked')).toBeFalsy();
85-
expect(control2.prop('checked')).toBeTruthy();
77+
const nestingSwitch = component.find('[data-test-subj="indexPattern-nesting-switch"]').first();
78+
expect(nestingSwitch.prop('checked')).toBeFalsy();
8679
});
8780

8881
it('should reorder the columns when toggled', () => {
@@ -103,9 +96,9 @@ describe('BucketNestingEditor', () => {
10396
setColumns={setColumns}
10497
/>
10598
);
106-
const control1 = component.find('[data-test-subj="indexPattern-nesting-topLevel"]').first();
10799

108-
(control1.prop('onChange') as () => {})();
100+
const nestingSwitch = component.find('[data-test-subj="indexPattern-nesting-switch"]').first();
101+
(nestingSwitch.prop('onChange') as () => {})();
109102

110103
expect(setColumns).toHaveBeenCalledTimes(1);
111104
expect(setColumns).toHaveBeenCalledWith(['a', 'b', 'c']);
@@ -122,9 +115,10 @@ describe('BucketNestingEditor', () => {
122115
},
123116
});
124117

125-
const control2 = component.find('[data-test-subj="indexPattern-nesting-bottomLevel"]').first();
126-
127-
(control2.prop('onChange') as () => {})();
118+
(component
119+
.find('[data-test-subj="indexPattern-nesting-switch"]')
120+
.first()
121+
.prop('onChange') as () => {})();
128122

129123
expect(setColumns).toHaveBeenCalledTimes(2);
130124
expect(setColumns).toHaveBeenLastCalledWith(['b', 'a', 'c']);

x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx

Lines changed: 44 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@
66

77
import React from 'react';
88
import { i18n } from '@kbn/i18n';
9-
import { EuiFormRow, EuiHorizontalRule, EuiRadio, EuiSelect, htmlIdGenerator } from '@elastic/eui';
9+
import { EuiFormRow, EuiSwitch, EuiSelect } from '@elastic/eui';
1010
import { IndexPatternLayer, IndexPatternField } from '../types';
1111
import { hasField } from '../utils';
1212
import { IndexPatternColumn } from '../operations';
1313

14-
const generator = htmlIdGenerator('lens-nesting');
15-
1614
function nestColumn(columnOrder: string[], outer: string, inner: string) {
1715
const result = columnOrder.filter((c) => c !== inner);
1816
const outerPosition = result.indexOf(outer);
@@ -52,114 +50,57 @@ export function BucketNestingEditor({
5250
return null;
5351
}
5452

55-
const fieldName = getFieldName(fieldMap, column);
56-
5753
const prevColumn = layer.columnOrder[layer.columnOrder.indexOf(columnId) - 1];
5854

5955
if (aggColumns.length === 1) {
6056
const [target] = aggColumns;
61-
62-
function toggleNesting() {
63-
if (prevColumn) {
64-
setColumns(nestColumn(layer.columnOrder, columnId, target.value));
65-
} else {
66-
setColumns(nestColumn(layer.columnOrder, target.value, columnId));
67-
}
68-
}
69-
70-
// todo: move the copy to operations
71-
const topLevelCopy: Record<string, string> = {
72-
terms: i18n.translate('xpack.lens.indexPattern.groupingOverallTerms', {
73-
defaultMessage: 'Overall top {field}',
74-
values: { field: fieldName },
75-
}),
76-
filters: i18n.translate('xpack.lens.indexPattern.groupingOverallFilters', {
77-
defaultMessage: 'Top values for each filter',
78-
}),
79-
date_histogram: i18n.translate('xpack.lens.indexPattern.groupingOverallDateHistogram', {
80-
defaultMessage: 'Top values for each {field}',
81-
values: { field: fieldName },
82-
}),
83-
range: i18n.translate('xpack.lens.indexPattern.groupingOverallRanges', {
84-
defaultMessage: 'Top values for each {field}',
85-
values: { field: fieldName },
86-
}),
87-
};
88-
89-
const bottomLevelCopy: Record<string, string> = {
90-
terms: i18n.translate('xpack.lens.indexPattern.groupingSecondTerms', {
91-
defaultMessage: 'Top values for each {target}',
92-
values: { target: target.fieldName },
93-
}),
94-
filters: i18n.translate('xpack.lens.indexPattern.groupingSecondFilters', {
95-
defaultMessage: 'Overall top {target}',
96-
values: { target: target.fieldName },
97-
}),
98-
date_histogram: i18n.translate('xpack.lens.indexPattern.groupingSecondDateHistogram', {
99-
defaultMessage: 'Overall top {target}',
100-
values: { target: target.fieldName },
101-
}),
102-
range: i18n.translate('xpack.lens.indexPattern.groupingSecondRanges', {
103-
defaultMessage: 'Overall top {target}',
104-
values: { target: target.fieldName },
105-
}),
106-
};
107-
57+
const useAsTopLevelAggCopy = i18n.translate('xpack.lens.indexPattern.useAsTopLevelAgg', {
58+
defaultMessage: 'Group by this field first',
59+
});
10860
return (
109-
<>
110-
<EuiHorizontalRule margin="m" />
111-
<EuiFormRow
112-
label={i18n.translate('xpack.lens.indexPattern.groupingControlLabel', {
113-
defaultMessage: 'Grouping',
114-
})}
115-
labelType="legend"
116-
>
117-
<>
118-
<EuiRadio
119-
id={generator('topLevel')}
120-
data-test-subj="indexPattern-nesting-topLevel"
121-
label={topLevelCopy[column.operationType]}
122-
checked={!prevColumn}
123-
onChange={toggleNesting}
124-
/>
125-
<EuiRadio
126-
id={generator('bottomLevel')}
127-
data-test-subj="indexPattern-nesting-bottomLevel"
128-
label={bottomLevelCopy[column.operationType]}
129-
checked={!!prevColumn}
130-
onChange={toggleNesting}
131-
/>
132-
</>
133-
</EuiFormRow>
134-
</>
61+
<EuiFormRow label={useAsTopLevelAggCopy} display="columnCompressedSwitch">
62+
<EuiSwitch
63+
compressed
64+
label={useAsTopLevelAggCopy}
65+
showLabel={false}
66+
data-test-subj="indexPattern-nesting-switch"
67+
name="nestingSwitch"
68+
checked={!prevColumn}
69+
onChange={() => {
70+
if (prevColumn) {
71+
setColumns(nestColumn(layer.columnOrder, columnId, target.value));
72+
} else {
73+
setColumns(nestColumn(layer.columnOrder, target.value, columnId));
74+
}
75+
}}
76+
/>
77+
</EuiFormRow>
13578
);
13679
}
13780

13881
return (
139-
<>
140-
<EuiHorizontalRule margin="m" />
141-
<EuiFormRow
142-
label={i18n.translate('xpack.lens.indexPattern.groupByDropdown', {
143-
defaultMessage: 'Group by',
144-
})}
145-
display="rowCompressed"
146-
>
147-
<EuiSelect
148-
compressed
149-
data-test-subj="indexPattern-nesting-select"
150-
options={[
151-
{
152-
value: '',
153-
text: i18n.translate('xpack.lens.xyChart.nestUnderRoot', {
154-
defaultMessage: 'Entire data set',
155-
}),
156-
},
157-
...aggColumns.map(({ value, text }) => ({ value, text })),
158-
]}
159-
value={prevColumn}
160-
onChange={(e) => setColumns(nestColumn(layer.columnOrder, e.target.value, columnId))}
161-
/>
162-
</EuiFormRow>
163-
</>
82+
<EuiFormRow
83+
label={i18n.translate('xpack.lens.indexPattern.groupByDropdown', {
84+
defaultMessage: 'Group by',
85+
})}
86+
display="columnCompressed"
87+
fullWidth
88+
>
89+
<EuiSelect
90+
compressed
91+
data-test-subj="indexPattern-nesting-select"
92+
options={[
93+
{
94+
value: '',
95+
text: i18n.translate('xpack.lens.xyChart.nestUnderRoot', {
96+
defaultMessage: 'Entire data set',
97+
}),
98+
},
99+
...aggColumns.map(({ value, text }) => ({ value, text })),
100+
]}
101+
value={prevColumn}
102+
onChange={(e) => setColumns(nestColumn(layer.columnOrder, e.target.value, columnId))}
103+
/>
104+
</EuiFormRow>
164105
);
165106
}

x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import {
1414
EuiFieldText,
1515
EuiSpacer,
1616
EuiListGroupItemProps,
17+
EuiFormLabel,
1718
} from '@elastic/eui';
18-
import { EuiFormLabel } from '@elastic/eui';
19-
import { IndexPatternColumn, OperationType } from '../indexpattern';
2019
import { IndexPatternDimensionEditorProps, OperationSupportMatrix } from './dimension_panel';
20+
import { IndexPatternColumn, OperationType } from '../indexpattern';
2121
import {
2222
operationDefinitionMap,
2323
getOperationDisplay,
@@ -411,7 +411,7 @@ export function DimensionEditor(props: DimensionEditorProps) {
411411
/>
412412
)}
413413

414-
{!hideGrouping && (
414+
{!incompatibleSelectedOperationType && !hideGrouping && (
415415
<BucketNestingEditor
416416
fieldMap={fieldMap}
417417
layer={state.layers[props.layerId]}

x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ export const filtersOperation: OperationDefinition<FiltersIndexPatternColumn, 'n
7272
type: 'filters',
7373
displayName: filtersLabel,
7474
priority: 3, // Higher than any metric
75-
7675
input: 'none',
7776
isTransferable: () => true,
7877

x-pack/plugins/translations/translations/ja-JP.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9513,9 +9513,6 @@
95139513
"xpack.lens.indexPattern.fieldTimeDistributionLabel": "時間分布",
95149514
"xpack.lens.indexPattern.fieldTopValuesLabel": "トップの値",
95159515
"xpack.lens.indexPattern.groupByDropdown": "グループ分けの条件",
9516-
"xpack.lens.indexPattern.groupingControlLabel": "グループ分け",
9517-
"xpack.lens.indexPattern.groupingOverallTerms": "全体のトップ {field}",
9518-
"xpack.lens.indexPattern.groupingSecondTerms": "各 {target} のトップの値",
95199516
"xpack.lens.indexPattern.indexPatternLoadError": "インデックスパターンの読み込み中にエラーが発生",
95209517
"xpack.lens.indexPattern.invalidInterval": "無効な間隔値",
95219518
"xpack.lens.indexPattern.invalidOperationLabel": "この関数を使用するには、別のフィールドを選択してください。",

x-pack/plugins/translations/translations/zh-CN.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9519,9 +9519,6 @@
95199519
"xpack.lens.indexPattern.fieldTimeDistributionLabel": "时间分布",
95209520
"xpack.lens.indexPattern.fieldTopValuesLabel": "排名最前值",
95219521
"xpack.lens.indexPattern.groupByDropdown": "分组依据",
9522-
"xpack.lens.indexPattern.groupingControlLabel": "分组",
9523-
"xpack.lens.indexPattern.groupingOverallTerms": "总体排名最前 {field}",
9524-
"xpack.lens.indexPattern.groupingSecondTerms": "每个 {target} 的排名最前值",
95259522
"xpack.lens.indexPattern.indexPatternLoadError": "加载索引模式时出错",
95269523
"xpack.lens.indexPattern.invalidInterval": "时间间隔值无效",
95279524
"xpack.lens.indexPattern.invalidOperationLabel": "要使用此函数,请选择不同的字段。",

0 commit comments

Comments
 (0)