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 1616095e7 fix(config-ui): add pagination params for all tables (#5878)
1616095e7 is described below
commit 1616095e727f4f7825ae9dc3522163011ec21fdb
Author: 青湛 <[email protected]>
AuthorDate: Tue Aug 15 22:05:44 2023 +1200
fix(config-ui): add pagination params for all tables (#5878)
* feat(config-ui): add new component pagination
* feat(config-ui): support pagination in table
* fix(config-ui): add pagination params for all tables
---
config-ui/src/components/index.ts | 1 +
config-ui/src/components/pagination/index.tsx | 58 ++++++++++++
config-ui/src/components/pagination/styled.ts | 73 +++++++++++++++
config-ui/src/components/table/table.tsx | 19 +++-
config-ui/src/global.d.ts | 5 +
.../pages/blueprint/connection-detail/index.tsx | 4 +-
config-ui/src/pages/blueprint/home/api.ts | 9 +-
config-ui/src/pages/blueprint/home/index.tsx | 64 ++++++-------
config-ui/src/pages/connection/detail/api.ts | 3 +-
config-ui/src/pages/connection/detail/index.tsx | 19 +++-
config-ui/src/pages/project/home/api.ts | 2 +-
config-ui/src/pages/project/home/index.tsx | 16 +++-
.../plugins/components/data-scope-select/api.ts | 9 +-
.../plugins/components/data-scope-select/index.tsx | 103 +++++++++++----------
14 files changed, 285 insertions(+), 100 deletions(-)
diff --git a/config-ui/src/components/index.ts
b/config-ui/src/components/index.ts
index 4ce766199..f039fc6f9 100644
--- a/config-ui/src/components/index.ts
+++ b/config-ui/src/components/index.ts
@@ -29,6 +29,7 @@ export * from './logo';
export * from './message';
export * from './no-data';
export * from './page-header';
+export * from './pagination';
export * from './selector';
export * from './table';
export * from './toast';
diff --git a/config-ui/src/components/pagination/index.tsx
b/config-ui/src/components/pagination/index.tsx
new file mode 100644
index 000000000..8bde5cf53
--- /dev/null
+++ b/config-ui/src/components/pagination/index.tsx
@@ -0,0 +1,58 @@
+/*
+ * 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 { Icon } from '@blueprintjs/core';
+
+import * as S from './styled';
+
+export interface PaginationProps {
+ page: number;
+ pageSize?: number;
+ total: number;
+ onChange: (page: number) => void;
+}
+
+export const Pagination = ({ page, pageSize = 20, total, onChange }:
PaginationProps) => {
+ const lastPage = Math.ceil(total / pageSize);
+
+ const handlePrevPage = () => {
+ if (page === 1) return;
+ onChange(page - 1);
+ };
+
+ const handleNextPage = () => {
+ if (page === lastPage) return;
+ onChange(page + 1);
+ };
+
+ return (
+ <S.List>
+ <S.Item disabled={page === 1} onClick={handlePrevPage}>
+ <Icon icon="chevron-left" />
+ </S.Item>
+ {Array.from({ length: lastPage }).map((_, i) => (
+ <S.Item key={i + 1} active={page === i + 1} onClick={() => onChange(i
+ 1)}>
+ <span>{i + 1}</span>
+ </S.Item>
+ ))}
+ <S.Item disabled={page === lastPage} onClick={handleNextPage}>
+ <Icon icon="chevron-right" />
+ </S.Item>
+ </S.List>
+ );
+};
diff --git a/config-ui/src/components/pagination/styled.ts
b/config-ui/src/components/pagination/styled.ts
new file mode 100644
index 000000000..5a810dcb1
--- /dev/null
+++ b/config-ui/src/components/pagination/styled.ts
@@ -0,0 +1,73 @@
+/*
+ * 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 styled from 'styled-components';
+
+export const List = styled.ul`
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ margin-top: 16px;
+`;
+
+export const Item = styled.li<{ active?: boolean; disabled?: boolean }>`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 8px;
+ width: 30px;
+ height: 30px;
+ color: #7497f7;
+ border: 1px solid #7497f7;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.3s ease-in-out;
+
+ &:hover {
+ color: #fff;
+ background-color: #7497f7;
+ }
+
+ ${({ active }) =>
+ active
+ ? `
+ color: #fff;
+ background-color: #7497f7;
+ cursor: no-drop;
+ `
+ : ''}
+
+ ${({ disabled }) =>
+ disabled
+ ? `
+ color: #a1a1a1;
+ border-color: #a1a1a1;
+ cursor: no-drop;
+
+ &:hover {
+ color: #a1a1a1;
+ border-color: #a1a1a1;
+ background-color: transparent;
+ }
+ `
+ : ''}
+
+ &:last-child {
+ margin-right: 0;
+ }
+`;
diff --git a/config-ui/src/components/table/table.tsx
b/config-ui/src/components/table/table.tsx
index 2f8e2fdf7..b55b6021b 100644
--- a/config-ui/src/components/table/table.tsx
+++ b/config-ui/src/components/table/table.tsx
@@ -16,6 +16,9 @@
*
*/
+import type { PaginationProps } from '../pagination';
+import { Pagination } from '../pagination';
+
import type { TableContentProps } from './components';
import { TableLoading, TableNoData, TableContent } from './components';
@@ -26,9 +29,16 @@ interface Props<T> extends TableContentProps<T> {
btnText?: string;
onCreate?: () => void;
};
+ pagination?: PaginationProps;
}
-export const Table = <T extends Record<string, any>>({ loading, dataSource,
noData = {}, ...props }: Props<T>) => {
+export const Table = <T extends Record<string, any>>({
+ loading,
+ dataSource,
+ noData = {},
+ pagination,
+ ...props
+}: Props<T>) => {
if (loading) {
return <TableLoading />;
}
@@ -37,5 +47,10 @@ export const Table = <T extends Record<string, any>>({
loading, dataSource, noDa
return <TableNoData {...noData} />;
}
- return <TableContent dataSource={dataSource} {...props} />;
+ return (
+ <>
+ <TableContent dataSource={dataSource} {...props} />
+ {pagination && <Pagination {...pagination} />}
+ </>
+ );
};
diff --git a/config-ui/src/global.d.ts b/config-ui/src/global.d.ts
index 0f3a050aa..c65a6126b 100644
--- a/config-ui/src/global.d.ts
+++ b/config-ui/src/global.d.ts
@@ -18,6 +18,11 @@
type ID = string | number;
+type Pagination = {
+ page?: number;
+ pageSize?: number;
+};
+
declare module '*.svg' {
const content: any;
export default content;
diff --git a/config-ui/src/pages/blueprint/connection-detail/index.tsx
b/config-ui/src/pages/blueprint/connection-detail/index.tsx
index 2c66ce8cd..92a98708e 100644
--- a/config-ui/src/pages/blueprint/connection-detail/index.tsx
+++ b/config-ui/src/pages/blueprint/connection-detail/index.tsx
@@ -50,7 +50,7 @@ export const BlueprintConnectionDetailPage = () => {
const { ready, data } = useRefreshData(async () => {
const [plugin, connectionId] = unique.split('-');
- const [blueprint, connection, scopes] = await Promise.all([
+ const [blueprint, connection, scopesRes] = await Promise.all([
getBlueprint(pname, bid),
API.getConnection(plugin, connectionId),
API.getDataScopes(plugin, connectionId),
@@ -68,7 +68,7 @@ export const BlueprintConnectionDetailPage = () => {
id: +connectionId,
name: connection.name,
},
- scopes: scopes.filter((sc: any) =>
scopeIds.includes(getPluginScopeId(plugin, sc))),
+ scopes: scopesRes.scopes.filter((sc: any) =>
scopeIds.includes(getPluginScopeId(plugin, sc))),
};
}, [version, pname, bid]);
diff --git a/config-ui/src/pages/blueprint/home/api.ts
b/config-ui/src/pages/blueprint/home/api.ts
index 62e7c80ed..d6554b6aa 100644
--- a/config-ui/src/pages/blueprint/home/api.ts
+++ b/config-ui/src/pages/blueprint/home/api.ts
@@ -20,17 +20,12 @@ import { request } from '@/utils';
import { BlueprintType } from '../types';
-type GetBlueprintsParams = {
- page: number;
- pageSize: number;
-};
-
-type GetBlueprintResponse = {
+type ResponseType = {
blueprints: Array<BlueprintType>;
count: number;
};
-export const getBlueprints = (params: GetBlueprintsParams):
Promise<GetBlueprintResponse> =>
+export const getBlueprints = (params: Pagination & { type: string }):
Promise<ResponseType> =>
request('/blueprints', { data: params });
export const createBlueprint = (payload: any) =>
diff --git a/config-ui/src/pages/blueprint/home/index.tsx
b/config-ui/src/pages/blueprint/home/index.tsx
index f37e3d558..1541bb657 100644
--- a/config-ui/src/pages/blueprint/home/index.tsx
+++ b/config-ui/src/pages/blueprint/home/index.tsx
@@ -32,43 +32,37 @@ import * as API from './api';
import * as S from './styled';
export const BlueprintHomePage = () => {
- const [type, setType] = useState('all');
const [version, setVersion] = useState(1);
+ const [type, setType] = useState('all');
+ const [page, setPage] = useState(1);
+ const [pageSize] = useState(20);
const [isOpen, setIsOpen] = useState(false);
const [name, setName] = useState('');
const [mode, setMode] = useState(ModeEnum.normal);
const [saving, setSaving] = useState(false);
const { onGet } = useConnections();
- const { ready, data } = useRefreshData(() => API.getBlueprints({ page: 1,
pageSize: 200 }), [version]);
+ const { ready, data } = useRefreshData(
+ () => API.getBlueprints({ type: type.toLocaleUpperCase(), page, pageSize
}),
+ [version, type, page, pageSize],
+ );
const [options, presets] = useMemo(() => [getCronOptions(),
cronPresets.map((preset) => preset.config)], []);
- const dataSource = useMemo(
- () =>
- (data?.blueprints ?? [])
- .filter((it) => {
- switch (type) {
- case 'all':
- return true;
- case 'manual':
- return it.isManual;
- case 'custom':
- return !presets.includes(it.cronConfig);
- default:
- return !it.isManual && it.cronConfig === type;
- }
- })
- .map((it) => {
- const connections =
- it.settings?.connections
- .filter((cs) => cs.plugin !== 'webhook')
- .map((cs) => onGet(`${cs.plugin}-${cs.connectionId}`) ||
`${cs.plugin}-${cs.connectionId}`) ?? [];
- return {
- ...it,
- connections: connections.map((cs) => cs.name),
- };
- }),
- [data, type],
+ const [dataSource, total] = useMemo(
+ () => [
+ (data?.blueprints ?? []).map((it) => {
+ const connections =
+ it.settings?.connections
+ .filter((cs) => cs.plugin !== 'webhook')
+ .map((cs) => onGet(`${cs.plugin}-${cs.connectionId}`) ||
`${cs.plugin}-${cs.connectionId}`) ?? [];
+ return {
+ ...it,
+ connections: connections.map((cs) => cs.name),
+ };
+ }),
+ data?.count ?? 0,
+ ],
+ [data],
);
const handleShowDialog = () => setIsOpen(true);
@@ -123,12 +117,12 @@ export const BlueprintHomePage = () => {
<div className="action">
<ButtonGroup>
<Button intent={type === 'all' ? Intent.PRIMARY : Intent.NONE}
text="All" onClick={() => setType('all')} />
- {options.map(({ label, value }) => (
+ {options.map(({ label }) => (
<Button
- key={value}
- intent={type === value ? Intent.PRIMARY : Intent.NONE}
+ key={label}
+ intent={type === label ? Intent.PRIMARY : Intent.NONE}
text={label}
- onClick={() => setType(value)}
+ onClick={() => setType(label)}
/>
))}
</ButtonGroup>
@@ -221,6 +215,12 @@ export const BlueprintHomePage = () => {
},
]}
dataSource={dataSource}
+ pagination={{
+ page,
+ pageSize,
+ total,
+ onChange: setPage,
+ }}
noData={{
text: 'There is no Blueprint yet. Please add a new Blueprint here
or from a Project.',
btnText: 'New Blueprint',
diff --git a/config-ui/src/pages/connection/detail/api.ts
b/config-ui/src/pages/connection/detail/api.ts
index 23a7270ed..9b8a999a0 100644
--- a/config-ui/src/pages/connection/detail/api.ts
+++ b/config-ui/src/pages/connection/detail/api.ts
@@ -21,10 +21,11 @@ import { request } from '@/utils';
export const deleteConnection = (plugin: string, id: ID) =>
request(`/plugins/${plugin}/connections/${id}`, { method: 'delete' });
-export const getDataScopes = (plugin: string, id: ID) =>
+export const getDataScopes = (plugin: string, id: ID, payload: Pagination) =>
request(`/plugins/${plugin}/connections/${id}/scopes`, {
data: {
blueprints: true,
+ ...payload,
},
});
diff --git a/config-ui/src/pages/connection/detail/index.tsx
b/config-ui/src/pages/connection/detail/index.tsx
index dc8d3493e..1456a4409 100644
--- a/config-ui/src/pages/connection/detail/index.tsx
+++ b/config-ui/src/pages/connection/detail/index.tsx
@@ -60,6 +60,8 @@ const ConnectionDetail = ({ plugin, connectionId }: Props) =>
{
>();
const [operating, setOperating] = useState(false);
const [version, setVersion] = useState(1);
+ const [page, setPage] = useState(1);
+ const [pageSize] = useState(10);
const [scopeId, setScopeId] = useState<ID>();
const [scopeIds, setScopeIds] = useState<ID[]>([]);
const [scopeConfigId, setScopeConfigId] = useState<ID>();
@@ -69,12 +71,17 @@ const ConnectionDetail = ({ plugin, connectionId }: Props)
=> {
const navigate = useNavigate();
const { onGet, onTest, onRefresh } = useConnections();
const { setTips } = useTips();
- const { ready, data } = useRefreshData(() => API.getDataScopes(plugin,
connectionId), [version]);
+ const { ready, data } = useRefreshData(
+ () => API.getDataScopes(plugin, connectionId, { page, pageSize }),
+ [version, page, pageSize],
+ );
const { unique, status, name, icon } = onGet(`${plugin}-${connectionId}`) ||
{};
const pluginConfig = useMemo(() => getPluginConfig(plugin), [plugin]);
+ const [dataSource, total] = useMemo(() => [data?.scopes ?? [], data?.count
?? 0], [data]);
+
useEffect(() => {
onTest(`${plugin}-${connectionId}`);
}, [plugin, connectionId]);
@@ -322,7 +329,13 @@ const ConnectionDetail = ({ plugin, connectionId }: Props)
=> {
),
},
]}
- dataSource={data}
+ dataSource={dataSource}
+ pagination={{
+ page,
+ pageSize,
+ total,
+ onChange: setPage,
+ }}
noData={{
text: 'Add data to this connection.',
btnText: 'Add Data Scope',
@@ -383,7 +396,7 @@ const ConnectionDetail = ({ plugin, connectionId }: Props)
=> {
<DataScopeSelectRemote
plugin={plugin}
connectionId={connectionId}
- disabledScope={data}
+ disabledScope={dataSource}
onCancel={handleHideDialog}
onSubmit={handleCreateDataScope}
/>
diff --git a/config-ui/src/pages/project/home/api.ts
b/config-ui/src/pages/project/home/api.ts
index e8dea41c7..539e91b38 100644
--- a/config-ui/src/pages/project/home/api.ts
+++ b/config-ui/src/pages/project/home/api.ts
@@ -33,7 +33,7 @@ type GetProjectsResponse = {
blueprint: BlueprintType;
lastPipeline: PipelineType;
}>;
- counts: number;
+ count: number;
};
export const getProjects = (params: GetProjectsParams):
Promise<GetProjectsResponse> =>
diff --git a/config-ui/src/pages/project/home/index.tsx
b/config-ui/src/pages/project/home/index.tsx
index 49d61723b..c9dd39005 100644
--- a/config-ui/src/pages/project/home/index.tsx
+++ b/config-ui/src/pages/project/home/index.tsx
@@ -36,19 +36,21 @@ import * as S from './styled';
export const ProjectHomePage = () => {
const [version, setVersion] = useState(1);
+ const [page, setPage] = useState(1);
+ const [pageSize] = useState(20);
const [isOpen, setIsOpen] = useState(false);
const [name, setName] = useState('');
const [enableDora, setEnableDora] = useState(true);
const [saving, setSaving] = useState(false);
- const { ready, data } = useRefreshData(() => API.getProjects({ page: 1,
pageSize: 200 }), [version]);
+ const { ready, data } = useRefreshData(() => API.getProjects({ page,
pageSize }), [version, page, pageSize]);
const { onGet } = useConnections();
const navigate = useNavigate();
const presets = useMemo(() => cronPresets.map((preset) => preset.config),
[]);
- const dataSource = useMemo(
- () =>
+ const [dataSource, total] = useMemo(
+ () => [
(data?.projects ?? []).map((it) => {
return {
name: it.name,
@@ -60,6 +62,8 @@ export const ProjectHomePage = () => {
lastRunStatus: it.lastPipeline?.status,
};
}),
+ data?.count ?? 0,
+ ],
[data],
);
@@ -190,6 +194,12 @@ export const ProjectHomePage = () => {
},
]}
dataSource={dataSource}
+ pagination={{
+ page,
+ pageSize,
+ total,
+ onChange: setPage,
+ }}
noData={{
text: 'Add new projects to see engineering metrics based on
projects.',
btnText: 'New Project',
diff --git a/config-ui/src/plugins/components/data-scope-select/api.ts
b/config-ui/src/plugins/components/data-scope-select/api.ts
index a6b1cb541..941dcbdc7 100644
--- a/config-ui/src/plugins/components/data-scope-select/api.ts
+++ b/config-ui/src/plugins/components/data-scope-select/api.ts
@@ -19,10 +19,15 @@
import { request } from '@/utils';
type ParamsType = {
- searchTerm: string;
+ searchTerm?: string;
+} & Pagination;
+
+type ResponseType = {
+ scopes: Array<{ name: string }>;
+ count: number;
};
-export const getDataScope = (plugin: string, connectionId: ID, params?:
ParamsType) =>
+export const getDataScope = (plugin: string, connectionId: ID, params?:
ParamsType): Promise<ResponseType> =>
request(`/plugins/${plugin}/connections/${connectionId}/scopes`, {
data: params,
});
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 145e87778..fdf64de6d 100644
--- a/config-ui/src/plugins/components/data-scope-select/index.tsx
+++ b/config-ui/src/plugins/components/data-scope-select/index.tsx
@@ -16,11 +16,13 @@
*
*/
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useMemo } from 'react';
import { Button, Intent } from '@blueprintjs/core';
import { useDebounce } from 'ahooks';
+import type { McsID, McsItem } from 'miller-columns-select';
+import MillerColumnsSelect from 'miller-columns-select';
-import { PageLoading, FormItem, ExternalLink, Message, Buttons, MultiSelector,
Table } from '@/components';
+import { FormItem, ExternalLink, Message, Buttons, MultiSelector } from
'@/components';
import { useRefreshData } from '@/hooks';
import { getPluginScopeId } from '@/plugins';
@@ -44,38 +46,59 @@ export const DataScopeSelect = ({
onSubmit,
onCancel,
}: Props) => {
- const [version, setVersion] = useState(1);
- const [scopeIds, setScopeIds] = useState<ID[]>([]);
const [query, setQuery] = useState('');
+ const [items, setItems] = useState<McsItem<{ data: any }>[]>([]);
+ const [selectedItems, setSelecteItems] = useState<any>([]);
+ const [page, setPage] = useState(1);
+ const [pageSize] = useState(10);
+ const [total, setTotal] = useState(0);
useEffect(() => {
- setScopeIds((initialScope ?? []).map((sc: any) => getPluginScopeId(plugin,
sc)) ?? []);
+ setSelecteItems(initialScope ?? []);
}, []);
+ const selectedIds = useMemo(() => selectedItems.map((it: any) =>
getPluginScopeId(plugin, it)), [selectedItems]);
+
+ const handleChangeSelectItemsIds = (ids: McsID[]) => {
+ setSelecteItems(items.filter((it) => ids.includes(it.id)).map((it) =>
it.data));
+ };
+
+ const getDataScope = async (page: number) => {
+ const res = await API.getDataScope(plugin, connectionId, { page, pageSize
});
+ setItems([
+ ...items,
+ ...res.scopes.map((sc) => ({
+ parentId: null,
+ id: getPluginScopeId(plugin, sc),
+ title: sc.name,
+ data: sc,
+ })),
+ ]);
+ if (page === 1) {
+ setTotal(res.count);
+ }
+ };
+
+ useEffect(() => {
+ getDataScope(page);
+ }, [page]);
+
const search = useDebounce(query, { wait: 500 });
- const { ready, data } = useRefreshData(() => API.getDataScope(plugin,
connectionId), [version]);
- const { ready: searchReady, data: searchItems } = useRefreshData<[{ name:
string }]>(
+ const { ready, data } = useRefreshData(
() => API.getDataScope(plugin, connectionId, { searchTerm: search }),
[search],
);
- const handleRefresh = () => setVersion((v) => v + 1);
-
- const handleSubmit = () => {
- const scope = data.filter((it: any) =>
scopeIds.includes(getPluginScopeId(plugin, it)));
- onSubmit?.(scope);
- };
+ const handleScroll = () => setPage(page + 1);
- if (!ready || !data) {
- return <PageLoading />;
- }
+ const handleSubmit = () => onSubmit?.(selectedItems);
return (
<FormItem
label="Select Data Scope"
subLabel={
- data.length ? (
+ items.length ? (
<>
Select the data scope in this Connection that you wish to
associate with this Project. If you wish to add
more Data Scope to this Connection, please{' '}
@@ -93,7 +116,7 @@ export const DataScopeSelect = ({
}
required
>
- {data.length ? (
+ {items.length ? (
<S.Wrapper>
{showWarning ? (
<Message
@@ -109,48 +132,34 @@ export const DataScopeSelect = ({
/>
) : (
<Buttons>
- <Button intent={Intent.PRIMARY} icon="refresh" text="Refresh
Data Scope" onClick={handleRefresh} />
+ <Button intent={Intent.PRIMARY} icon="refresh" text="Refresh
Data Scope" />
</Buttons>
)}
<div className="search">
<MultiSelector
- loading={!searchReady}
- items={searchItems ?? []}
+ loading={!ready}
+ items={data?.scopes ?? []}
getName={(it: any) => it.name}
getKey={(it) => getPluginScopeId(plugin, it)}
noResult="No Data Scopes Available."
onQueryChange={(query) => setQuery(query)}
- selectedItems={data.filter((it: any) =>
scopeIds.includes(getPluginScopeId(plugin, it))) ?? []}
- onChangeItems={(items) => setScopeIds(items.map((it: any) =>
getPluginScopeId(plugin, it)))}
+ selectedItems={selectedItems}
+ onChangeItems={setSelecteItems}
/>
</div>
- <Table
- noShadow
- loading={!ready}
- columns={[
- {
- title: 'Data Scope',
- dataIndex: 'name',
- key: 'name',
- },
- {
- title: 'Scope Config',
- dataIndex: 'scopeConfig',
- key: 'scopeConfig',
- render: (_, row) => (row.scopeConfigId ? row.scopeConfig?.name
: 'N/A'),
- },
- ]}
- dataSource={data}
- rowSelection={{
- getRowKey: (data) => getPluginScopeId(plugin, data),
- type: 'checkbox',
- selectedRowKeys: scopeIds as string[],
- onChange: (selectedRowKeys) => setScopeIds(selectedRowKeys),
- }}
+ <MillerColumnsSelect
+ showSelectAll
+ columnCount={1}
+ columnHeight={200}
+ items={items}
+ getHasMore={() => items.length < total}
+ onScroll={handleScroll}
+ selectedIds={selectedIds}
+ onSelectItemIds={handleChangeSelectItemsIds}
/>
<Buttons position="bottom" align="right">
<Button outlined intent={Intent.PRIMARY} text="Cancel"
onClick={onCancel} />
- <Button disabled={!scopeIds.length} intent={Intent.PRIMARY}
text="Save" onClick={handleSubmit} />
+ <Button disabled={!selectedItems.length} intent={Intent.PRIMARY}
text="Save" onClick={handleSubmit} />
</Buttons>
</S.Wrapper>
) : (