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 3e77dd5da fix(config-ui): switch data scope lost data (#6085)
3e77dd5da is described below

commit 3e77dd5da8da19ff0f98811549a16366b4525baa
Author: 青湛 <[email protected]>
AuthorDate: Fri Sep 15 16:32:52 2023 +1200

    fix(config-ui): switch data scope lost data (#6085)
    
    * refactor(config-ui): remove data scope search
    
    * fix(config-ui): switch data scope lost data
---
 .../plugins/components/data-scope-search/api.ts    |  31 ------
 .../plugins/components/data-scope-search/index.tsx |  70 ------------
 .../plugins/components/data-scope-search/types.ts  |  24 -----
 .../components/data-scope-select-remote/api.ts     |   2 +-
 .../components/data-scope-select-remote/index.tsx  | 120 ++++++++++++---------
 config-ui/src/plugins/components/index.ts          |   1 -
 6 files changed, 71 insertions(+), 177 deletions(-)

diff --git a/config-ui/src/plugins/components/data-scope-search/api.ts 
b/config-ui/src/plugins/components/data-scope-search/api.ts
deleted file mode 100644
index e1e7e74a4..000000000
--- a/config-ui/src/plugins/components/data-scope-search/api.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { request } from '@/utils';
-
-type Params = {
-  search?: string;
-  page?: number;
-  pageSize?: number;
-};
-
-export const searchScope = (plugin: string, connectionId: ID, params: Params) 
=>
-  
request(`/plugins/${plugin}/connections/${connectionId}/search-remote-scopes`, {
-    method: 'get',
-    data: params,
-  });
diff --git a/config-ui/src/plugins/components/data-scope-search/index.tsx 
b/config-ui/src/plugins/components/data-scope-search/index.tsx
deleted file mode 100644
index 5ab73d613..000000000
--- a/config-ui/src/plugins/components/data-scope-search/index.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { useState } from 'react';
-import { useDebounce } from 'ahooks';
-
-import { MultiSelector } from '@/components';
-import { useRefreshData } from '@/hooks';
-
-import type { ItemType } from './types';
-import * as API from './api';
-
-interface Props {
-  plugin: string;
-  connectionId: ID;
-  disabledItems?: any[];
-  selectedItems?: any[];
-  onChangeItems?: (selectedItems: any[]) => void;
-}
-
-export const DataScopeSearch = ({ plugin, connectionId, disabledItems, 
selectedItems, onChangeItems }: Props) => {
-  const [query, setQuery] = useState('');
-
-  const search = useDebounce(query, { wait: 500 });
-
-  const { ready, data } = useRefreshData<{ children: ItemType[] }>(async () => 
{
-    if (!search) return { children: [] };
-    return API.searchScope(plugin, connectionId, {
-      search,
-      page: 1,
-      pageSize: 50,
-    });
-  }, [search]);
-
-  const getKey = (it: ItemType) => it.id;
-
-  const getName = (it: ItemType) => it.fullName;
-
-  const handleChangeItems = (selectedItems: ItemType[]) => 
onChangeItems?.(selectedItems);
-
-  return (
-    <MultiSelector
-      placeholder="Search Repositories..."
-      items={data?.children ?? []}
-      getKey={getKey}
-      getName={getName}
-      disabledItems={disabledItems}
-      selectedItems={selectedItems}
-      onChangeItems={handleChangeItems}
-      loading={!ready}
-      noResult="No Repositories Available."
-      onQueryChange={(query) => setQuery(query)}
-    />
-  );
-};
diff --git a/config-ui/src/plugins/components/data-scope-search/types.ts 
b/config-ui/src/plugins/components/data-scope-search/types.ts
deleted file mode 100644
index c3f6318a3..000000000
--- a/config-ui/src/plugins/components/data-scope-search/types.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-export type ItemType = {
-  id: ID;
-  name: string;
-  fullName: string;
-  data: any;
-};
diff --git a/config-ui/src/plugins/components/data-scope-select-remote/api.ts 
b/config-ui/src/plugins/components/data-scope-select-remote/api.ts
index fab503b8e..4c042d6b6 100644
--- a/config-ui/src/plugins/components/data-scope-select-remote/api.ts
+++ b/config-ui/src/plugins/components/data-scope-select-remote/api.ts
@@ -34,7 +34,7 @@ export const searchRemoteScope = (
   plugin: string,
   connectionId: ID,
   params: T.SearchRemoteScopeParams,
-): Promise<{ children: T.ResItem[] }> =>
+): Promise<{ children: T.ResItem[]; count: number }> =>
   
request(`/plugins/${plugin}/connections/${connectionId}/search-remote-scopes`, {
     method: 'get',
     data: params,
diff --git 
a/config-ui/src/plugins/components/data-scope-select-remote/index.tsx 
b/config-ui/src/plugins/components/data-scope-select-remote/index.tsx
index 262756381..5be9d3fd4 100644
--- a/config-ui/src/plugins/components/data-scope-select-remote/index.tsx
+++ b/config-ui/src/plugins/components/data-scope-select-remote/index.tsx
@@ -105,20 +105,31 @@ const SelectRemote = ({
   selectedScope: any[];
   onChangeSelectedScope: (selectedScope: any[]) => void;
 }) => {
-  // miller columns
-  const [items, setItems] = useState<McsItem<T.ResItem>[]>([]);
-  const [loadedIds, setLoadedIds] = useState<ID[]>([]);
-  const [nextTokenMap, setNextTokenMap] = useState<Record<ID, string>>({});
-
-  // search
-  const [query, setQuery] = useState('');
-  const [items2, setItems2] = useState<McsItem<T.ResItem>[]>([]);
-  const [page, setPage] = useState(1);
-  const [total] = useState(0);
-
-  const search = useDebounce(query, { wait: 500 });
-
-  const allItems = useMemo(() => uniqBy([...items, ...items2], 'id'), [items, 
items2]);
+  const [miller, setMiller] = useState<{
+    items: McsItem<T.ResItem>[];
+    loadedIds: ID[];
+    nextTokenMap: Record<ID, string>;
+  }>({
+    items: [],
+    loadedIds: [],
+    nextTokenMap: {},
+  });
+
+  const [search, setSearch] = useState<{
+    items: McsItem<T.ResItem>[];
+    query: string;
+    page: number;
+    total: number;
+  }>({
+    items: [],
+    query: '',
+    page: 1,
+    total: 0,
+  });
+
+  const searchDebounce = useDebounce(search.query, { wait: 500 });
+
+  const allItems = useMemo(() => uniqBy([...miller.items, ...search.items], 
'id'), [miller.items, search.items]);
 
   const getItems = async (groupId: ID | null, currentPageToken?: string) => {
     const res = await API.getRemoteScope(plugin, connectionId, {
@@ -126,21 +137,26 @@ const SelectRemote = ({
       pageToken: currentPageToken,
     });
 
-    setItems([
-      ...items,
-      ...(res.children ?? []).map((it: any) => ({
-        ...it,
-        title: it.name,
-      })),
-    ]);
-
-    if (!res.nextPageToken) {
-      setLoadedIds([...loadedIds, groupId ? groupId : 'root']);
+    const newItems = (res.children ?? []).map((it) => ({
+      ...it,
+      title: it.name,
+    }));
+
+    if (res.nextPageToken) {
+      setMiller((m) => ({
+        ...m,
+        items: [...m.items, ...newItems],
+        nextTokenMap: {
+          ...m.nextTokenMap,
+          [`${groupId ? groupId : 'root'}`]: res.nextPageToken,
+        },
+      }));
     } else {
-      setNextTokenMap({
-        ...nextTokenMap,
-        [`${groupId ? groupId : 'root'}`]: res.nextPageToken,
-      });
+      setMiller((m) => ({
+        ...m,
+        items: [...m.items, ...newItems],
+        loadedIds: [...m.loadedIds, groupId ?? 'root'],
+      }));
     }
   };
 
@@ -149,29 +165,29 @@ const SelectRemote = ({
   }, []);
 
   const searchItems = async () => {
-    if (!search) return;
+    if (!searchDebounce) return;
 
     const res = await API.searchRemoteScope(plugin, connectionId, {
-      search,
-      page,
+      search: searchDebounce,
+      page: search.page,
       pageSize: 50,
     });
 
-    setItems2(
-      res.children.map((it) => ({
-        ...it,
-        title: it.fullName,
-      })),
-    );
+    const newItems = (res.children ?? []).map((it) => ({
+      ...it,
+      title: it.name,
+    }));
 
-    if (page === 1) {
-      // setTotal(res.count);
-    }
+    setSearch((s) => ({
+      ...s,
+      items: [...s.items, ...newItems],
+      total: res.count,
+    }));
   };
 
   useEffect(() => {
     searchItems();
-  }, [search, page]);
+  }, [searchDebounce, search.page]);
 
   return (
     <S.Wrapper>
@@ -185,16 +201,20 @@ const SelectRemote = ({
         />
       </FormItem>
       <FormItem>
-        <InputGroup leftIcon="search" value={query} onChange={(e) => 
setQuery(e.target.value)} />
-        {!search ? (
+        <InputGroup
+          leftIcon="search"
+          value={search.query}
+          onChange={(e) => setSearch({ ...search, query: e.target.value })}
+        />
+        {!searchDebounce ? (
           <MillerColumnsSelect
-            items={items}
+            items={miller.items}
             columnCount={config.millerColumnCount ?? 1}
             columnHeight={300}
             getCanExpand={(it) => it.type === 'group'}
-            getHasMore={(id) => !loadedIds.includes(id ?? 'root')}
-            onExpand={(id: McsID) => getItems(id, nextTokenMap[id])}
-            onScroll={(id: McsID | null) => getItems(id, nextTokenMap[id ?? 
'root'])}
+            getHasMore={(id) => !miller.loadedIds.includes(id ?? 'root')}
+            onExpand={(id: McsID) => getItems(id, miller.nextTokenMap[id])}
+            onScroll={(id: McsID | null) => getItems(id, 
miller.nextTokenMap[id ?? 'root'])}
             renderTitle={(column: McsColumn) =>
               !column.parentId && config.millerFirstTitle && 
<S.ColumnTitle>{config.millerFirstTitle}</S.ColumnTitle>
             }
@@ -207,12 +227,12 @@ const SelectRemote = ({
           />
         ) : (
           <MillerColumnsSelect
-            items={items2}
+            items={search.items}
             columnCount={1}
             columnHeight={300}
             getCanExpand={() => false}
-            getHasMore={() => total === 0}
-            onScroll={() => setPage(page + 1)}
+            getHasMore={() => search.total === 0}
+            onScroll={() => setSearch({ ...search, page: search.page + 1 })}
             renderLoading={() => <Loading size={20} style={{ padding: '4px 
12px' }} />}
             disabledIds={(disabledScope ?? []).map((it) => 
getPluginScopeId(plugin, it))}
             selectedIds={selectedScope.map((it) => it.id)}
diff --git a/config-ui/src/plugins/components/index.ts 
b/config-ui/src/plugins/components/index.ts
index 03f86c5a9..9f3e71026 100644
--- a/config-ui/src/plugins/components/index.ts
+++ b/config-ui/src/plugins/components/index.ts
@@ -19,7 +19,6 @@
 export * from './connection-form';
 export * from './connection-list';
 export * from './connection-status';
-export * from './data-scope-search';
 export * from './data-scope-select';
 export * from './data-scope-select-remote';
 export * from './scope-config-form';

Reply via email to