mirror of https://github.com/apache/superset.git
chore(explore): Reorder dataset search results based on property relevance (#12770)
This commit is contained in:
parent
dec6661fa6
commit
c475f6b173
|
@ -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,
|
||||||
|
];
|
|
@ -17,9 +17,11 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
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 { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||||
import DatasourcePanel from 'src/explore/components/DatasourcePanel';
|
import DatasourcePanel from 'src/explore/components/DatasourcePanel';
|
||||||
|
import { columns, metrics } from 'spec/javascripts/datasource/fixtures';
|
||||||
|
|
||||||
describe('datasourcepanel', () => {
|
describe('datasourcepanel', () => {
|
||||||
const datasource = {
|
const datasource = {
|
||||||
|
@ -27,8 +29,8 @@ describe('datasourcepanel', () => {
|
||||||
type: 'table',
|
type: 'table',
|
||||||
uid: '1__table',
|
uid: '1__table',
|
||||||
id: 1,
|
id: 1,
|
||||||
columns: [],
|
columns,
|
||||||
metrics: [],
|
metrics,
|
||||||
database: {
|
database: {
|
||||||
backend: 'mysql',
|
backend: 'mysql',
|
||||||
name: 'main',
|
name: 'main',
|
||||||
|
@ -47,6 +49,14 @@ describe('datasourcepanel', () => {
|
||||||
},
|
},
|
||||||
actions: {},
|
actions: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function search(value, input) {
|
||||||
|
fireEvent.change(input, {
|
||||||
|
target: { value },
|
||||||
|
});
|
||||||
|
Simulate.change(input);
|
||||||
|
}
|
||||||
|
|
||||||
it('should render', () => {
|
it('should render', () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<ThemeProvider theme={supersetTheme}>
|
<ThemeProvider theme={supersetTheme}>
|
||||||
|
@ -66,4 +76,46 @@ describe('datasourcepanel', () => {
|
||||||
expect(screen.getByText('Columns')).toBeTruthy();
|
expect(screen.getByText('Columns')).toBeTruthy();
|
||||||
expect(screen.getByText('Metrics')).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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -117,31 +117,43 @@ export default function DataSourcePanel({
|
||||||
setList({
|
setList({
|
||||||
columns: matchSorter(columns, value, {
|
columns: matchSorter(columns, value, {
|
||||||
keys: [
|
keys: [
|
||||||
'verbose_name',
|
|
||||||
'column_name',
|
|
||||||
{
|
{
|
||||||
key: 'description',
|
key: 'verbose_name',
|
||||||
threshold: rankings.CONTAINS,
|
threshold: rankings.CONTAINS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'expression',
|
key: 'column_name',
|
||||||
threshold: rankings.CONTAINS,
|
threshold: rankings.CONTAINS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: item =>
|
||||||
|
[item.description, item.expression].map(
|
||||||
|
x => x?.replace(/[_\n\s]+/g, ' ') || '',
|
||||||
|
),
|
||||||
|
threshold: rankings.CONTAINS,
|
||||||
|
maxRanking: rankings.CONTAINS,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
keepDiacritics: true,
|
keepDiacritics: true,
|
||||||
}),
|
}),
|
||||||
metrics: matchSorter(metrics, value, {
|
metrics: matchSorter(metrics, value, {
|
||||||
keys: [
|
keys: [
|
||||||
'verbose_name',
|
|
||||||
'metric_name',
|
|
||||||
{
|
{
|
||||||
key: 'description',
|
key: 'verbose_name',
|
||||||
threshold: rankings.CONTAINS,
|
threshold: rankings.CONTAINS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'expression',
|
key: 'metric_name',
|
||||||
threshold: rankings.CONTAINS,
|
threshold: rankings.CONTAINS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: item =>
|
||||||
|
[item.description, item.expression].map(
|
||||||
|
x => x?.replace(/[_\n\s]+/g, ' ') || '',
|
||||||
|
),
|
||||||
|
threshold: rankings.CONTAINS,
|
||||||
|
maxRanking: rankings.CONTAINS,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
keepDiacritics: true,
|
keepDiacritics: true,
|
||||||
baseSort: (a, b) =>
|
baseSort: (a, b) =>
|
||||||
|
|
Loading…
Reference in New Issue