mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
fix: Use total count to filter datasets (#36135)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
This commit is contained in:
@@ -24,7 +24,8 @@ import {
|
||||
within,
|
||||
} from 'spec/helpers/testing-library';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import DatasetSelect from './DatasetSelect';
|
||||
import DatasetSelect, { loadDatasetOptions } from './DatasetSelect';
|
||||
import { supersetGetCache } from 'src/utils/cachedSupersetGet';
|
||||
|
||||
const DATASETS = [
|
||||
{
|
||||
@@ -201,3 +202,66 @@ test('includes table_name field in option data structure', async () => {
|
||||
expect(callArg).toHaveProperty('table_name', 'birth_names');
|
||||
});
|
||||
});
|
||||
|
||||
test('uses API count instead of filteredResult.length', async () => {
|
||||
supersetGetCache.clear();
|
||||
fetchMock.restore();
|
||||
fetchMock.get('glob:*/api/v1/dataset/*', {
|
||||
result: [
|
||||
{
|
||||
id: 1,
|
||||
table_name: 'ds1',
|
||||
database: { database_name: 'db' },
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
table_name: 'ds2',
|
||||
database: { database_name: 'db' },
|
||||
schema: 'public',
|
||||
},
|
||||
],
|
||||
count: 500,
|
||||
});
|
||||
|
||||
const result = await loadDatasetOptions('', 0, 100, [1, 2]);
|
||||
|
||||
expect(result.totalCount).toBe(500);
|
||||
expect(result.totalCount).not.toBe(0);
|
||||
});
|
||||
|
||||
test('returns total count from API when data is filtered', async () => {
|
||||
supersetGetCache.clear();
|
||||
fetchMock.restore();
|
||||
|
||||
fetchMock.get('glob:*/api/v1/dataset/*', {
|
||||
result: [
|
||||
{
|
||||
id: 1,
|
||||
table_name: 'birth_names',
|
||||
database: { database_name: 'examples' },
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
table_name: 'birth_registry',
|
||||
database: { database_name: 'examples' },
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
table_name: 'birth_rates',
|
||||
database: { database_name: 'examples' },
|
||||
schema: 'public',
|
||||
},
|
||||
],
|
||||
count: 25,
|
||||
});
|
||||
|
||||
// Search for 'birth' and exclude dataset id 2 (client-side filtering)
|
||||
const result = await loadDatasetOptions('birth', 0, 100, [2]);
|
||||
|
||||
expect(result.totalCount).toBe(25);
|
||||
expect(result.data).toHaveLength(2);
|
||||
expect(result.data.find(item => item.value === 2)).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -37,70 +37,73 @@ interface DatasetSelectProps {
|
||||
excludeDatasetIds?: number[];
|
||||
}
|
||||
|
||||
const getErrorMessage = ({ error, message }: ClientErrorObject) => {
|
||||
let errorText = message || error || t('An error has occurred');
|
||||
if (message === 'Forbidden') {
|
||||
errorText = t('You do not have permission to edit this dashboard');
|
||||
}
|
||||
return errorText;
|
||||
};
|
||||
|
||||
export const loadDatasetOptions = async (
|
||||
search: string,
|
||||
page: number,
|
||||
pageSize: number,
|
||||
excludeDatasetIds: number[] = [],
|
||||
) => {
|
||||
const query = rison.encode({
|
||||
columns: ['id', 'table_name', 'database.database_name', 'schema'],
|
||||
filters: [{ col: 'table_name', opr: 'ct', value: search }],
|
||||
page,
|
||||
page_size: pageSize,
|
||||
order_column: 'table_name',
|
||||
order_direction: 'asc',
|
||||
});
|
||||
return cachedSupersetGet({
|
||||
endpoint: `/api/v1/dataset/?q=${query}`,
|
||||
})
|
||||
.then((response: JsonResponse) => {
|
||||
const filteredResult = response.json.result.filter(
|
||||
(item: Dataset) => !excludeDatasetIds.includes(item.id),
|
||||
);
|
||||
|
||||
const list: {
|
||||
label: string | ReactNode;
|
||||
value: string | number;
|
||||
table_name: string;
|
||||
}[] = filteredResult.map((item: Dataset) => ({
|
||||
...item,
|
||||
label: DatasetSelectLabel(item),
|
||||
value: item.id,
|
||||
table_name: item.table_name,
|
||||
}));
|
||||
return {
|
||||
data: list,
|
||||
totalCount: response.json.count ?? 0,
|
||||
};
|
||||
})
|
||||
.catch(async error => {
|
||||
const errorMessage = getErrorMessage(await getClientErrorObject(error));
|
||||
throw new Error(errorMessage);
|
||||
});
|
||||
};
|
||||
|
||||
const DatasetSelect = ({
|
||||
onChange,
|
||||
value,
|
||||
excludeDatasetIds = [],
|
||||
}: DatasetSelectProps) => {
|
||||
const getErrorMessage = useCallback(
|
||||
({ error, message }: ClientErrorObject) => {
|
||||
let errorText = message || error || t('An error has occurred');
|
||||
if (message === 'Forbidden') {
|
||||
errorText = t('You do not have permission to edit this dashboard');
|
||||
}
|
||||
return errorText;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const loadDatasetOptions = useCallback(
|
||||
async (search: string, page: number, pageSize: number) => {
|
||||
const query = rison.encode({
|
||||
columns: ['id', 'table_name', 'database.database_name', 'schema'],
|
||||
filters: [{ col: 'table_name', opr: 'ct', value: search }],
|
||||
page,
|
||||
page_size: pageSize,
|
||||
order_column: 'table_name',
|
||||
order_direction: 'asc',
|
||||
});
|
||||
return cachedSupersetGet({
|
||||
endpoint: `/api/v1/dataset/?q=${query}`,
|
||||
})
|
||||
.then((response: JsonResponse) => {
|
||||
const filteredResult = response.json.result.filter(
|
||||
(item: Dataset) => !excludeDatasetIds.includes(item.id),
|
||||
);
|
||||
|
||||
const list: {
|
||||
label: string | ReactNode;
|
||||
value: string | number;
|
||||
table_name: string;
|
||||
}[] = filteredResult.map((item: Dataset) => ({
|
||||
...item,
|
||||
label: DatasetSelectLabel(item),
|
||||
value: item.id,
|
||||
table_name: item.table_name,
|
||||
}));
|
||||
return {
|
||||
data: list,
|
||||
totalCount: filteredResult.length,
|
||||
};
|
||||
})
|
||||
.catch(async error => {
|
||||
const errorMessage = getErrorMessage(
|
||||
await getClientErrorObject(error),
|
||||
);
|
||||
throw new Error(errorMessage);
|
||||
});
|
||||
},
|
||||
[excludeDatasetIds, getErrorMessage],
|
||||
const loadDatasetOptionsCallback = useCallback(
|
||||
(search: string, page: number, pageSize: number) =>
|
||||
loadDatasetOptions(search, page, pageSize, excludeDatasetIds),
|
||||
[excludeDatasetIds],
|
||||
);
|
||||
|
||||
return (
|
||||
<AsyncSelect
|
||||
ariaLabel={t('Dataset')}
|
||||
value={value}
|
||||
options={loadDatasetOptions}
|
||||
options={loadDatasetOptionsCallback}
|
||||
onChange={onChange}
|
||||
optionFilterProps={['table_name']}
|
||||
notFoundContent={t('No compatible datasets found')}
|
||||
|
||||
Reference in New Issue
Block a user