Skip to content

Commit 70c7151

Browse files
claudeironAiken2
authored andcommitted
fix(FR-2824): move CSV export to BAITable bottom-right in resource policy lists
1 parent 82d550b commit 70c7151

3 files changed

Lines changed: 125 additions & 250 deletions

File tree

react/src/components/KeypairResourcePolicyList.tsx

Lines changed: 42 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,17 @@ import { KeypairResourcePolicySettingModalFragment$key } from '../__generated__/
1212
import { localeCompare, numberSorterWithInfinityValue } from '../helper';
1313
import { SIGNED_32BIT_MAX_INT } from '../helper/const-vars';
1414
import { exportCSVWithFormattingRules } from '../helper/csv-util';
15-
import { useHiddenColumnKeysSetting } from '../hooks/useHiddenColumnKeysSetting';
15+
import { useBAISettingUserState } from '../hooks/useBAISetting';
1616
import KeypairResourcePolicyInfoModal from './KeypairResourcePolicyInfoModal';
1717
import KeypairResourcePolicySettingModal from './KeypairResourcePolicySettingModal';
18-
import TableColumnsSettingModal from './TableColumnsSettingModal';
1918
import {
2019
DeleteFilled,
2120
InfoCircleOutlined,
2221
PlusOutlined,
2322
ReloadOutlined,
2423
SettingOutlined,
2524
} from '@ant-design/icons';
26-
import { useToggle } from 'ahooks';
27-
import { App, Button, Dropdown, Tooltip } from 'antd';
25+
import { App, Button, Tooltip } from 'antd';
2826
import { AnyObject } from 'antd/es/_util/type';
2927
import type { ColumnsType, ColumnType } from 'antd/es/table';
3028
import {
@@ -38,7 +36,6 @@ import {
3836
BAIDeleteConfirmModal,
3937
} from 'backend.ai-ui';
4038
import * as _ from 'lodash-es';
41-
import { EllipsisIcon } from 'lucide-react';
4239
import React, { Suspense, useState, useTransition } from 'react';
4340
import { useTranslation } from 'react-i18next';
4441
import { graphql, useLazyLoadQuery, useMutation } from 'react-relay';
@@ -58,8 +55,6 @@ const KeypairResourcePolicyList: React.FC<KeypairResourcePolicyListProps> = (
5855
const [keypairResourcePolicyFetchKey, updateKeypairResourcePolicyFetchKey] =
5956
useUpdatableState('initial-fetch');
6057
const [isRefetchPending, startRefetchTransition] = useTransition();
61-
const [visibleColumnSettingModal, { toggle: toggleColumnSettingModal }] =
62-
useToggle();
6358
const [isCreatingPolicySetting, setIsCreatingPolicySetting] = useState(false);
6459
const [editingKeypairResourcePolicy, setEditingKeypairResourcePolicy] =
6560
useState<KeypairResourcePolicySettingModalFragment$key | null>();
@@ -263,21 +258,28 @@ const KeypairResourcePolicyList: React.FC<KeypairResourcePolicyListProps> = (
263258
},
264259
]);
265260

266-
const [hiddenColumnKeys, setHiddenColumnKeys] = useHiddenColumnKeysSetting(
267-
'KeypairResourcePolicyList',
261+
const [columnOverrides, setColumnOverrides] = useBAISettingUserState(
262+
'table_column_overrides.KeypairResourcePolicyList',
268263
);
269264

270-
const handleExportCSV = () => {
265+
const supportedFields = _.compact(
266+
_.map(columns, (column) => _.toString(column.key)),
267+
);
268+
269+
const handleExportCSV = (selectedExportKeys: string[]) => {
270+
if (selectedExportKeys.length === 0) {
271+
message.error(t('resourcePolicy.NoDataToExport'));
272+
return;
273+
}
271274
if (!keypair_resource_policies) {
272275
message.error(t('resourcePolicy.NoDataToExport'));
273276
return;
274277
}
275278

276-
const columnKeys = _.map(columns, (column) => _.toString(column.key));
277279
const responseData = _.map(keypair_resource_policies, (policy) => {
278280
return _.pick(
279281
policy,
280-
columnKeys.map((key) => key as keyof KeypairResourcePolicies),
282+
selectedExportKeys.map((key) => key as keyof KeypairResourcePolicies),
281283
);
282284
});
283285

@@ -301,91 +303,47 @@ const KeypairResourcePolicyList: React.FC<KeypairResourcePolicyListProps> = (
301303
return (
302304
<BAIFlex direction="column" align="stretch" gap="sm" {...props}>
303305
<BAIFlex direction="row" justify="end" wrap="wrap" gap={'xs'}>
304-
<Dropdown
305-
menu={{
306-
items: [
307-
{
308-
key: 'exportCSV',
309-
label: t('resourcePolicy.ExportCSV'),
310-
onClick: () => {
311-
handleExportCSV();
312-
},
313-
},
314-
],
315-
}}
316-
trigger={['click']}
317-
>
318-
<Button icon={<EllipsisIcon />} />
319-
</Dropdown>
320-
<BAIFlex
321-
direction="row"
322-
gap={'xs'}
323-
wrap="wrap"
324-
style={{ flexShrink: 1 }}
325-
>
326-
<BAIFlex gap={'xs'}>
327-
<Tooltip title={t('button.Refresh')}>
328-
<Button
329-
icon={<ReloadOutlined />}
330-
loading={isRefetchPending}
331-
onClick={() => {
332-
startRefetchTransition(() =>
333-
updateKeypairResourcePolicyFetchKey(),
334-
);
335-
}}
336-
/>
337-
</Tooltip>
306+
<BAIFlex gap={'xs'}>
307+
<Tooltip title={t('button.Refresh')}>
338308
<Button
339-
type="primary"
340-
icon={<PlusOutlined />}
309+
icon={<ReloadOutlined />}
310+
loading={isRefetchPending}
341311
onClick={() => {
342-
setIsCreatingPolicySetting(true);
312+
startRefetchTransition(() =>
313+
updateKeypairResourcePolicyFetchKey(),
314+
);
343315
}}
344-
>
345-
{t('button.Create')}
346-
</Button>
347-
</BAIFlex>
316+
/>
317+
</Tooltip>
318+
<Button
319+
type="primary"
320+
icon={<PlusOutlined />}
321+
onClick={() => {
322+
setIsCreatingPolicySetting(true);
323+
}}
324+
>
325+
{t('button.Create')}
326+
</Button>
348327
</BAIFlex>
349328
</BAIFlex>
350329
<BAITable
351-
columns={
352-
_.filter(
353-
columns,
354-
(column) => !_.includes(hiddenColumnKeys, _.toString(column?.key)),
355-
) as ColumnType<AnyObject>[]
356-
}
330+
columns={columns as ColumnType<AnyObject>[]}
357331
dataSource={
358332
keypair_resource_policies as readonly AnyObject[] | undefined
359333
}
360334
rowKey="name"
361335
scroll={{ x: 'max-content' }}
362-
pagination={{
363-
extraContent: (
364-
<Button
365-
type="text"
366-
icon={<SettingOutlined />}
367-
onClick={() => {
368-
toggleColumnSettingModal();
369-
}}
370-
/>
371-
),
372-
}}
373336
showSorterTooltip={false}
374-
/>
375-
<TableColumnsSettingModal
376-
open={visibleColumnSettingModal}
377-
onRequestClose={(values) => {
378-
values?.selectedColumnKeys &&
379-
setHiddenColumnKeys(
380-
_.difference(
381-
columns.map((column) => _.toString(column.key)),
382-
values?.selectedColumnKeys,
383-
),
384-
);
385-
toggleColumnSettingModal();
337+
tableSettings={{
338+
columnOverrides: columnOverrides,
339+
onColumnOverridesChange: setColumnOverrides,
340+
}}
341+
exportSettings={{
342+
supportedFields,
343+
onExport: async (selectedExportKeys) => {
344+
handleExportCSV(selectedExportKeys);
345+
},
386346
}}
387-
columns={columns}
388-
hiddenColumnKeys={hiddenColumnKeys}
389347
/>
390348
<Suspense>
391349
<KeypairResourcePolicySettingModal

react/src/components/ProjectResourcePolicyList.tsx

Lines changed: 41 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,15 @@ import {
1515
} from '../helper';
1616
import { exportCSVWithFormattingRules } from '../helper/csv-util';
1717
import { useSuspendedBackendaiClient } from '../hooks';
18-
import { useHiddenColumnKeysSetting } from '../hooks/useHiddenColumnKeysSetting';
18+
import { useBAISettingUserState } from '../hooks/useBAISetting';
1919
import ProjectResourcePolicySettingModal from './ProjectResourcePolicySettingModal';
20-
import TableColumnsSettingModal from './TableColumnsSettingModal';
2120
import {
2221
DeleteFilled,
2322
PlusOutlined,
2423
ReloadOutlined,
2524
SettingOutlined,
2625
} from '@ant-design/icons';
27-
import { useToggle } from 'ahooks';
28-
import { App, Button, Dropdown, Tooltip } from 'antd';
26+
import { App, Button, Tooltip } from 'antd';
2927
import type { ColumnType } from 'antd/es/table';
3028
import {
3129
filterOutEmpty,
@@ -38,7 +36,6 @@ import {
3836
} from 'backend.ai-ui';
3937
import dayjs from 'dayjs';
4038
import * as _ from 'lodash-es';
41-
import { EllipsisIcon } from 'lucide-react';
4239
import React, { useState, useTransition } from 'react';
4340
import { useTranslation } from 'react-i18next';
4441
import { graphql, useLazyLoadQuery, useMutation } from 'react-relay';
@@ -60,8 +57,6 @@ const ProjectResourcePolicyList: React.FC<
6057
const [projectResourcePolicyFetchKey, updateProjectResourcePolicyFetchKey] =
6158
useUpdatableState('initial-fetch');
6259
const [isCreatingPolicySetting, setIsCreatingPolicySetting] = useState(false);
63-
const [visibleColumnSettingModal, { toggle: toggleColumnSettingModal }] =
64-
useToggle();
6560
const [editingProjectResourcePolicy, setEditingProjectResourcePolicy] =
6661
useState<ProjectResourcePolicySettingModalFragment$key | null>();
6762
const [deletingPolicyName, setDeletingPolicyName] = useState<string | null>(
@@ -190,21 +185,28 @@ const ProjectResourcePolicyList: React.FC<
190185
},
191186
]);
192187

193-
const [hiddenColumnKeys, setHiddenColumnKeys] = useHiddenColumnKeysSetting(
194-
'ProjectResourcePolicyList',
188+
const [columnOverrides, setColumnOverrides] = useBAISettingUserState(
189+
'table_column_overrides.ProjectResourcePolicyList',
195190
);
196191

197-
const handleExportCSV = () => {
192+
const supportedFields = _.compact(
193+
_.map(columns, (column) => _.toString(column.key)),
194+
);
195+
196+
const handleExportCSV = (selectedExportKeys: string[]) => {
197+
if (selectedExportKeys.length === 0) {
198+
message.error(t('resourcePolicy.NoDataToExport'));
199+
return;
200+
}
198201
if (!project_resource_policies) {
199202
message.error(t('resourcePolicy.NoDataToExport'));
200203
return;
201204
}
202205

203-
const columnkeys = _.map(columns, (column) => _.toString(column.key));
204206
const responseData = _.map(project_resource_policies, (policy) => {
205207
return _.pick(
206208
policy,
207-
columnkeys.map((key) => key as keyof ProjectResourcePolicies),
209+
selectedExportKeys.map((key) => key as keyof ProjectResourcePolicies),
208210
);
209211
});
210212
exportCSVWithFormattingRules(
@@ -221,87 +223,45 @@ const ProjectResourcePolicyList: React.FC<
221223
return (
222224
<BAIFlex direction="column" align="stretch" gap="sm">
223225
<BAIFlex direction="row" justify="end" wrap="wrap" gap={'xs'}>
224-
<BAIFlex
225-
direction="row"
226-
gap={'xs'}
227-
wrap="wrap"
228-
style={{ flexShrink: 1 }}
229-
>
230-
<Dropdown
231-
menu={{
232-
items: [
233-
{
234-
key: 'exportCSV',
235-
label: t('resourcePolicy.ExportCSV'),
236-
onClick: () => {
237-
handleExportCSV();
238-
},
239-
},
240-
],
241-
}}
242-
trigger={['click']}
243-
>
244-
<Button icon={<EllipsisIcon />} />
245-
</Dropdown>
246-
<BAIFlex gap={'xs'}>
247-
<Tooltip title={t('button.Refresh')}>
248-
<Button
249-
icon={<ReloadOutlined />}
250-
loading={isRefetchPending}
251-
onClick={() => {
252-
startRefetchTransition(() =>
253-
updateProjectResourcePolicyFetchKey(),
254-
);
255-
}}
256-
/>
257-
</Tooltip>
226+
<BAIFlex gap={'xs'}>
227+
<Tooltip title={t('button.Refresh')}>
258228
<Button
259-
type="primary"
260-
icon={<PlusOutlined />}
229+
icon={<ReloadOutlined />}
230+
loading={isRefetchPending}
261231
onClick={() => {
262-
setIsCreatingPolicySetting(true);
232+
startRefetchTransition(() =>
233+
updateProjectResourcePolicyFetchKey(),
234+
);
263235
}}
264-
>
265-
{t('button.Create')}
266-
</Button>
267-
</BAIFlex>
236+
/>
237+
</Tooltip>
238+
<Button
239+
type="primary"
240+
icon={<PlusOutlined />}
241+
onClick={() => {
242+
setIsCreatingPolicySetting(true);
243+
}}
244+
>
245+
{t('button.Create')}
246+
</Button>
268247
</BAIFlex>
269248
</BAIFlex>
270249
<BAITable
271250
rowKey="id"
272251
showSorterTooltip={false}
273-
columns={_.filter(
274-
columns,
275-
(column) => !_.includes(hiddenColumnKeys, _.toString(column?.key)),
276-
)}
252+
columns={columns}
277253
dataSource={filterOutNullAndUndefined(project_resource_policies)}
278254
scroll={{ x: 'max-content' }}
279-
pagination={{
280-
extraContent: (
281-
<Button
282-
type="text"
283-
icon={<SettingOutlined />}
284-
onClick={() => {
285-
toggleColumnSettingModal();
286-
}}
287-
/>
288-
),
255+
tableSettings={{
256+
columnOverrides: columnOverrides,
257+
onColumnOverridesChange: setColumnOverrides,
289258
}}
290-
/>
291-
<TableColumnsSettingModal
292-
open={visibleColumnSettingModal}
293-
onRequestClose={(values) => {
294-
values?.selectedColumnKeys &&
295-
setHiddenColumnKeys(
296-
_.difference(
297-
columns.map((column) => _.toString(column.key)),
298-
values?.selectedColumnKeys,
299-
),
300-
);
301-
toggleColumnSettingModal();
259+
exportSettings={{
260+
supportedFields,
261+
onExport: async (selectedExportKeys) => {
262+
handleExportCSV(selectedExportKeys);
263+
},
302264
}}
303-
columns={columns}
304-
hiddenColumnKeys={hiddenColumnKeys}
305265
/>
306266
<ProjectResourcePolicySettingModal
307267
existingPolicyNames={_.map(project_resource_policies, 'name')}

0 commit comments

Comments
 (0)