Skip to content

Commit 5847993

Browse files
committed
feat(explore): display metrics and columns in alphabetical order
1 parent 93fa39a commit 5847993

File tree

5 files changed

+234
-26
lines changed

5 files changed

+234
-26
lines changed

superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanel.test.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import DatasourcePanel, {
3232
import {
3333
columns,
3434
metrics,
35+
columnsUnsorted,
36+
metricsUnsorted,
3537
} from 'src/explore/components/DatasourcePanel/fixtures';
3638
import { DatasourceType } from '@superset-ui/core';
3739
import DatasourceControl from 'src/explore/components/controls/DatasourceControl';
@@ -101,6 +103,12 @@ const datasourceWithFolders: IDatasource = {
101103
],
102104
};
103105

106+
const datasourceUnsorted: IDatasource = {
107+
...datasource,
108+
columns: columnsUnsorted,
109+
metrics: metricsUnsorted,
110+
};
111+
104112
const mockUser = {
105113
createdOn: '2021-04-27T18:12:38.952304',
106114
email: 'admin',
@@ -492,3 +500,43 @@ test('Default Metrics and Columns folders dont render when all metrics and colum
492500
expect(screen.getAllByTestId('DatasourcePanelDragOption').length).toEqual(5);
493501
expect(screen.getAllByTestId('datasource-panel-divider').length).toEqual(1);
494502
});
503+
504+
test('Displays metrics and columns in alphabetical order', () => {
505+
const panelProps = {
506+
...props,
507+
datasource: datasourceUnsorted,
508+
controls: {
509+
...props.controls,
510+
datasource: {
511+
...props.controls.datasource,
512+
datasource: datasourceUnsorted,
513+
},
514+
},
515+
};
516+
517+
render(
518+
<ExploreContainer>
519+
<DatasourcePanel {...panelProps} />
520+
<DndMetricSelect {...metricProps} />
521+
</ExploreContainer>,
522+
{
523+
useRedux: true,
524+
useDnd: true,
525+
},
526+
);
527+
528+
const items = screen.getAllByTestId('DatasourcePanelDragOption');
529+
expect(items.map(it => it.textContent)).toEqual([
530+
'ee (certified)',
531+
'aa',
532+
'bb',
533+
'cc (has empty verbose_name)',
534+
'dd',
535+
'yyy (certified)',
536+
'BBB (has empty verbose_name)',
537+
'Cbb',
538+
'ccc',
539+
'Cdd',
540+
'Www',
541+
]);
542+
});

superset-frontend/src/explore/components/DatasourcePanel/fixtures.tsx

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,168 @@ const metricsFiltered = {
9797
],
9898
};
9999

100+
export const columnsUnsorted = [
101+
{
102+
column_name: 'ccc',
103+
description: null,
104+
expression: 'null',
105+
filterable: true,
106+
groupby: true,
107+
id: 100,
108+
uuid: '100',
109+
is_dttm: false,
110+
python_date_format: null,
111+
type: 'VARCHAR',
112+
type_generic: GenericDataType.String,
113+
verbose_name: 'ccc',
114+
},
115+
{
116+
column_name: 'aaa',
117+
description: null,
118+
expression: null,
119+
filterable: true,
120+
groupby: true,
121+
id: 101,
122+
uuid: '101',
123+
is_dttm: false,
124+
python_date_format: null,
125+
type: 'DOUBLE',
126+
type_generic: GenericDataType.Numeric,
127+
verbose_name: 'Www',
128+
},
129+
{
130+
column_name: 'Cbb',
131+
description: null,
132+
expression: null,
133+
filterable: true,
134+
groupby: true,
135+
id: 102,
136+
uuid: '102',
137+
is_dttm: false,
138+
python_date_format: null,
139+
type: 'INT',
140+
type_generic: GenericDataType.Numeric,
141+
verbose_name: null,
142+
},
143+
{
144+
column_name: 'BBB (has empty verbose_name)',
145+
description: null,
146+
expression: null,
147+
filterable: true,
148+
groupby: true,
149+
id: 102,
150+
uuid: '102',
151+
is_dttm: false,
152+
python_date_format: null,
153+
type: 'INT',
154+
type_generic: GenericDataType.Numeric,
155+
verbose_name: '',
156+
},
157+
{
158+
column_name: 'yyy',
159+
is_certified: 1,
160+
description: null,
161+
expression: null,
162+
filterable: true,
163+
groupby: true,
164+
id: 103,
165+
uuid: '103',
166+
is_dttm: false,
167+
python_date_format: null,
168+
type: 'INT',
169+
type_generic: GenericDataType.Numeric,
170+
verbose_name: 'yyy (certified)',
171+
},
172+
{
173+
column_name: 'Cdd',
174+
description: null,
175+
expression: null,
176+
filterable: true,
177+
groupby: true,
178+
id: 104,
179+
uuid: '104',
180+
is_dttm: false,
181+
python_date_format: null,
182+
type: 'INT',
183+
type_generic: GenericDataType.Numeric,
184+
verbose_name: null,
185+
},
186+
];
187+
188+
const metricsFilteredUnsorted = {
189+
certified: [
190+
{
191+
certification_details: null,
192+
certified_by: 'user',
193+
d3format: null,
194+
description: null,
195+
expression: '',
196+
id: 59,
197+
uuid: '59',
198+
is_certified: true,
199+
metric_name: 'ee (certified)',
200+
verbose_name: null,
201+
warning_text: null,
202+
},
203+
],
204+
uncertified: [
205+
{
206+
certification_details: null,
207+
d3format: null,
208+
description: null,
209+
expression: '',
210+
id: 56,
211+
uuid: '56',
212+
is_certified: false,
213+
metric_name: 'dd',
214+
verbose_name: null,
215+
warning_text: null,
216+
},
217+
{
218+
certification_details: null,
219+
d3format: null,
220+
description: null,
221+
expression: '',
222+
id: 57,
223+
uuid: '57',
224+
is_certified: false,
225+
metric_name: 'ee',
226+
verbose_name: 'aa',
227+
warning_text: null,
228+
},
229+
{
230+
certification_details: null,
231+
d3format: null,
232+
description: null,
233+
expression: '',
234+
id: 57,
235+
uuid: '57',
236+
is_certified: false,
237+
metric_name: 'cc (has empty verbose_name)',
238+
verbose_name: '',
239+
warning_text: null,
240+
},
241+
{
242+
certification_details: null,
243+
d3format: null,
244+
description: null,
245+
expression: '',
246+
id: 58,
247+
uuid: '58',
248+
is_certified: false,
249+
metric_name: 'bb',
250+
verbose_name: null,
251+
warning_text: null,
252+
},
253+
],
254+
};
255+
100256
export const metrics = [
101257
...metricsFiltered.certified,
102258
...metricsFiltered.uncertified,
103259
];
260+
261+
export const metricsUnsorted = [
262+
...metricsFilteredUnsorted.certified,
263+
...metricsFilteredUnsorted.uncertified,
264+
];

superset-frontend/src/explore/components/DatasourcePanel/index.tsx

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,6 @@ const StyledInfoboxWrapper = styled.div`
122122

123123
const BORDER_WIDTH = 2;
124124

125-
const sortColumns = (slice: DatasourcePanelColumn[]) =>
126-
[...slice]
127-
.sort((col1, col2) => {
128-
if (col1?.is_dttm && !col2?.is_dttm) {
129-
return -1;
130-
}
131-
if (col2?.is_dttm && !col1?.is_dttm) {
132-
return 1;
133-
}
134-
return 0;
135-
})
136-
.sort((a, b) => (b?.is_certified ?? 0) - (a?.is_certified ?? 0));
137-
138125
export default function DataSourcePanel({
139126
datasource,
140127
formData,
@@ -222,28 +209,19 @@ export default function DataSourcePanel({
222209
},
223210
],
224211
keepDiacritics: true,
225-
baseSort: (a, b) =>
226-
Number(b?.item?.is_certified ?? 0) -
227-
Number(a?.item?.is_certified ?? 0) ||
228-
String(a?.rankedValue ?? '').localeCompare(b?.rankedValue ?? ''),
229212
});
230213
}, [allowedMetrics, searchKeyword]);
231214

232-
const sortedColumns = useMemo(
233-
() => sortColumns(filteredColumns),
234-
[filteredColumns],
235-
);
236-
237215
const folders = useMemo(
238216
() =>
239217
transformDatasourceWithFolders(
240218
filteredMetrics,
241-
sortedColumns,
219+
filteredColumns,
242220
_folders,
243221
allowedMetrics,
244222
allowedColumns,
245223
),
246-
[_folders, filteredMetrics, sortedColumns],
224+
[_folders, filteredMetrics, filteredColumns],
247225
);
248226

249227
const showInfoboxCheck = () => {

superset-frontend/src/explore/components/DatasourcePanel/transformDatasourceFolders.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ import {
2525
MetricItem,
2626
} from './types';
2727

28+
const sortMetrics = (arr: MetricItem[]) =>
29+
arr.sort((a, b) => {
30+
const certCmp = Number(b?.is_certified ?? 0) - Number(a?.is_certified ?? 0);
31+
if (certCmp) return certCmp;
32+
33+
const aName = (a.verbose_name || a.metric_name) ?? '';
34+
const bName = (b.verbose_name || b.metric_name) ?? '';
35+
return aName.localeCompare(bName, undefined, { sensitivity: 'base' });
36+
});
37+
38+
const sortColumns = (arr: ColumnItem[]) =>
39+
arr.sort((a, b) => {
40+
const certCmp = Number(b?.is_certified ?? 0) - Number(a?.is_certified ?? 0);
41+
if (certCmp) return certCmp;
42+
43+
const aName = (a.verbose_name || a.column_name) ?? '';
44+
const bName = (b.verbose_name || b.column_name) ?? '';
45+
return aName.localeCompare(bName, undefined, { sensitivity: 'base' });
46+
});
47+
2848
const transformToFolderStructure = (
2949
metricsToDisplay: MetricItem[],
3050
columnsToDisplay: ColumnItem[],
@@ -102,15 +122,15 @@ const transformToFolderStructure = (
102122
id: 'metrics-default',
103123
name: t('Metrics'),
104124
isCollapsed: false,
105-
items: metricsToDisplay,
125+
items: sortMetrics(metricsToDisplay.slice()),
106126
totalItems: allMetrics.length,
107127
showingItems: metricsToDisplay.length,
108128
},
109129
{
110130
id: 'columns-default',
111131
name: t('Columns'),
112132
isCollapsed: false,
113-
items: columnsToDisplay,
133+
items: sortColumns(columnsToDisplay.slice()),
114134
totalItems: allColumns.length,
115135
showingItems: columnsToDisplay.length,
116136
},

superset-frontend/src/explore/components/DatasourcePanel/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export type DatasourcePanelColumn = {
4444
expression?: string | null;
4545
is_certified?: number | null;
4646
column_name?: string | null;
47+
verbose_name?: string | null;
4748
name?: string | null;
4849
type?: string;
4950
};

0 commit comments

Comments
 (0)