@boarteam/boar-pack-common-frontend 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/components/Descriptions/Descriptions.tsx +198 -46
- package/src/components/Descriptions/DescriptionsCreateModal.tsx +1 -1
- package/src/components/Descriptions/descriptionTypes.ts +20 -6
- package/src/components/Descriptions/useContentViewMode.tsx +28 -0
- package/src/components/Descriptions/useDescriptionColumns.ts +6 -1
- package/src/components/Table/BulkDeleteButton.tsx +2 -2
- package/src/components/Table/BulkEditButton.tsx +2 -2
- package/src/components/Table/CreateEntityModal.tsx +85 -0
- package/src/components/Table/DeleteButton.tsx +44 -0
- package/src/components/Table/Table.tsx +103 -266
- package/src/components/Table/getTableDataQueryParams.ts +79 -0
- package/src/components/Table/index.ts +1 -0
- package/src/components/Table/tableTools.ts +3 -2
- package/src/components/Table/tableTypes.ts +16 -9
- package/src/components/Table/useBulkEditing.tsx +128 -0
- package/src/components/Table/useCreation.tsx +96 -0
- package/src/components/Table/useEditableTable.tsx +84 -0
|
@@ -1,30 +1,14 @@
|
|
|
1
1
|
import ProTable, { ActionType } from "@ant-design/pro-table";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
|
-
import { flushSync } from "react-dom";
|
|
7
|
-
import { applyKeywordToSearch, buildJoinFields, collectFieldsFromColumns, getFiltersSearch } from "./tableTools";
|
|
8
|
-
import { TFilterParams, TFilters, TGetAllParams, TSort, TTableProps } from "./tableTypes";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Modal } from "antd";
|
|
4
|
+
import { TFilterParams, TFilters, TSort, TTableProps } from "./tableTypes";
|
|
9
5
|
import useColumnsSets from "./useColumnsSets";
|
|
10
|
-
import DescriptionsCreateModal from "../Descriptions/DescriptionsCreateModal";
|
|
11
|
-
import BulkEditButton from "./BulkEditButton";
|
|
12
|
-
import _ from "lodash";
|
|
13
|
-
import BulkDeleteButton from "./BulkDeleteButton";
|
|
14
6
|
import { createStyles } from "antd-style";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export function getNewId(): string {
|
|
22
|
-
return NEW_RECORD + creatingRecordsCount++;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function isRecordNew(record: Record<string | symbol, any>): boolean {
|
|
26
|
-
return record[KEY_SYMBOL]?.startsWith?.(NEW_RECORD) || record.id?.startsWith?.(NEW_RECORD) || false;
|
|
27
|
-
}
|
|
7
|
+
import { Descriptions } from "../Descriptions";
|
|
8
|
+
import { KEY_SYMBOL, useCreation } from "./useCreation";
|
|
9
|
+
import { getTableDataQueryParams } from "./getTableDataQueryParams";
|
|
10
|
+
import { useEditableTable } from "./useEditableTable";
|
|
11
|
+
import { useBulkEditing } from "./useBulkEditing";
|
|
28
12
|
|
|
29
13
|
const useStyles = createStyles(() => {
|
|
30
14
|
return {
|
|
@@ -42,7 +26,7 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
42
26
|
TEntityParams = {},
|
|
43
27
|
TPathParams extends Record<string, string | number> = {},
|
|
44
28
|
TKey = string,
|
|
45
|
-
|
|
29
|
+
>(
|
|
46
30
|
{
|
|
47
31
|
getAll,
|
|
48
32
|
onCreate,
|
|
@@ -55,6 +39,7 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
55
39
|
entityToCreateDto,
|
|
56
40
|
entityToUpdateDto,
|
|
57
41
|
createNewDefaultParams,
|
|
42
|
+
editableRecord,
|
|
58
43
|
afterSave,
|
|
59
44
|
actionRef: actionRefProp,
|
|
60
45
|
editable,
|
|
@@ -68,7 +53,9 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
68
53
|
popupCreation = false,
|
|
69
54
|
toolBarRender,
|
|
70
55
|
params,
|
|
71
|
-
|
|
56
|
+
editPopupTitle,
|
|
57
|
+
createPopupTitle,
|
|
58
|
+
descriptionsMainTitle,
|
|
72
59
|
...rest
|
|
73
60
|
}: TTableProps<Entity,
|
|
74
61
|
CreateDto,
|
|
@@ -78,19 +65,63 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
78
65
|
) => {
|
|
79
66
|
const actionRefComponent = useRef<ActionType>();
|
|
80
67
|
const actionRef = actionRefProp || actionRefComponent;
|
|
81
|
-
const [
|
|
82
|
-
const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
|
|
83
|
-
const [selectedRecords, setSelectedRecords] = useState<Entity[]>([]);
|
|
84
|
-
const [lastRequest, setLastRequest] = useState<[TGetAllParams & TPathParams, any] | []>([]);
|
|
85
|
-
const [allSelected, setAllSelected] = useState(false);
|
|
68
|
+
const [updatePopupData, setUpdatePopupData] = useState<Partial<Entity> | undefined>();
|
|
86
69
|
const { styles } = useStyles();
|
|
87
|
-
const [messageApi, contextHolder] = message.useMessage();
|
|
88
70
|
|
|
89
|
-
const
|
|
71
|
+
const {
|
|
72
|
+
editableConfig,
|
|
73
|
+
} = useEditableTable<Entity, CreateDto, UpdateDto, TPathParams>({
|
|
74
|
+
actionRef,
|
|
75
|
+
pathParams,
|
|
76
|
+
onCreate,
|
|
77
|
+
onUpdate,
|
|
78
|
+
onDelete,
|
|
79
|
+
entityToCreateDto,
|
|
80
|
+
entityToUpdateDto,
|
|
81
|
+
afterSave,
|
|
82
|
+
editable,
|
|
83
|
+
onDeleteMany,
|
|
84
|
+
onUpdateMany,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const {
|
|
88
|
+
rowSelection,
|
|
89
|
+
setSelectedRecords,
|
|
90
|
+
setLastRequest,
|
|
91
|
+
bulkEditButton,
|
|
92
|
+
bulkDeleteButton,
|
|
93
|
+
messagesContext,
|
|
94
|
+
} = useBulkEditing<Entity, TPathParams, UpdateDto, TEntityParams & TFilterParams>({
|
|
95
|
+
actionRef,
|
|
96
|
+
columns,
|
|
97
|
+
idColumnName,
|
|
98
|
+
onDeleteMany,
|
|
99
|
+
onUpdateMany,
|
|
100
|
+
entityToUpdateDto,
|
|
101
|
+
pathParams,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const {
|
|
105
|
+
creationModal,
|
|
106
|
+
createButton,
|
|
107
|
+
} = useCreation<Entity, CreateDto, TPathParams>({
|
|
108
|
+
title: createPopupTitle,
|
|
109
|
+
mainTitle: descriptionsMainTitle,
|
|
110
|
+
columns: columns,
|
|
111
|
+
idColumnName: idColumnName,
|
|
112
|
+
onCreate,
|
|
113
|
+
pathParams,
|
|
114
|
+
entityToCreateDto,
|
|
115
|
+
actionRef,
|
|
116
|
+
createButtonSize: rest.size,
|
|
117
|
+
popupCreation,
|
|
118
|
+
createNewDefaultParams,
|
|
119
|
+
});
|
|
90
120
|
|
|
91
121
|
useEffect(() => {
|
|
122
|
+
setUpdatePopupData(editableRecord);
|
|
92
123
|
actionRef?.current?.reload();
|
|
93
|
-
}, [JSON.stringify(pathParams), JSON.stringify(params)]);
|
|
124
|
+
}, [editableRecord, JSON.stringify(pathParams), JSON.stringify(params)]);
|
|
94
125
|
|
|
95
126
|
const {
|
|
96
127
|
columnsSetSelect: localColumnsSetSelect,
|
|
@@ -108,55 +139,17 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
108
139
|
sort: TSort = {},
|
|
109
140
|
filters: TFilters = {},
|
|
110
141
|
) => {
|
|
111
|
-
const {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
sortMap,
|
|
118
|
-
...filtersFromSearchForm
|
|
119
|
-
} = params;
|
|
120
|
-
|
|
121
|
-
const queryParams: TGetAllParams & TPathParams = {
|
|
122
|
-
...pathParams,
|
|
123
|
-
page: current,
|
|
124
|
-
limit: pageSize,
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const sortBy = Object
|
|
128
|
-
.entries(sort)
|
|
129
|
-
.reduce<string[]>(
|
|
130
|
-
(data: string[], [key, direction]) => {
|
|
131
|
-
data.push(`${sortMap?.[key] || key},${direction === 'ascend' ? 'ASC' : 'DESC'}`);
|
|
132
|
-
return data;
|
|
133
|
-
},
|
|
134
|
-
[]
|
|
135
|
-
);
|
|
136
|
-
if (!sortBy.length && defaultSort) {
|
|
137
|
-
sortBy.push(defaultSort.join(','));
|
|
138
|
-
}
|
|
139
|
-
queryParams.sort = sortBy;
|
|
140
|
-
|
|
141
|
-
let search = getFiltersSearch({
|
|
142
|
-
baseFilters,
|
|
143
|
-
filters: {
|
|
144
|
-
...filters,
|
|
145
|
-
...filtersFromSearchForm,
|
|
146
|
-
},
|
|
142
|
+
const queryParams = getTableDataQueryParams({
|
|
143
|
+
params,
|
|
144
|
+
sort,
|
|
145
|
+
filters,
|
|
146
|
+
pathParams,
|
|
147
|
+
defaultSort,
|
|
147
148
|
searchableColumns,
|
|
148
|
-
});
|
|
149
|
-
search = applyKeywordToSearch(search, searchableColumns!, columnsState.value!, keyword);
|
|
150
|
-
queryParams.s = JSON.stringify(search);
|
|
151
|
-
|
|
152
|
-
const { joinSelect, joinFields } = buildJoinFields(join);
|
|
153
|
-
queryParams.join = joinSelect;
|
|
154
|
-
|
|
155
|
-
queryParams.fields = columns && collectFieldsFromColumns(
|
|
156
149
|
columns,
|
|
157
150
|
idColumnName,
|
|
158
|
-
|
|
159
|
-
)
|
|
151
|
+
columnsState,
|
|
152
|
+
});
|
|
160
153
|
|
|
161
154
|
const result = await getAll(queryParams);
|
|
162
155
|
|
|
@@ -168,26 +161,6 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
168
161
|
return result;
|
|
169
162
|
}
|
|
170
163
|
|
|
171
|
-
const createButton = <Button
|
|
172
|
-
size={rest.size}
|
|
173
|
-
type="primary"
|
|
174
|
-
key="create"
|
|
175
|
-
onClick={() => {
|
|
176
|
-
if (popupCreation) {
|
|
177
|
-
setCreatePopupData(createNewDefaultParams);
|
|
178
|
-
} else {
|
|
179
|
-
actionRef?.current?.addEditRecord({
|
|
180
|
-
[KEY_SYMBOL]: getNewId(),
|
|
181
|
-
...createNewDefaultParams,
|
|
182
|
-
}, {
|
|
183
|
-
position: 'top',
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
}}
|
|
187
|
-
>
|
|
188
|
-
<PlusOutlined /> <FormattedMessage id={'table.newButton'} />
|
|
189
|
-
</Button>;
|
|
190
|
-
|
|
191
164
|
return (<>
|
|
192
165
|
<ProTable<Entity, TEntityParams & TFilterParams>
|
|
193
166
|
actionRef={actionRef}
|
|
@@ -210,119 +183,17 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
210
183
|
}}
|
|
211
184
|
bordered
|
|
212
185
|
search={false}
|
|
213
|
-
editable={
|
|
214
|
-
type: 'multiple',
|
|
215
|
-
editableKeys,
|
|
216
|
-
onChange: setEditableRowKeys,
|
|
217
|
-
async onSave(
|
|
218
|
-
id,
|
|
219
|
-
record,
|
|
220
|
-
origin,
|
|
221
|
-
newLine,
|
|
222
|
-
) {
|
|
223
|
-
if (newLine) {
|
|
224
|
-
await onCreate?.({
|
|
225
|
-
...pathParams,
|
|
226
|
-
requestBody: entityToCreateDto(record),
|
|
227
|
-
});
|
|
228
|
-
} else {
|
|
229
|
-
await onUpdate({
|
|
230
|
-
...pathParams,
|
|
231
|
-
...record,
|
|
232
|
-
requestBody: entityToUpdateDto({
|
|
233
|
-
...pathParams,
|
|
234
|
-
...record,
|
|
235
|
-
}),
|
|
236
|
-
})
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (typeof afterSave === 'function') {
|
|
240
|
-
await afterSave(record);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
flushSync(() => {
|
|
244
|
-
actionRef?.current?.reload();
|
|
245
|
-
});
|
|
246
|
-
},
|
|
247
|
-
async onCancel(
|
|
248
|
-
id,
|
|
249
|
-
record,
|
|
250
|
-
origin,
|
|
251
|
-
) {
|
|
252
|
-
if (record) {
|
|
253
|
-
Object.assign(record, origin);
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
async onDelete(id, row) {
|
|
257
|
-
await onDelete({ ...row, ...pathParams });
|
|
258
|
-
},
|
|
259
|
-
deletePopconfirmMessage: intl.formatMessage({ id: 'table.deletePopconfirmMessage' }),
|
|
260
|
-
onlyAddOneLineAlertMessage: intl.formatMessage({ id: 'table.onlyAddOneLineAlertMessage' }),
|
|
261
|
-
cancelText: <Tooltip title={intl.formatMessage({ id: 'table.cancelText' })}><StopOutlined /></Tooltip>,
|
|
262
|
-
deleteText: <Tooltip title={intl.formatMessage({ id: 'table.deleteText' })}><DeleteOutlined /></Tooltip>,
|
|
263
|
-
saveText: <Button size={"small"} type={"primary"}><FormattedMessage id={'table.saveText'} /></Button>,
|
|
264
|
-
...editable,
|
|
265
|
-
}}
|
|
186
|
+
editable={editableConfig}
|
|
266
187
|
toolBarRender={(...args) => [
|
|
267
|
-
...toolBarRender && toolBarRender(...args) || [],
|
|
268
188
|
columnsSetSelect?.() || null,
|
|
269
189
|
!viewOnly && onUpdateMany
|
|
270
|
-
?
|
|
271
|
-
|
|
272
|
-
selectedRecords={selectedRecords}
|
|
273
|
-
lastRequest={lastRequest}
|
|
274
|
-
allSelected={allSelected}
|
|
275
|
-
columns={columns}
|
|
276
|
-
idColumnName={idColumnName}
|
|
277
|
-
// @ts-ignore
|
|
278
|
-
onSubmit={values => onUpdateMany({
|
|
279
|
-
...pathParams,
|
|
280
|
-
...lastRequest[0],
|
|
281
|
-
requestBody: {
|
|
282
|
-
updateValues: _.pickBy(
|
|
283
|
-
// @ts-ignore
|
|
284
|
-
entityToUpdateDto({
|
|
285
|
-
...pathParams,
|
|
286
|
-
...values,
|
|
287
|
-
}),
|
|
288
|
-
(value, key) => _.has(values, key),
|
|
289
|
-
),
|
|
290
|
-
records: allSelected ? [] : selectedRecords,
|
|
291
|
-
},
|
|
292
|
-
}).then(() => {
|
|
293
|
-
messageApi.open({
|
|
294
|
-
type: 'success',
|
|
295
|
-
content: 'Operation Successful',
|
|
296
|
-
});
|
|
297
|
-
actionRef?.current?.reload();
|
|
298
|
-
})}
|
|
299
|
-
/>
|
|
300
|
-
)
|
|
301
|
-
: <></>,
|
|
190
|
+
? bulkEditButton
|
|
191
|
+
: null,
|
|
302
192
|
!viewOnly && onDeleteMany
|
|
303
|
-
?
|
|
304
|
-
|
|
305
|
-
selectedRecords={selectedRecords}
|
|
306
|
-
lastRequest={lastRequest}
|
|
307
|
-
allSelected={allSelected}
|
|
308
|
-
// @ts-ignore
|
|
309
|
-
onDelete={() => onDeleteMany({
|
|
310
|
-
...pathParams,
|
|
311
|
-
...lastRequest[0],
|
|
312
|
-
requestBody: {
|
|
313
|
-
records: allSelected ? [] : selectedRecords,
|
|
314
|
-
},
|
|
315
|
-
}).then(() => {
|
|
316
|
-
messageApi.open({
|
|
317
|
-
type: 'success',
|
|
318
|
-
content: 'Operation Successful',
|
|
319
|
-
});
|
|
320
|
-
actionRef?.current?.reload();
|
|
321
|
-
})}
|
|
322
|
-
/>
|
|
323
|
-
)
|
|
324
|
-
: <></>,
|
|
193
|
+
? bulkDeleteButton
|
|
194
|
+
: null,
|
|
325
195
|
!viewOnly && createButton || null,
|
|
196
|
+
...toolBarRender && toolBarRender(...args) || [],
|
|
326
197
|
]}
|
|
327
198
|
columns={columns}
|
|
328
199
|
defaultSize='small'
|
|
@@ -331,71 +202,37 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
331
202
|
{
|
|
332
203
|
...(
|
|
333
204
|
!viewOnly && (onUpdateMany || onDeleteMany)
|
|
334
|
-
? {
|
|
335
|
-
rowSelection: {
|
|
336
|
-
selectedRowKeys: selectedRecords.map(record => Array.isArray(idColumnName) ? idColumnName.map(colName => record[colName]).join('-') : record[idColumnName]),
|
|
337
|
-
selections: [
|
|
338
|
-
{
|
|
339
|
-
key: 'all',
|
|
340
|
-
text: (
|
|
341
|
-
<Space>
|
|
342
|
-
Select ALL
|
|
343
|
-
<Popover
|
|
344
|
-
content={(
|
|
345
|
-
<div style={{ width: '100%' }}>
|
|
346
|
-
This includes records from ALL pages of the table.
|
|
347
|
-
</div>
|
|
348
|
-
)}
|
|
349
|
-
title={'Select All'}
|
|
350
|
-
trigger={['hover', 'click']}
|
|
351
|
-
zIndex={1080}
|
|
352
|
-
>
|
|
353
|
-
<QuestionCircleTwoTone />
|
|
354
|
-
</Popover>
|
|
355
|
-
</Space>
|
|
356
|
-
),
|
|
357
|
-
onSelect: () => {
|
|
358
|
-
setSelectedRecords(lastRequest[1].data);
|
|
359
|
-
setAllSelected(true);
|
|
360
|
-
},
|
|
361
|
-
},
|
|
362
|
-
],
|
|
363
|
-
onChange: (rowKeys, records) => {
|
|
364
|
-
setSelectedRecords(records);
|
|
365
|
-
allSelected && setAllSelected(false);
|
|
366
|
-
},
|
|
367
|
-
}
|
|
368
|
-
}
|
|
205
|
+
? { rowSelection }
|
|
369
206
|
: {}
|
|
370
207
|
)
|
|
371
208
|
}
|
|
372
209
|
{...rest}
|
|
373
210
|
/>
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
actionRef?.current?.reload();
|
|
387
|
-
setCreatePopupData(undefined);
|
|
388
|
-
}
|
|
389
|
-
catch (e) {
|
|
390
|
-
console.error(e);
|
|
391
|
-
}
|
|
211
|
+
|
|
212
|
+
{creationModal}
|
|
213
|
+
|
|
214
|
+
<Modal
|
|
215
|
+
title={editPopupTitle}
|
|
216
|
+
open={updatePopupData !== undefined}
|
|
217
|
+
width='80%'
|
|
218
|
+
closeIcon={true}
|
|
219
|
+
footer={null}
|
|
220
|
+
onCancel={() => {
|
|
221
|
+
actionRef?.current?.reload();
|
|
222
|
+
setUpdatePopupData(undefined);
|
|
392
223
|
}}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
224
|
+
>
|
|
225
|
+
<Descriptions<Entity, CreateDto, UpdateDto, TPathParams>
|
|
226
|
+
mainTitle={descriptionsMainTitle}
|
|
227
|
+
columns={columns ?? []}
|
|
228
|
+
entity={updatePopupData}
|
|
229
|
+
canEdit={true}
|
|
230
|
+
onUpdate={onUpdate}
|
|
231
|
+
entityToUpdateDto={entityToUpdateDto}
|
|
232
|
+
/>
|
|
233
|
+
</Modal>
|
|
234
|
+
{messagesContext}
|
|
397
235
|
</>);
|
|
398
236
|
};
|
|
399
237
|
|
|
400
238
|
export default Table;
|
|
401
|
-
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { TFilterParams, TFilters, TGetAllParams, TSearchableColumn, TSort } from "./tableTypes";
|
|
2
|
+
import { applyKeywordToSearch, buildJoinFields, collectFieldsFromColumns, getFiltersSearch } from "./tableTools";
|
|
3
|
+
import { QuerySortArr } from "@nestjsx/crud-request";
|
|
4
|
+
import { ProColumns } from "@ant-design/pro-components";
|
|
5
|
+
import { ColumnStateType } from "@ant-design/pro-table/es/typing";
|
|
6
|
+
|
|
7
|
+
export function getTableDataQueryParams<Entity, TPathParams extends Record<string, string | number> = {}>({
|
|
8
|
+
params,
|
|
9
|
+
sort = {},
|
|
10
|
+
filters = {},
|
|
11
|
+
pathParams,
|
|
12
|
+
defaultSort,
|
|
13
|
+
searchableColumns,
|
|
14
|
+
columns = [],
|
|
15
|
+
idColumnName = 'id',
|
|
16
|
+
columnsState,
|
|
17
|
+
}: {
|
|
18
|
+
params: TFilterParams,
|
|
19
|
+
sort?: TSort,
|
|
20
|
+
filters?: TFilters,
|
|
21
|
+
pathParams: TPathParams,
|
|
22
|
+
defaultSort?: QuerySortArr,
|
|
23
|
+
searchableColumns?: TSearchableColumn[],
|
|
24
|
+
columns?: ProColumns<Entity>[],
|
|
25
|
+
idColumnName?: string | string[];
|
|
26
|
+
columnsState?: ColumnStateType;
|
|
27
|
+
}): TGetAllParams & TPathParams {
|
|
28
|
+
const {
|
|
29
|
+
current,
|
|
30
|
+
pageSize,
|
|
31
|
+
keyword,
|
|
32
|
+
baseFilters,
|
|
33
|
+
join,
|
|
34
|
+
sortMap,
|
|
35
|
+
...filtersFromSearchForm
|
|
36
|
+
} = params;
|
|
37
|
+
|
|
38
|
+
const queryParams: TGetAllParams & TPathParams = {
|
|
39
|
+
...pathParams,
|
|
40
|
+
page: current,
|
|
41
|
+
limit: pageSize,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const sortBy = Object
|
|
45
|
+
.entries(sort)
|
|
46
|
+
.reduce<string[]>(
|
|
47
|
+
(data: string[], [key, direction]) => {
|
|
48
|
+
data.push(`${sortMap?.[key] || key},${direction === 'ascend' ? 'ASC' : 'DESC'}`);
|
|
49
|
+
return data;
|
|
50
|
+
},
|
|
51
|
+
[]
|
|
52
|
+
);
|
|
53
|
+
if (!sortBy.length && defaultSort) {
|
|
54
|
+
sortBy.push(defaultSort.join(','));
|
|
55
|
+
}
|
|
56
|
+
queryParams.sort = sortBy;
|
|
57
|
+
|
|
58
|
+
let search = getFiltersSearch({
|
|
59
|
+
baseFilters,
|
|
60
|
+
filters: {
|
|
61
|
+
...filters,
|
|
62
|
+
...filtersFromSearchForm,
|
|
63
|
+
},
|
|
64
|
+
searchableColumns,
|
|
65
|
+
});
|
|
66
|
+
search = applyKeywordToSearch(search, searchableColumns!, columnsState.value!, keyword);
|
|
67
|
+
queryParams.s = JSON.stringify(search);
|
|
68
|
+
|
|
69
|
+
const { joinSelect, joinFields } = buildJoinFields(join);
|
|
70
|
+
queryParams.join = joinSelect;
|
|
71
|
+
|
|
72
|
+
queryParams.fields = columns && collectFieldsFromColumns(
|
|
73
|
+
columns,
|
|
74
|
+
idColumnName,
|
|
75
|
+
joinFields,
|
|
76
|
+
) || [];
|
|
77
|
+
|
|
78
|
+
return queryParams;
|
|
79
|
+
}
|
|
@@ -169,11 +169,12 @@ export function buildFieldsFromColumns<T>(
|
|
|
169
169
|
// skip id column because it is always included by backend
|
|
170
170
|
// and join fields because they are included by join
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
const dataIndex = String(Array.isArray(col.dataIndex) ? col.dataIndex[0] : col.dataIndex);
|
|
173
|
+
if (!dataIndex || (Array.isArray(idColumnName) ? idColumnName.includes(dataIndex) : dataIndex === idColumnName) || joinFields.has(dataIndex)) {
|
|
173
174
|
return;
|
|
174
175
|
}
|
|
175
176
|
|
|
176
|
-
fields.add(
|
|
177
|
+
fields.add(dataIndex);
|
|
177
178
|
});
|
|
178
179
|
|
|
179
180
|
return fields;
|
|
@@ -5,6 +5,7 @@ import { Operators } from "./tableTools";
|
|
|
5
5
|
import { TColumnsSet } from "./useColumnsSets";
|
|
6
6
|
import { ColumnStateType } from "@ant-design/pro-table/es/typing";
|
|
7
7
|
import { RowEditableConfig } from "@ant-design/pro-utils";
|
|
8
|
+
import { ProColumns } from "@ant-design/pro-components";
|
|
8
9
|
|
|
9
10
|
export type IWithId = {
|
|
10
11
|
id: string | number,
|
|
@@ -88,9 +89,7 @@ interface BaseProps<Entity,
|
|
|
88
89
|
pathParams: TPathParams;
|
|
89
90
|
idColumnName?: string & keyof Entity | (string & keyof Entity)[];
|
|
90
91
|
createNewDefaultParams?: Partial<Entity>;
|
|
91
|
-
|
|
92
|
-
actionRef?: MutableRefObject<ActionType | undefined>;
|
|
93
|
-
editable?: RowEditableConfig<Entity>;
|
|
92
|
+
editableRecord?: Partial<Entity>;
|
|
94
93
|
defaultSort?: QuerySortArr;
|
|
95
94
|
searchableColumns?: TSearchableColumn[];
|
|
96
95
|
viewOnly?: boolean;
|
|
@@ -98,17 +97,25 @@ interface BaseProps<Entity,
|
|
|
98
97
|
popupCreation?: boolean;
|
|
99
98
|
columnsState?: ColumnStateType;
|
|
100
99
|
columnsSetSelect?: () => React.ReactNode;
|
|
101
|
-
|
|
100
|
+
editPopupTitle?: string;
|
|
101
|
+
createPopupTitle?: string;
|
|
102
|
+
descriptionsMainTitle?: ProColumns<Entity>['title'] | null;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
interface EditableProps<Entity, CreateDto, UpdateDto, TPathParams = {}> {
|
|
105
|
+
export interface EditableProps<Entity, CreateDto, UpdateDto, TPathParams = {}> {
|
|
106
|
+
actionRef?: MutableRefObject<ActionType | undefined>;
|
|
107
|
+
editable?: RowEditableConfig<Entity>;
|
|
108
|
+
afterSave?: (record: Entity) => Promise<void>;
|
|
105
109
|
onCreate?: ({}: { requestBody: CreateDto } & TPathParams) => Promise<Entity>;
|
|
106
|
-
onUpdate: ({}:
|
|
107
|
-
|
|
110
|
+
onUpdate: ({}: Partial<Entity> & {
|
|
111
|
+
requestBody: UpdateDto,
|
|
112
|
+
index?: number,
|
|
113
|
+
} & TPathParams) => Promise<Entity>;
|
|
114
|
+
onDelete: ({}: Partial<Entity> & TPathParams) => Promise<void>;
|
|
108
115
|
entityToCreateDto: (entity: Entity) => CreateDto;
|
|
109
116
|
entityToUpdateDto: (entity: Entity) => UpdateDto;
|
|
110
|
-
onUpdateMany: ({}:
|
|
111
|
-
onDeleteMany: ({}:
|
|
117
|
+
onUpdateMany: ({}: Partial<Entity> & { requestBody: { updateValues: Partial<UpdateDto>[], records: Entity[] } } & TPathParams) => Promise<void>,
|
|
118
|
+
onDeleteMany: ({}: Partial<Entity> & { requestBody: { records: Entity[] } } & TPathParams) => Promise<void>,
|
|
112
119
|
}
|
|
113
120
|
|
|
114
121
|
// Conditional type to merge base and editable props conditionally
|