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,
     );

Reply via email to