This is an automated email from the ASF dual-hosted git repository.

mintsweet pushed a commit to branch feat-miller-columns
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git

commit 569953f6059b76d9292c3f824b1851a2e2bd847c
Author: mintsweet <[email protected]>
AuthorDate: Fri Sep 27 18:32:52 2024 +1200

    feat: simplify the miller columns
---
 config-ui/package.json                             |   4 +-
 .../components/data-scope-remote/search-local.tsx  | 129 +++++++-------------
 .../components/data-scope-remote/search-remote.tsx | 135 ++++++++++-----------
 .../plugins/components/data-scope-select/index.tsx |  95 ++++++++++-----
 .../webhook/components/selector-dialog.tsx         |  19 +--
 config-ui/yarn.lock                                |  20 +--
 6 files changed, 189 insertions(+), 213 deletions(-)

diff --git a/config-ui/package.json b/config-ui/package.json
index 6bf071988..7e1305d72 100644
--- a/config-ui/package.json
+++ b/config-ui/package.json
@@ -24,8 +24,8 @@
   "dependencies": {
     "@ant-design/icons": "^5.4.0",
     "@fontsource/roboto": "^5.0.14",
-    "@mints/hooks": "^1.0.0-beta.2",
-    "@mints/miller-columns": "^2.0.0-beta.5",
+    "@mints/hooks": "^1.0.0-beta.9",
+    "@mints/miller-columns": "^2.0.0-beta.10",
     "@mui/icons-material": "^5.16.7",
     "@mui/material": "^5.16.7",
     "@mui/styled-engine-sc": "^6.0.0-alpha.18",
diff --git 
a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx 
b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx
index 67b8f4a7f..961ca68e9 100644
--- a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx
+++ b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx
@@ -16,11 +16,12 @@
  *
  */
 
-import { useState, useReducer, useCallback } from 'react';
+import { useState, useReducer } from 'react';
 import { CheckCircleFilled, SearchOutlined } from '@ant-design/icons';
 import { Space, Tag, Button, Input, Modal } from 'antd';
-import { MillerColumns } from '@mints/miller-columns';
 import { useDebounce } from '@mints/hooks';
+import type { IDType } from '@mints/miller-columns';
+import { MillerColumns } from '@mints/miller-columns';
 
 import API from '@/api';
 import { Block, Loading, Message } from '@/components';
@@ -76,43 +77,26 @@ export const SearchLocal = ({ mode, plugin, connectionId, 
config, disabledScope,
 
   const searchDebounce = useDebounce(search, { wait: 500 });
 
-  const request = useCallback(
-    async (groupId?: string | number, params?: any) => {
-      const res = await API.scope.remote(plugin, connectionId, {
-        groupId: groupId ?? null,
-        pageToken: params?.nextPageToken,
-      });
-
-      return {
-        data: res.children.map((it) => ({
-          parentId: it.parentId,
-          id: it.id,
-          title: it.name ?? it.fullName,
-          canExpand: it.type === 'group',
-          original: it,
-        })),
-        hasMore: !!res.nextPageToken,
-        params: {
-          nextPageToken: res.nextPageToken,
-        },
-      };
-    },
-    [plugin, connectionId, scope, searchDebounce],
-  );
+  const request = async (groupId?: string | number, params?: any) => {
+    const res = await API.scope.remote(plugin, connectionId, {
+      groupId: groupId ?? null,
+      pageToken: params?.nextPageToken,
+    });
 
-  const requestAll = useCallback(
-    async (groupId?: string | number) => {
-      return {
-        data: searchDebounce
-          ? scope
-              .filter((it) => it.title.includes(searchDebounce) && 
!it.canExpand)
-              .map((it) => ({ ...it, parentId: null }))
-          : scope.filter((it) => it.parentId === (groupId ?? null)),
-        hasMore: false,
-      };
-    },
-    [scope, searchDebounce],
-  );
+    return {
+      data: res.children.map((it) => ({
+        parentId: it.parentId,
+        id: it.id,
+        title: it.name ?? it.fullName,
+        canExpand: it.type === 'group',
+        original: it,
+      })),
+      hasMore: !!res.nextPageToken,
+      params: {
+        nextPageToken: res.nextPageToken,
+      },
+    };
+  };
 
   const handleRequestAll = async () => {
     setOpen(false);
@@ -145,6 +129,24 @@ export const SearchLocal = ({ mode, plugin, connectionId, 
config, disabledScope,
     dispatch({ type: 'DONE' });
   };
 
+  const millerColumnsProps = {
+    bordered: true,
+    theme: {
+      colorPrimary: '#7497f7',
+      borderColor: '#dbe4fd',
+    },
+    columnHeight: 300,
+    mode,
+    renderTitle: (id?: IDType) =>
+      !id &&
+      config.millerColumn?.firstColumnTitle && 
<S.ColumnTitle>{config.millerColumn.firstColumnTitle}</S.ColumnTitle>,
+    renderLoading: () => <Loading size={20} style={{ padding: '4px 12px' }} />,
+    selectable: true,
+    disabledIds: disabledScope.map((it) => it.id),
+    selectedIds: selectedScope.map((it) => it.id),
+    onSelectedIds: (_: IDType[], data?: any) => onChange(data ?? []),
+  };
+
   return (
     <>
       <Block title={config.title} required>
@@ -189,56 +191,19 @@ export const SearchLocal = ({ mode, plugin, connectionId, 
config, disabledScope,
         )}
       </Block>
       <Block>
-        {status === 'idle' && (
+        {status === 'idle' ? (
           <MillerColumns
-            bordered
-            theme={{
-              colorPrimary: '#7497f7',
-              borderColor: '#dbe4fd',
-            }}
+            {...millerColumnsProps}
             request={request}
-            columnCount={search ? 1 : config.millerColumn?.columnCount ?? 1}
-            columnHeight={300}
-            mode={mode}
-            renderTitle={(id) =>
-              !id &&
-              config.millerColumn?.firstColumnTitle && (
-                
<S.ColumnTitle>{config.millerColumn.firstColumnTitle}</S.ColumnTitle>
-              )
-            }
-            renderLoading={() => <Loading size={20} style={{ padding: '4px 
12px' }} />}
-            renderError={() => <span style={{ color: 'red' }}>Something 
Error</span>}
-            selectable
-            disabledIds={(disabledScope ?? []).map((it) => it.id)}
-            selectedIds={selectedScope.map((it) => it.id)}
-            onSelectedIds={(_, data) => onChange(data ?? [])}
+            columnCount={config.millerColumn?.columnCount ?? 1}
           />
-        )}
-        {status === 'done' && (
+        ) : (
           <>
             <Input prefix={<SearchOutlined />} value={search} onChange={(e) => 
setSearch(e.target.value)} />
             <MillerColumns
-              bordered
-              theme={{
-                colorPrimary: '#7497f7',
-                borderColor: '#dbe4fd',
-              }}
-              request={requestAll}
-              columnCount={search ? 1 : config.millerColumn?.columnCount ?? 1}
-              columnHeight={300}
-              mode={mode}
-              renderTitle={(id) =>
-                !id &&
-                config.millerColumn?.firstColumnTitle && (
-                  
<S.ColumnTitle>{config.millerColumn.firstColumnTitle}</S.ColumnTitle>
-                )
-              }
-              renderLoading={() => <Loading size={20} style={{ padding: '4px 
12px' }} />}
-              renderError={() => <span style={{ color: 'red' }}>Something 
Error</span>}
-              selectable
-              disabledIds={(disabledScope ?? []).map((it) => it.id)}
-              selectedIds={selectedScope.map((it) => it.id)}
-              onSelectedIds={(_, data) => onChange(data ?? [])}
+              {...millerColumnsProps}
+              loading={status === 'loading'}
+              items={searchDebounce ? scope.filter((it) => 
it.title.includes(searchDebounce) && !it.canExpand) : scope}
             />
           </>
         )}
diff --git 
a/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx 
b/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx
index 0510ad29a..1841d3403 100644
--- a/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx
+++ b/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx
@@ -16,11 +16,13 @@
  *
  */
 
-import { useState, useCallback } from 'react';
+import { useState } from 'react';
 import { SearchOutlined } from '@ant-design/icons';
 import { Space, Tag, Input } from 'antd';
-import { MillerColumns } from '@mints/miller-columns';
+import { useRequest } from '@mints/hooks';
 import { useDebounce } from '@mints/hooks';
+import type { IDType } from '@mints/miller-columns';
+import { MillerColumns } from '@mints/miller-columns';
 
 import API from '@/api';
 import { Block, Loading } from '@/components';
@@ -43,60 +45,62 @@ export const SearchRemote = ({ mode, plugin, connectionId, 
config, disabledScope
 
   const searchDebounce = useDebounce(search, { wait: 500 });
 
-  const request = useCallback(
-    async (groupId?: string | number, params?: any) => {
-      let data = [];
-      let hasMore = false;
-      let newParams = {};
-
-      if (!searchDebounce) {
-        const res = await API.scope.remote(plugin, connectionId, {
-          groupId: groupId ?? null,
-          pageToken: params?.pageToken,
-        });
-
-        data = res.children.map((it) => ({
-          parentId: it.parentId,
-          id: it.id,
-          title: it.name ?? it.fullName,
-          canExpand: it.type === 'group',
-          original: it,
-        }));
+  const { loading, data } = useRequest(async () => {
+    if (!searchDebounce) {
+      return [];
+    }
+    const res = await API.scope.searchRemote(plugin, connectionId, {
+      search: searchDebounce,
+      page: 1,
+      pageSize: 50,
+    });
+    return res.children.map((it) => ({
+      parentId: it.parentId,
+      id: it.id,
+      title: it.fullName ?? it.name,
+      canExpand: it.type === 'group',
+      original: it,
+    }));
+  }, [plugin, connectionId, searchDebounce]);
 
-        hasMore = !!res.nextPageToken;
-        newParams = {
-          pageToken: res.nextPageToken,
-        };
-      } else {
-        const res = await API.scope.searchRemote(plugin, connectionId, {
-          search: searchDebounce,
-          page: params?.page ?? 1,
-          pageSize: 20,
-        });
+  const request = async (groupId?: string | number, params?: any) => {
+    const res = await API.scope.remote(plugin, connectionId, {
+      groupId: groupId ?? null,
+      pageToken: params?.pageToken,
+    });
 
-        data = res.children.map((it) => ({
-          parentId: it.parentId,
-          id: it.id,
-          title: it.fullName ?? it.name,
-          canExpand: it.type === 'group',
-          original: it,
-        }));
+    return {
+      data: res.children.map((it) => ({
+        parentId: it.parentId,
+        id: it.id,
+        title: it.name ?? it.fullName,
+        canExpand: it.type === 'group',
+        original: it,
+      })),
+      hasMore: !!res.nextPageToken,
+      params: {
+        pageToken: res.nextPageToken,
+      },
+    };
+  };
 
-        hasMore = res.children.length === res.pageSize;
-        newParams = {
-          page: (params?.page ?? 0) + 1,
-          count: (params?.count ?? 0) + res.children.length,
-        };
-      }
-
-      return {
-        data,
-        hasMore,
-        params: newParams,
-      };
+  const millerColumnsProps = {
+    bordered: true,
+    theme: {
+      colorPrimary: '#7497f7',
+      borderColor: '#dbe4fd',
     },
-    [plugin, connectionId, searchDebounce],
-  );
+    columnHeight: 300,
+    mode,
+    renderTitle: (id?: IDType) =>
+      !id &&
+      config.millerColumn?.firstColumnTitle && 
<S.ColumnTitle>{config.millerColumn.firstColumnTitle}</S.ColumnTitle>,
+    renderLoading: () => <Loading size={20} style={{ padding: '4px 12px' }} />,
+    selectable: true,
+    disabledIds: disabledScope.map((it) => it.id),
+    selectedIds: selectedScope.map((it) => it.id),
+    onSelectedIds: (_: IDType[], data?: any) => onChange(data ?? []),
+  };
 
   return (
     <>
@@ -125,28 +129,11 @@ export const SearchRemote = ({ mode, plugin, 
connectionId, config, disabledScope
           value={search}
           onChange={(e) => setSearch(e.target.value)}
         />
-        <MillerColumns
-          bordered
-          theme={{
-            colorPrimary: '#7497f7',
-            borderColor: '#dbe4fd',
-          }}
-          request={request}
-          columnCount={searchDebounce ? 1 : config.millerColumn?.columnCount 
?? 1}
-          columnHeight={300}
-          mode={mode}
-          renderTitle={(id?) =>
-            !id &&
-            config.millerColumn?.firstColumnTitle && (
-              
<S.ColumnTitle>{config.millerColumn.firstColumnTitle}</S.ColumnTitle>
-            )
-          }
-          renderLoading={() => <Loading size={20} style={{ padding: '4px 12px' 
}} />}
-          selectable
-          disabledIds={disabledScope.map((it) => it.id)}
-          selectedIds={selectedScope.map((it) => it.id)}
-          onSelectedIds={(_, data) => onChange(data ?? [])}
-        />
+        {searchDebounce ? (
+          <MillerColumns {...millerColumnsProps} loading={loading} items={data 
?? []} columnCount={1} />
+        ) : (
+          <MillerColumns {...millerColumnsProps} request={request} 
columnCount={config.millerColumn?.columnCount} />
+        )}
       </Block>
     </>
   );
diff --git a/config-ui/src/plugins/components/data-scope-select/index.tsx 
b/config-ui/src/plugins/components/data-scope-select/index.tsx
index d6913cee0..6bee1af1e 100644
--- a/config-ui/src/plugins/components/data-scope-select/index.tsx
+++ b/config-ui/src/plugins/components/data-scope-select/index.tsx
@@ -19,12 +19,15 @@
 import { useState, useEffect, useCallback } from 'react';
 import { RedoOutlined, PlusOutlined } from '@ant-design/icons';
 import { Flex, Button, Input, Space, Tag } from 'antd';
+import { useRequest } from '@mints/hooks';
+import type { IDType } from '@mints/miller-columns';
 import { MillerColumns } from '@mints/miller-columns';
 import { useDebounce } from '@mints/hooks';
 
 import API from '@/api';
 import { Loading, Block, ExternalLink, Message } from '@/components';
 import { getPluginScopeId } from '@/plugins';
+import type { IDataScope } from '@/types';
 
 interface Props {
   plugin: string;
@@ -65,6 +68,25 @@ export const DataScopeSelect = ({
     );
   }, []);
 
+  const { loading, data } = useRequest(async () => {
+    if (!searchDebounce) {
+      return [];
+    }
+    const res = await API.scope.list(plugin, connectionId, {
+      page: 1,
+      pageSize: 50,
+      searchTerm: searchDebounce,
+    });
+
+    return res.scopes.map((it) => ({
+      parentId: null,
+      id: getPluginScopeId(plugin, it.scope),
+      title: it.scope.fullName ?? it.scope.name,
+      canExpand: false,
+      original: it,
+    }));
+  }, [plugin, connectionId, searchDebounce, version]);
+
   const request = useCallback(
     async (_?: string | number, params?: any) => {
       const res = await API.scope.list(plugin, connectionId, {
@@ -87,11 +109,46 @@ export const DataScopeSelect = ({
         },
       };
     },
-    [plugin, connectionId, searchDebounce, version],
+    [plugin, connectionId],
   );
 
   const handleSubmit = () => onSubmit?.(selectedIds);
 
+  const millerColumnsProps = {
+    bordered: true,
+    theme: {
+      colorPrimary: '#7497f7',
+      borderColor: '#dbe4fd',
+    },
+    columnHeight: 200,
+    renderLoading: () => <Loading size={20} style={{ padding: '4px 12px' }} />,
+    renderNoData: () => (
+      <Flex style={{ height: '100%' }} justify="center" align="center">
+        <ExternalLink link={`/connections/${plugin}/${connectionId}`}>
+          <Button type="primary" icon={<PlusOutlined />}>
+            Add Data Scope
+          </Button>
+        </ExternalLink>
+      </Flex>
+    ),
+    selectable: true,
+    selectedIds,
+    onSelectedIds: (
+      ids: IDType[],
+      data?: Array<{
+        scope: IDataScope;
+      }>,
+    ) => {
+      setSelectedIds(ids);
+      setSelectedScope(
+        (data ?? []).map((it) => ({
+          id: getPluginScopeId(plugin, it.scope),
+          name: it.scope.fullName ?? it.scope.name,
+        })),
+      );
+    },
+  };
+
   return (
     <Block
       title="Select Data Scope"
@@ -142,37 +199,11 @@ export const DataScopeSelect = ({
         </Space>
         <div>
           <Input.Search value={search} onChange={(e) => 
setSearch(e.target.value)} />
-          <MillerColumns
-            bordered
-            theme={{
-              colorPrimary: '#7497f7',
-              borderColor: '#dbe4fd',
-            }}
-            request={request}
-            columnHeight={200}
-            renderLoading={() => <Loading size={20} style={{ padding: '4px 
12px' }} />}
-            renderError={() => <span style={{ color: 'red' }}>Something 
Error</span>}
-            renderNoData={() => (
-              <Flex style={{ height: '100%' }} justify="center" align="center">
-                <ExternalLink link={`/connections/${plugin}/${connectionId}`}>
-                  <Button type="primary" icon={<PlusOutlined />}>
-                    Add Data Scope
-                  </Button>
-                </ExternalLink>
-              </Flex>
-            )}
-            selectable
-            selectedIds={selectedIds}
-            onSelectedIds={(ids, data) => {
-              setSelectedIds(ids);
-              setSelectedScope(
-                (data ?? []).map((it) => ({
-                  id: it.scope.id,
-                  name: it.scope.name,
-                })),
-              );
-            }}
-          />
+          {searchDebounce ? (
+            <MillerColumns {...millerColumnsProps} loading={loading} 
items={data ?? []} />
+          ) : (
+            <MillerColumns {...millerColumnsProps} request={request} 
rootId={version} />
+          )}
         </div>
         <Flex justify="flex-end" gap="small">
           <Button onClick={onCancel}>Cancel</Button>
diff --git 
a/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx 
b/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx
index a0c972dee..516298572 100644
--- a/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx
+++ b/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx
@@ -16,7 +16,7 @@
  *
  */
 
-import { useCallback, useState } from 'react';
+import { useState } from 'react';
 import { Modal } from 'antd';
 import { MillerColumns } from '@mints/miller-columns';
 
@@ -39,17 +39,6 @@ export const SelectorDialog = ({ open, saving, onCancel, 
onSubmit }: Props) => {
 
   const webhooks = useAppSelector(selectWebhooks);
 
-  const request = useCallback(async () => {
-    return {
-      data: webhooks.map((it) => ({
-        parentId: null,
-        id: it.id,
-        title: it.name,
-      })),
-      hasMore: false,
-    };
-  }, [webhooks]);
-
   const handleSubmit = () => onSubmit(webhooks.filter((it) => 
selectedIds.includes(it.id)));
 
   return (
@@ -74,7 +63,11 @@ export const SelectorDialog = ({ open, saving, onCancel, 
onSubmit }: Props) => {
               colorPrimary: '#7497f7',
               borderColor: '#dbe4fd',
             }}
-            request={request}
+            items={webhooks.map((it) => ({
+              parentId: null,
+              id: it.id,
+              title: it.name,
+            }))}
             columnHeight={160}
             renderLoading={() => <Loading size={20} style={{ padding: '4px 
12px' }} />}
             selectable
diff --git a/config-ui/yarn.lock b/config-ui/yarn.lock
index 9e36a73e3..c7db434e4 100644
--- a/config-ui/yarn.lock
+++ b/config-ui/yarn.lock
@@ -2073,9 +2073,9 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@mints/hooks@npm:^1.0.0-beta.2":
-  version: 1.0.0-beta.2
-  resolution: "@mints/hooks@npm:1.0.0-beta.2"
+"@mints/hooks@npm:^1.0.0-beta.9":
+  version: 1.0.0-beta.9
+  resolution: "@mints/hooks@npm:1.0.0-beta.9"
   dependencies:
     lodash: ^4.17.21
     react: ^18.3.1
@@ -2083,13 +2083,13 @@ __metadata:
   peerDependencies:
     react: ^18.3.1
     react-dom: ^18.3.1
-  checksum: 
b11707b70aca8c931d247e18065046d7f5bbef4eee7e17bbae1ff1c85a4f90e830d6af0d3397bd8bec63fa81b5f44055363184b162b4cd90edc0316d4d53251b
+  checksum: 
03f146f2e1881dee18383502dc7631f630c7b99fd7da67d54d37a7b3abac6518e0a302e34b968c72d27cb21ae0c45c39e34d668930881d3e1fd2fbb7dac34b85
   languageName: node
   linkType: hard
 
-"@mints/miller-columns@npm:^2.0.0-beta.5":
-  version: 2.0.0-beta.5
-  resolution: "@mints/miller-columns@npm:2.0.0-beta.5"
+"@mints/miller-columns@npm:^2.0.0-beta.10":
+  version: 2.0.0-beta.10
+  resolution: "@mints/miller-columns@npm:2.0.0-beta.10"
   dependencies:
     "@fontsource/roboto": ^5.0.14
     "@mui/material": ^5.16.7
@@ -2108,7 +2108,7 @@ __metadata:
     react-dom: ^18.2.0
     react-infinite-scroll-component: ^6.1.0
     styled-components: ^6.1.12
-  checksum: 
2ff5e7e942a1f5e592d7fe53d5522a59d72075604e80cfcf816d70d67ad33d3982b699770cdab01065bff19a219117b51017ea878ce5f015f120fb6623431839
+  checksum: 
94c3ba41210f2ccbddc413ef6c26e5615f11c5a3aac7954484d838d1b05713543def70b6714e79cfc396efea522f553b2d648b36af994bf66456a440836a1386
   languageName: node
   linkType: hard
 
@@ -3910,8 +3910,8 @@ __metadata:
   dependencies:
     "@ant-design/icons": ^5.4.0
     "@fontsource/roboto": ^5.0.14
-    "@mints/hooks": ^1.0.0-beta.2
-    "@mints/miller-columns": ^2.0.0-beta.5
+    "@mints/hooks": ^1.0.0-beta.9
+    "@mints/miller-columns": ^2.0.0-beta.10
     "@mui/icons-material": ^5.16.7
     "@mui/material": ^5.16.7
     "@mui/styled-engine-sc": ^6.0.0-alpha.18

Reply via email to