@boarteam/boar-pack-common-frontend 2.10.0 → 3.1.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 +4 -3
- package/src/components/Comment/Comment.tsx +53 -0
- package/src/components/Comment/CommentAvatar.tsx +34 -0
- package/src/components/Comment/CommentForm.tsx +36 -0
- package/src/components/Comment/CommentFormModal.tsx +31 -0
- package/src/components/Comment/index.ts +5 -0
- package/src/components/Descriptions/Descriptions.tsx +27 -3
- package/src/components/Descriptions/descriptionTypes.ts +8 -0
- package/src/components/Table/CreateEntityModal.tsx +5 -1
- package/src/components/Table/Table.tsx +2 -0
- package/src/components/Table/tableTools.ts +20 -4
- package/src/components/Table/tableTypes.ts +4 -1
- package/src/components/Table/useColumnsSets.tsx +39 -7
- package/src/components/Table/useCreation.tsx +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boarteam/boar-pack-common-frontend",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Common frontend package for Boar Pack",
|
|
5
5
|
"repository": "git@github.com:boarteam/boar-pack.git",
|
|
6
6
|
"author": "Andrew Balakirev <balakirev.andrey@gmail.com>",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@nestjsx/crud-request": "^5.0.0-alpha.3",
|
|
29
|
-
"lodash": "^4.17.21"
|
|
29
|
+
"lodash": "^4.17.21",
|
|
30
|
+
"uuid": "^11.1.0"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@ant-design/icons": "^4.8.3",
|
|
@@ -46,5 +47,5 @@
|
|
|
46
47
|
"scripts": {
|
|
47
48
|
"yalc:push": "yalc push"
|
|
48
49
|
},
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "008e1d42d47532005e1af1909d40befdebff5197"
|
|
50
51
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import { createStyles } from "antd-style";
|
|
3
|
+
import CommentAvatar from "./CommentAvatar";
|
|
4
|
+
|
|
5
|
+
export interface AuthorProps {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface CommentProps {
|
|
11
|
+
key: string;
|
|
12
|
+
content: string;
|
|
13
|
+
author: AuthorProps;
|
|
14
|
+
date: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const useStyles = createStyles(() => {
|
|
18
|
+
return {
|
|
19
|
+
/**
|
|
20
|
+
* Styles for the ant-descriptions component to show edit icon on hover
|
|
21
|
+
*/
|
|
22
|
+
commentStyles: {
|
|
23
|
+
display: 'flex',
|
|
24
|
+
alignItems: 'flex-start',
|
|
25
|
+
gap: '10px'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const Comment: React.FC<CommentProps> = ({
|
|
31
|
+
content,
|
|
32
|
+
author,
|
|
33
|
+
date,
|
|
34
|
+
...rest
|
|
35
|
+
}) => {
|
|
36
|
+
const { styles } = useStyles();
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
className={styles.commentStyles}
|
|
41
|
+
{...rest}
|
|
42
|
+
>
|
|
43
|
+
<CommentAvatar author={author} />
|
|
44
|
+
<div>
|
|
45
|
+
<strong>{author.name}</strong>
|
|
46
|
+
<p>{content}</p>
|
|
47
|
+
<small style={{ color: '#888' }}>{dayjs(date).format('DD.MM.YYYY HH:mm')}</small>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default Comment;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Avatar } from "antd";
|
|
2
|
+
import { AuthorProps } from "./Comment";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
interface CommentProps {
|
|
6
|
+
author: AuthorProps;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const ColorList = [
|
|
10
|
+
'#f56a00',
|
|
11
|
+
'#7265e6',
|
|
12
|
+
'#ffbf00',
|
|
13
|
+
'#00a2ae',
|
|
14
|
+
'#b45d7e',
|
|
15
|
+
'#ace665',
|
|
16
|
+
'#6e3aaf',
|
|
17
|
+
'#54ae00'
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const getColorByAuthor = (authorId: string) => {
|
|
21
|
+
return ColorList[parseInt(authorId, 36) % ColorList.length]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const CommentAvatar: React.FC<CommentProps> = ({
|
|
25
|
+
author,
|
|
26
|
+
}) => {
|
|
27
|
+
return (
|
|
28
|
+
<Avatar style={{ backgroundColor: getColorByAuthor(author.id), verticalAlign: 'middle', flexShrink: 0 }} size="large">
|
|
29
|
+
{author.name.slice(0, 1)}
|
|
30
|
+
</Avatar>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default CommentAvatar;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Form, Input, Button } from 'antd';
|
|
3
|
+
|
|
4
|
+
interface CommentFormProps {
|
|
5
|
+
onSubmit: (content: string) => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const CommentForm: React.FC<CommentFormProps> = ({ onSubmit }) => {
|
|
9
|
+
const [content, setContent] = useState('');
|
|
10
|
+
|
|
11
|
+
const handleSubmit = () => {
|
|
12
|
+
if (content.trim()) {
|
|
13
|
+
onSubmit(content);
|
|
14
|
+
setContent('');
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Form layout="vertical" onFinish={handleSubmit}>
|
|
20
|
+
<div>
|
|
21
|
+
<Form.Item label="Leave a comment:">
|
|
22
|
+
<Input.TextArea
|
|
23
|
+
value={content}
|
|
24
|
+
onChange={(e) => setContent(e.target.value)}
|
|
25
|
+
autoSize={{ minRows: 3, maxRows: 6 }}
|
|
26
|
+
/>
|
|
27
|
+
</Form.Item>
|
|
28
|
+
</div>
|
|
29
|
+
<Button type="primary" htmlType="submit" style={{ width: 100 }}>
|
|
30
|
+
Send
|
|
31
|
+
</Button>
|
|
32
|
+
</Form>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default CommentForm;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal } from 'antd';
|
|
3
|
+
import CommentForm from "./CommentForm";
|
|
4
|
+
|
|
5
|
+
interface CommentFormProps {
|
|
6
|
+
isOpen: boolean;
|
|
7
|
+
setIsOpen: (open: boolean) => void;
|
|
8
|
+
onSubmit: (content: string) => void;
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
title?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const CommentFormModal: React.FC<CommentFormProps> = ({ setIsOpen, isOpen, onSubmit, children, title = 'Add comment' }) => {
|
|
14
|
+
return (
|
|
15
|
+
<Modal
|
|
16
|
+
title={title}
|
|
17
|
+
open={isOpen}
|
|
18
|
+
width={800}
|
|
19
|
+
closeIcon={true}
|
|
20
|
+
footer={null}
|
|
21
|
+
onCancel={() => {
|
|
22
|
+
setIsOpen(false);
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
<CommentForm onSubmit={onSubmit} />
|
|
27
|
+
</Modal>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default CommentFormModal;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ActionType } from "@ant-design/pro-table";
|
|
2
2
|
import React, { Key, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { Badge, Button, Result, Tabs, TabsProps, Tooltip } from "antd";
|
|
3
|
+
import { Badge, Button, Form, Result, Tabs, TabsProps, Tooltip } from "antd";
|
|
4
4
|
import { DeleteOutlined, StopOutlined } from "@ant-design/icons";
|
|
5
5
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
6
|
import { DescriptionsRefType, FieldsEdit, TDescriptionsProps, TGetOneParams } from "./descriptionTypes";
|
|
@@ -21,7 +21,7 @@ import { debounce } from "lodash";
|
|
|
21
21
|
import { NamePath } from "antd/lib/form/interface";
|
|
22
22
|
import { FieldData } from "rc-field-form/lib/interface";
|
|
23
23
|
|
|
24
|
-
const useStyles = createStyles(({css}) => {
|
|
24
|
+
const useStyles = createStyles(({ css }) => {
|
|
25
25
|
return {
|
|
26
26
|
antDescriptionsStyles: css`
|
|
27
27
|
.ant-descriptions-item-content {
|
|
@@ -62,6 +62,7 @@ const DescriptionsComponent = <Entity extends Record<string | symbol, any>,
|
|
|
62
62
|
columns,
|
|
63
63
|
params,
|
|
64
64
|
onEntityChange,
|
|
65
|
+
conditionalFieldsConfig,
|
|
65
66
|
...rest
|
|
66
67
|
}: TDescriptionsProps<Entity,
|
|
67
68
|
CreateDto,
|
|
@@ -80,13 +81,36 @@ const DescriptionsComponent = <Entity extends Record<string | symbol, any>,
|
|
|
80
81
|
}
|
|
81
82
|
form = editable.form;
|
|
82
83
|
|
|
84
|
+
const watchedValue = conditionalFieldsConfig
|
|
85
|
+
? Form.useWatch(conditionalFieldsConfig.field, form)
|
|
86
|
+
: undefined;
|
|
87
|
+
|
|
88
|
+
const filteredColumns = React.useMemo(() => {
|
|
89
|
+
if (!conditionalFieldsConfig) {
|
|
90
|
+
return columns;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const { field, deps } = conditionalFieldsConfig;
|
|
94
|
+
const depsList = deps[watchedValue as string];
|
|
95
|
+
|
|
96
|
+
if (!depsList?.length) {
|
|
97
|
+
return columns;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Always include the watched field itself
|
|
101
|
+
return columns.filter(col => {
|
|
102
|
+
const idx = col.dataIndex as string;
|
|
103
|
+
return idx === field || depsList.includes(idx);
|
|
104
|
+
});
|
|
105
|
+
}, [columns, watchedValue, conditionalFieldsConfig]);
|
|
106
|
+
|
|
83
107
|
const actionRefComponent = useRef<ActionType>();
|
|
84
108
|
const actionRef = actionRefProp || actionRefComponent;
|
|
85
109
|
const intl = useIntl();
|
|
86
110
|
const [data, setData] = useState<Partial<Entity> | undefined>(entity);
|
|
87
111
|
const [loading, setLoading] = useState(false);
|
|
88
112
|
|
|
89
|
-
const sections = columnsToDescriptionItemProps(
|
|
113
|
+
const sections = columnsToDescriptionItemProps(filteredColumns, mainTitle);
|
|
90
114
|
|
|
91
115
|
const columnDataIndexToSection = sections.reduce((acc, section) => {
|
|
92
116
|
section.columns.forEach(column => {
|
|
@@ -35,7 +35,15 @@ export enum FieldsEdit {
|
|
|
35
35
|
All = 'all'
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export interface ConditionalFieldsConfig {
|
|
39
|
+
/** Which field to watch */
|
|
40
|
+
field: string;
|
|
41
|
+
/** Map of watched-value → array of dataIndex you want to show */
|
|
42
|
+
deps: Record<string, string[]>;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
export type TDescriptionsProps<Entity, CreateDto, UpdateDto, TPathParams = object> = {
|
|
46
|
+
conditionalFieldsConfig?: ConditionalFieldsConfig;
|
|
39
47
|
mainTitle?: ProColumns<Entity>['title'] | null,
|
|
40
48
|
entity?: Partial<Entity>,
|
|
41
49
|
getOne?: ({}: TGetOneParams & TPathParams) => Promise<Entity | null>,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ProColumns } from "@ant-design/pro-components";
|
|
2
2
|
import { Button, Modal } from "antd";
|
|
3
3
|
import { MutableRefObject, useRef } from "react";
|
|
4
|
-
import { Descriptions, DescriptionsRefType } from "../Descriptions";
|
|
4
|
+
import { ConditionalFieldsConfig, Descriptions, DescriptionsRefType } from "../Descriptions";
|
|
5
5
|
import { buildFieldsFromColumnsForDescriptionsDisplay } from "./tableTools";
|
|
6
6
|
|
|
7
7
|
export interface CreateEntityModalProps<Entity> {
|
|
@@ -24,6 +24,8 @@ export interface CreateEntityModalProps<Entity> {
|
|
|
24
24
|
* Receives the validated form data.
|
|
25
25
|
*/
|
|
26
26
|
onSubmit: (data: any, descriptionsRef: MutableRefObject<DescriptionsRefType<Entity>>) => Promise<void>;
|
|
27
|
+
/** Configuration for conditional fields */
|
|
28
|
+
conditionalFieldsConfig?: ConditionalFieldsConfig
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export function CreateEntityModal<
|
|
@@ -40,6 +42,7 @@ export function CreateEntityModal<
|
|
|
40
42
|
idColumnName,
|
|
41
43
|
onCancel,
|
|
42
44
|
onSubmit,
|
|
45
|
+
conditionalFieldsConfig,
|
|
43
46
|
}: CreateEntityModalProps<Entity>) {
|
|
44
47
|
const descriptionsRef = useRef<DescriptionsRefType<Entity>>(null);
|
|
45
48
|
|
|
@@ -79,6 +82,7 @@ export function CreateEntityModal<
|
|
|
79
82
|
editableKeys,
|
|
80
83
|
actionRender: () => [],
|
|
81
84
|
}}
|
|
85
|
+
conditionalFieldsConfig={conditionalFieldsConfig}
|
|
82
86
|
/>
|
|
83
87
|
</Modal>
|
|
84
88
|
);
|
|
@@ -55,6 +55,7 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
55
55
|
columnsState: managedColumnsState,
|
|
56
56
|
columnsSetSelect: managedColumnsSetSelect,
|
|
57
57
|
popupCreation = false,
|
|
58
|
+
conditionalFieldsConfig,
|
|
58
59
|
toolBarRender,
|
|
59
60
|
params,
|
|
60
61
|
editPopupTitle,
|
|
@@ -120,6 +121,7 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
120
121
|
createButtonSize: rest.size,
|
|
121
122
|
popupCreation,
|
|
122
123
|
createNewDefaultParams,
|
|
124
|
+
conditionalFieldsConfig,
|
|
123
125
|
});
|
|
124
126
|
|
|
125
127
|
const { exportButton, importButton, setLastQueryParams } = useImportExport<TPathParams>({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CondOperator, QueryJoin, SCondition } from "@nestjsx/crud-request";
|
|
2
|
+
import { validate as uuidValidate } from 'uuid';
|
|
2
3
|
import { IWithId, TFilters, TSearchableColumn } from "./tableTypes";
|
|
3
4
|
import React, { Key } from "react";
|
|
4
5
|
import { TColumnsStates } from "./useColumnsSets";
|
|
@@ -20,7 +21,12 @@ export function getFiltersSearch({
|
|
|
20
21
|
let operator = col.filterOperator || col.operator;
|
|
21
22
|
let value = filters[colDataIndex] || baseFilters[colDataIndex];
|
|
22
23
|
filterKeys.delete(colDataIndex);
|
|
23
|
-
if (
|
|
24
|
+
if (
|
|
25
|
+
value === '' ||
|
|
26
|
+
value === undefined ||
|
|
27
|
+
col.numeric && !Number.isFinite(Number(value)) ||
|
|
28
|
+
col.uuid && (typeof value !== 'string' || !uuidValidate(value))
|
|
29
|
+
) {
|
|
24
30
|
return;
|
|
25
31
|
}
|
|
26
32
|
|
|
@@ -126,7 +132,10 @@ export function applyKeywordToSearch(
|
|
|
126
132
|
const field = col.searchField || (Array.isArray(col.field) ? col.field.join('.') : col.field);
|
|
127
133
|
const operator = col.operator;
|
|
128
134
|
|
|
129
|
-
|
|
135
|
+
const wrongNumeric = col.numeric && !Number.isFinite(Number(word));
|
|
136
|
+
const wrongUuid = col.uuid && (typeof word !== 'string' || !uuidValidate(word));
|
|
137
|
+
|
|
138
|
+
if (!wrongNumeric && !wrongUuid) {
|
|
130
139
|
keywordSearch.$or.push({ [field]: { [operator]: word } });
|
|
131
140
|
}
|
|
132
141
|
});
|
|
@@ -146,6 +155,7 @@ export function applyKeywordToSearch(
|
|
|
146
155
|
export type TIndexableRecord = {
|
|
147
156
|
dataIndex?: Key | Key[];
|
|
148
157
|
children?: TIndexableRecord[] | React.ReactNode;
|
|
158
|
+
editable?: false;
|
|
149
159
|
};
|
|
150
160
|
|
|
151
161
|
export function collectFieldsFromColumns<T>(
|
|
@@ -166,7 +176,9 @@ export function buildFieldsFromColumnsForDescriptionsDisplay<T>(
|
|
|
166
176
|
if ('children' in col && Array.isArray(col.children)) {
|
|
167
177
|
buildFieldsFromColumnsForDescriptionsDisplay(col.children, idColumnName, fields);
|
|
168
178
|
}
|
|
169
|
-
|
|
179
|
+
if (col.editable !== false) {
|
|
180
|
+
fields.add(String(Array.isArray(col.dataIndex) ? col.dataIndex[0] : col.dataIndex));
|
|
181
|
+
}
|
|
170
182
|
});
|
|
171
183
|
|
|
172
184
|
return fields;
|
|
@@ -186,7 +198,11 @@ export function buildFieldsFromColumns<T>(
|
|
|
186
198
|
// skip id column because it is always included by backend
|
|
187
199
|
// and join fields because they are included by join
|
|
188
200
|
|
|
189
|
-
const dataIndex =
|
|
201
|
+
const dataIndex = Array.isArray(col.dataIndex) ? col.dataIndex[0] : col.dataIndex;
|
|
202
|
+
if (typeof dataIndex !== 'string') {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
190
206
|
if (!dataIndex || (Array.isArray(idColumnName) ? idColumnName.includes(dataIndex) : dataIndex === idColumnName) || joinFields.has(dataIndex)) {
|
|
191
207
|
return;
|
|
192
208
|
}
|
|
@@ -6,6 +6,7 @@ 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
8
|
import { ProColumns } from "@ant-design/pro-components";
|
|
9
|
+
import { ConditionalFieldsConfig } from "../Descriptions";
|
|
9
10
|
|
|
10
11
|
export type IWithId = {
|
|
11
12
|
id: string | number,
|
|
@@ -53,7 +54,7 @@ export type TGetAllParams = {
|
|
|
53
54
|
cache?: number,
|
|
54
55
|
}
|
|
55
56
|
export type TFilters = {
|
|
56
|
-
[key: string]: number | string | boolean | (string | number)[] | null;
|
|
57
|
+
[key: string]: number | string | boolean | (string | number | boolean)[] | null;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
export type TGetRequestParams = {
|
|
@@ -78,6 +79,7 @@ export type TSearchableColumn = {
|
|
|
78
79
|
filterField?: string,
|
|
79
80
|
filterOperator?: typeof Operators[keyof typeof Operators],
|
|
80
81
|
numeric?: boolean,
|
|
82
|
+
uuid?: boolean,
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
interface BaseProps<Entity,
|
|
@@ -95,6 +97,7 @@ interface BaseProps<Entity,
|
|
|
95
97
|
viewOnly?: boolean;
|
|
96
98
|
columnsSets?: TColumnsSet<Entity>[];
|
|
97
99
|
popupCreation?: boolean;
|
|
100
|
+
conditionalFieldsConfig?: ConditionalFieldsConfig;
|
|
98
101
|
columnsState?: ColumnStateType;
|
|
99
102
|
columnsSetSelect?: () => React.ReactNode;
|
|
100
103
|
editPopupTitle?: string;
|
|
@@ -33,19 +33,28 @@ function getColumnsStates<T>(
|
|
|
33
33
|
columns: TIndexableRecord[],
|
|
34
34
|
shownCols: Set<keyof T>,
|
|
35
35
|
state: TColumnsState = {},
|
|
36
|
-
): Record<string, ColumnsState
|
|
36
|
+
): {state: Record<string, ColumnsState>, someColumnsShown: boolean} {
|
|
37
|
+
let someColumnsShown = false;
|
|
37
38
|
columns.forEach(col => {
|
|
38
39
|
const idx = Array.isArray(col.dataIndex) ? col.dataIndex.join(',') : col.dataIndex;
|
|
40
|
+
let childrenColumnsShown = false;
|
|
39
41
|
if ('children' in col && Array.isArray(col.children)) {
|
|
40
|
-
getColumnsStates(col.children, shownCols, state);
|
|
42
|
+
const { someColumnsShown } = getColumnsStates(col.children, shownCols, state);
|
|
43
|
+
if (someColumnsShown) {
|
|
44
|
+
childrenColumnsShown = true;
|
|
45
|
+
}
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
if (idx
|
|
44
|
-
|
|
48
|
+
if (idx) {
|
|
49
|
+
if (shownCols.has(idx as keyof T) || childrenColumnsShown) {
|
|
50
|
+
someColumnsShown = true;
|
|
51
|
+
} else {
|
|
52
|
+
state[idx as string] = { show: false };
|
|
53
|
+
}
|
|
45
54
|
}
|
|
46
55
|
}, state);
|
|
47
56
|
|
|
48
|
-
return state
|
|
57
|
+
return { state, someColumnsShown };
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
export default function useColumnsSets<Entity>({
|
|
@@ -60,7 +69,7 @@ export default function useColumnsSets<Entity>({
|
|
|
60
69
|
columns: columnsSet
|
|
61
70
|
}) => [
|
|
62
71
|
name,
|
|
63
|
-
getColumnsStates<Entity>(columns, new Set(columnsSet))
|
|
72
|
+
getColumnsStates<Entity>(columns as TIndexableRecord[], new Set(columnsSet)).state,
|
|
64
73
|
])
|
|
65
74
|
), [columns]
|
|
66
75
|
);
|
|
@@ -97,7 +106,30 @@ export default function useColumnsSets<Entity>({
|
|
|
97
106
|
|
|
98
107
|
const columnsState = {
|
|
99
108
|
value: chosenColumnsSet,
|
|
100
|
-
|
|
109
|
+
// value contains only hidden columns and one which is just changed
|
|
110
|
+
onChange: (value: TColumnsStates) => {
|
|
111
|
+
const checkParentVisibility = (columns: TIndexableRecord[]) => {
|
|
112
|
+
let someColumnsShown = false;
|
|
113
|
+
|
|
114
|
+
columns.forEach(col => {
|
|
115
|
+
const idx = Array.isArray(col.dataIndex) ? col.dataIndex.join(',') : col.dataIndex as string;
|
|
116
|
+
if (idx && value[idx]?.show) {
|
|
117
|
+
someColumnsShown = true;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if ('children' in col && Array.isArray(col.children)) {
|
|
121
|
+
const someChildColumnsShown = checkParentVisibility(col.children);
|
|
122
|
+
if (someChildColumnsShown) {
|
|
123
|
+
value[idx] = { show: true };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return someColumnsShown;
|
|
129
|
+
};
|
|
130
|
+
checkParentVisibility(columns as TIndexableRecord[]);
|
|
131
|
+
setChosenColumnsSet(value);
|
|
132
|
+
},
|
|
101
133
|
};
|
|
102
134
|
|
|
103
135
|
return {
|
|
@@ -32,10 +32,11 @@ export function useCreation<Entity, CreateDto, TPathParams = {}>({
|
|
|
32
32
|
createButtonSize,
|
|
33
33
|
popupCreation,
|
|
34
34
|
createNewDefaultParams,
|
|
35
|
+
conditionalFieldsConfig,
|
|
35
36
|
}: {
|
|
36
37
|
actionRef?: MutableRefObject<ActionType | undefined>;
|
|
37
38
|
pathParams: TPathParams;
|
|
38
|
-
entityToCreateDto: (entity:
|
|
39
|
+
entityToCreateDto: (entity: Entity) => CreateDto;
|
|
39
40
|
onCreate?: ({}: { requestBody: CreateDto } & TPathParams) => Promise<Entity>;
|
|
40
41
|
createButtonSize: SizeType;
|
|
41
42
|
popupCreation?: boolean;
|
|
@@ -43,7 +44,7 @@ export function useCreation<Entity, CreateDto, TPathParams = {}>({
|
|
|
43
44
|
} & Omit<CreateEntityModalProps<Entity>, 'onSubmit' | 'onCancel' | 'entity'>) {
|
|
44
45
|
const [createPopupData, setCreatePopupData] = useState<Partial<Entity> | undefined>();
|
|
45
46
|
|
|
46
|
-
const onCreateSubmit = async (data:
|
|
47
|
+
const onCreateSubmit = async (data: Entity, descriptionsRef: MutableRefObject<DescriptionsRefType<Entity>>) => {
|
|
47
48
|
try {
|
|
48
49
|
await onCreate?.({
|
|
49
50
|
...pathParams,
|
|
@@ -105,6 +106,7 @@ export function useCreation<Entity, CreateDto, TPathParams = {}>({
|
|
|
105
106
|
setCreatePopupData(undefined);
|
|
106
107
|
}}
|
|
107
108
|
onSubmit={onCreateSubmit}
|
|
109
|
+
conditionalFieldsConfig={conditionalFieldsConfig}
|
|
108
110
|
/>;
|
|
109
111
|
|
|
110
112
|
return {
|