This is an automated email from the ASF dual-hosted git repository.
justinpark pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 453a645356 fix(sqllab): Sort db selector options by the API order
(#28749)
453a645356 is described below
commit 453a645356b540520de7ab1cb3339a0353cfbc5c
Author: JUST.in DO IT <[email protected]>
AuthorDate: Wed May 29 11:17:37 2024 -0700
fix(sqllab): Sort db selector options by the API order (#28749)
---
.../DatabaseSelector/DatabaseSelector.test.tsx | 33 +++++++++++++++++++++-
.../src/components/DatabaseSelector/index.tsx | 26 +++++++++++++++--
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git
a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
index 32373301f6..72b22d4f28 100644
---
a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
+++
b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
@@ -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,
diff --git a/superset-frontend/src/components/DatabaseSelector/index.tsx
b/superset-frontend/src/components/DatabaseSelector/index.tsx
index 14753c6dfe..308ebc34bd 100644
--- a/superset-frontend/src/components/DatabaseSelector/index.tsx
+++ b/superset-frontend/src/components/DatabaseSelector/index.tsx
@@ -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,
);