This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 94aaaf93d feat: simplify the miller columns (#8112)
94aaaf93d is described below
commit 94aaaf93d0301311feeee6f0883ab59e56a75a7d
Author: 青湛 <[email protected]>
AuthorDate: Sat Sep 28 00:51:31 2024 +1200
feat: simplify the miller columns (#8112)
---
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