chore(explore): Reorder dataset search results based on property relevance (#12770)

This commit is contained in:
Nikola Gigić 2021-01-28 02:49:02 +01:00 committed by GitHub
parent dec6661fa6
commit c475f6b173
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 168 additions and 11 deletions

View File

@ -0,0 +1,93 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export const columns = [
{
column_name: 'bootcamp_attend',
description: null,
expression: null,
filterable: true,
groupby: true,
id: 516,
is_dttm: false,
python_date_format: null,
type: 'DOUBLE PRECISION',
verbose_name: null,
},
{
column_name: 'calc_first_time_dev',
description: null,
expression:
'CASE WHEN is_first_dev_job = 0 THEN "No" WHEN is_first_dev_job = 1 THEN "Yes" END',
filterable: true,
groupby: true,
id: 477,
is_dttm: false,
python_date_format: null,
type: 'STRING',
verbose_name: null,
},
{
column_name: 'aaaaaaaaaaa',
description: null,
expression: null,
filterable: true,
groupby: true,
id: 516,
is_dttm: false,
python_date_format: null,
type: 'DOUBLE PRECISION',
verbose_name: null,
},
];
const metricsFiltered = {
certified: [
{
certification_details: null,
certified_by: 'user',
d3format: null,
description: null,
expression: '',
id: 56,
is_certified: true,
metric_name: 'metric_end_certified',
verbose_name: '',
warning_text: null,
},
],
uncertified: [
{
certification_details: null,
certified_by: null,
d3format: null,
description: null,
expression: '',
id: 57,
is_certified: false,
metric_name: 'metric_end',
verbose_name: '',
warning_text: null,
},
],
};
export const metrics = [
...metricsFiltered.certified,
...metricsFiltered.uncertified,
];

View File

@ -17,9 +17,11 @@
* under the License.
*/
import React from 'react';
import { render, screen } from '@testing-library/react';
import { Simulate } from 'react-dom/test-utils';
import { render, screen, fireEvent } from '@testing-library/react';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import DatasourcePanel from 'src/explore/components/DatasourcePanel';
import { columns, metrics } from 'spec/javascripts/datasource/fixtures';
describe('datasourcepanel', () => {
const datasource = {
@ -27,8 +29,8 @@ describe('datasourcepanel', () => {
type: 'table',
uid: '1__table',
id: 1,
columns: [],
metrics: [],
columns,
metrics,
database: {
backend: 'mysql',
name: 'main',
@ -47,6 +49,14 @@ describe('datasourcepanel', () => {
},
actions: {},
};
function search(value, input) {
fireEvent.change(input, {
target: { value },
});
Simulate.change(input);
}
it('should render', () => {
const { container } = render(
<ThemeProvider theme={supersetTheme}>
@ -66,4 +76,46 @@ describe('datasourcepanel', () => {
expect(screen.getByText('Columns')).toBeTruthy();
expect(screen.getByText('Metrics')).toBeTruthy();
});
it('should render search results', () => {
const { container } = render(
<ThemeProvider theme={supersetTheme}>
<DatasourcePanel {...props} />
</ThemeProvider>,
);
const c = container.getElementsByClassName('option-label');
expect(c).toHaveLength(5);
});
it('should render 0 search results', () => {
const { container } = render(
<ThemeProvider theme={supersetTheme}>
<DatasourcePanel {...props} />
</ThemeProvider>,
);
const c = container.getElementsByClassName('option-label');
const searchInput = screen.getByPlaceholderText('Search Metrics & Columns');
search('sssssssss', searchInput);
setTimeout(() => {
expect(c).toHaveLength(0);
}, 201);
});
it('should render and sort search results', () => {
const { container } = render(
<ThemeProvider theme={supersetTheme}>
<DatasourcePanel {...props} />
</ThemeProvider>,
);
const c = container.getElementsByClassName('option-label');
const searchInput = screen.getByPlaceholderText('Search Metrics & Columns');
search('end', searchInput);
setTimeout(() => {
expect(c).toHaveLength(4);
expect(c[0].value).toBe('metric_end_certified');
}, 201);
});
});

View File

@ -117,31 +117,43 @@ export default function DataSourcePanel({
setList({
columns: matchSorter(columns, value, {
keys: [
'verbose_name',
'column_name',
{
key: 'description',
key: 'verbose_name',
threshold: rankings.CONTAINS,
},
{
key: 'expression',
key: 'column_name',
threshold: rankings.CONTAINS,
},
{
key: item =>
[item.description, item.expression].map(
x => x?.replace(/[_\n\s]+/g, ' ') || '',
),
threshold: rankings.CONTAINS,
maxRanking: rankings.CONTAINS,
},
],
keepDiacritics: true,
}),
metrics: matchSorter(metrics, value, {
keys: [
'verbose_name',
'metric_name',
{
key: 'description',
key: 'verbose_name',
threshold: rankings.CONTAINS,
},
{
key: 'expression',
key: 'metric_name',
threshold: rankings.CONTAINS,
},
{
key: item =>
[item.description, item.expression].map(
x => x?.replace(/[_\n\s]+/g, ' ') || '',
),
threshold: rankings.CONTAINS,
maxRanking: rankings.CONTAINS,
},
],
keepDiacritics: true,
baseSort: (a, b) =>