fix(sqllab): Sort db selector options by the API order (#28749)

This commit is contained in:
JUST.in DO IT 2024-05-29 11:17:37 -07:00 committed by GitHub
parent a67b0edfb2
commit 453a645356
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 55 additions and 4 deletions

View File

@ -154,6 +154,12 @@ const fakeDatabaseApiResult = {
],
};
const fakeDatabaseApiResultInReverseOrder = {
...fakeDatabaseApiResult,
ids: [2, 1],
result: [...fakeDatabaseApiResult.result].reverse(),
};
const fakeSchemaApiResult = {
count: 2,
result: ['information_schema', 'public'],
@ -168,7 +174,8 @@ const fakeFunctionNamesApiResult = {
function_names: [],
};
const databaseApiRoute = 'glob:*/api/v1/database/?*';
const databaseApiRoute =
'glob:*/api/v1/database/?*order_column:database_name,order_direction*';
const catalogApiRoute = 'glob:*/api/v1/database/*/catalogs/?*';
const schemaApiRoute = 'glob:*/api/v1/database/*/schemas/?*';
const tablesApiRoute = 'glob:*/api/v1/database/*/tables/*';
@ -241,6 +248,30 @@ test('Should database select display options', async () => {
expect(await screen.findByText('test-mysql')).toBeInTheDocument();
});
test('should display options in order of the api response', async () => {
fetchMock.get(databaseApiRoute, fakeDatabaseApiResultInReverseOrder, {
overwriteRoutes: true,
});
const props = createProps();
render(<DatabaseSelector {...props} db={undefined} />, {
useRedux: true,
store,
});
const select = screen.getByRole('combobox', {
name: 'Select database or type to search databases',
});
expect(select).toBeInTheDocument();
userEvent.click(select);
const options = await screen.findAllByRole('option');
expect(options[0]).toHaveTextContent(
`${fakeDatabaseApiResultInReverseOrder.result[0].id}`,
);
expect(options[1]).toHaveTextContent(
`${fakeDatabaseApiResultInReverseOrder.result[1].id}`,
);
});
test('Should fetch the search keyword when total count exceeds initial options', async () => {
fetchMock.get(
databaseApiRoute,

View File

@ -16,8 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { ReactNode, useState, useMemo, useEffect, useRef } from 'react';
import React, {
ReactNode,
useState,
useMemo,
useEffect,
useRef,
useCallback,
} from 'react';
import { styled, SupersetClient, t } from '@superset-ui/core';
import type { LabeledValue as AntdLabeledValue } from 'antd/lib/select';
import rison from 'rison';
import { AsyncSelect, Select } from 'src/components';
import Label from 'src/components/Label';
@ -124,6 +132,10 @@ const SelectLabel = ({
const EMPTY_CATALOG_OPTIONS: CatalogOption[] = [];
const EMPTY_SCHEMA_OPTIONS: SchemaOption[] = [];
interface AntdLabeledValueWithOrder extends AntdLabeledValue {
order: number;
}
export default function DatabaseSelector({
db,
formMode = false,
@ -153,6 +165,11 @@ export default function DatabaseSelector({
const schemaRef = useRef(schema);
schemaRef.current = schema;
const { addSuccessToast } = useToasts();
const sortComparator = useCallback(
(itemA: AntdLabeledValueWithOrder, itemB: AntdLabeledValueWithOrder) =>
itemA.order - itemB.order,
[],
);
const loadDatabases = useMemo(
() =>
@ -165,7 +182,7 @@ export default function DatabaseSelector({
totalCount: number;
}> => {
const queryParams = rison.encode({
order_columns: 'database_name',
order_column: 'database_name',
order_direction: 'asc',
page,
page_size: pageSize,
@ -191,7 +208,8 @@ export default function DatabaseSelector({
if (result.length === 0) {
if (onEmptyResults) onEmptyResults(search);
}
const options = result.map((row: DatabaseObject) => ({
const options = result.map((row: DatabaseObject, order: number) => ({
label: (
<SelectLabel
backend={row.backend}
@ -203,6 +221,7 @@ export default function DatabaseSelector({
database_name: row.database_name,
backend: row.backend,
allow_multi_catalog: row.allow_multi_catalog,
order,
}));
return {
@ -346,6 +365,7 @@ export default function DatabaseSelector({
placeholder={t('Select database or type to search databases')}
disabled={!isDatabaseSelectEnabled || readOnly}
options={loadDatabases}
sortComparator={sortComparator}
/>,
null,
);