@boarteam/boar-pack-common-frontend 2.1.0 → 2.4.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boarteam/boar-pack-common-frontend",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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>",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"scripts": {
|
|
47
47
|
"yalc:push": "yalc push"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "29f4f6c6598c7422bef8e02dfd1e679b471a4aa4"
|
|
50
50
|
}
|
|
@@ -4,7 +4,7 @@ import { TDescriptionsCreateModalProps } from "./descriptionTypes";
|
|
|
4
4
|
import { ProDescriptions } from "@ant-design/pro-components";
|
|
5
5
|
import { columnsToDescriptionItemProps } from "./useDescriptionColumns";
|
|
6
6
|
import { useForm } from "antd/es/form/Form";
|
|
7
|
-
import {
|
|
7
|
+
import { buildFieldsFromColumnsForDescriptionsDisplay } from "../Table";
|
|
8
8
|
|
|
9
9
|
const DescriptionsCreateModal = <Entity extends Record<string | symbol, any>>({
|
|
10
10
|
idColumnName,
|
|
@@ -19,7 +19,7 @@ const DescriptionsCreateModal = <Entity extends Record<string | symbol, any>>({
|
|
|
19
19
|
|
|
20
20
|
const editableKeys = useMemo(() => {
|
|
21
21
|
return [
|
|
22
|
-
...
|
|
22
|
+
...buildFieldsFromColumnsForDescriptionsDisplay(
|
|
23
23
|
columns,
|
|
24
24
|
idColumnName,
|
|
25
25
|
),
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Tag, Input, InputNumber, Space, Button } from "antd";
|
|
1
|
+
import { Tag, Input, InputNumber, Space, Button, Switch, Descriptions, Checkbox, Typography } from "antd";
|
|
2
2
|
import { ColumnFilterItem, FilterDropdownProps } from "antd/es/table/interface";
|
|
3
3
|
import { ReactNode, useEffect, useState } from "react";
|
|
4
4
|
|
|
5
|
+
const { Text } = Typography;
|
|
6
|
+
|
|
5
7
|
export const booleanFilters: ColumnFilterItem[] = [
|
|
6
8
|
{ text: <Tag color='red'>Disabled</Tag>, value: 0 },
|
|
7
9
|
{ text: <Tag color='green'>Enabled</Tag>, value: 1 },
|
|
@@ -22,9 +24,45 @@ export function NumberFilterDropdown({ setSelectedKeys, selectedKeys, confirm, c
|
|
|
22
24
|
)
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
export function SwitchFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }: FilterDropdownProps) {
|
|
28
|
+
return (
|
|
29
|
+
<DynamicOptionsFilterDropdown confirm={confirm} clearFilters={clearFilters}>
|
|
30
|
+
<Descriptions
|
|
31
|
+
style={{ margin: '8px 16px', width: 200 }}
|
|
32
|
+
items={[
|
|
33
|
+
{
|
|
34
|
+
label: 'Only filled values',
|
|
35
|
+
children: <Switch
|
|
36
|
+
checked={selectedKeys.length ? Boolean(selectedKeys[0]) : undefined}
|
|
37
|
+
onChange={(value) => setSelectedKeys([value as any])}
|
|
38
|
+
/>,
|
|
39
|
+
style: { padding: 0 },
|
|
40
|
+
contentStyle: { justifyContent: 'flex-end' },
|
|
41
|
+
}
|
|
42
|
+
]}
|
|
43
|
+
/>
|
|
44
|
+
</DynamicOptionsFilterDropdown>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function CheckboxFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }: FilterDropdownProps) {
|
|
49
|
+
return (
|
|
50
|
+
<DynamicOptionsFilterDropdown confirm={confirm} clearFilters={clearFilters}>
|
|
51
|
+
<Checkbox
|
|
52
|
+
checked={selectedKeys.length ? Boolean(selectedKeys[0]) : undefined}
|
|
53
|
+
onChange={(event) => setSelectedKeys([event.target.checked as any])}
|
|
54
|
+
indeterminate={selectedKeys.length === 0}
|
|
55
|
+
style={{ margin: '8px 16px', width: 250 }}
|
|
56
|
+
>
|
|
57
|
+
{selectedKeys.length ? (selectedKeys[0] ? 'Will show only filled values' : 'Will show only empty values') : <Text type="secondary">Click to filter</Text>}
|
|
58
|
+
</Checkbox>
|
|
59
|
+
</DynamicOptionsFilterDropdown>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
25
63
|
export function NumberRangeFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }: FilterDropdownProps) {
|
|
26
64
|
const [range, updateRange] = useState<[number, number] | undefined>(selectedKeys);
|
|
27
|
-
|
|
65
|
+
|
|
28
66
|
useEffect(() => {
|
|
29
67
|
updateRange(selectedKeys);
|
|
30
68
|
}, [selectedKeys]);
|
|
@@ -71,8 +109,8 @@ export function StringFilterDropdown({ setSelectedKeys, selectedKeys, confirm, c
|
|
|
71
109
|
|
|
72
110
|
export const DynamicOptionsFilterDropdown = ({
|
|
73
111
|
children,
|
|
74
|
-
confirm,
|
|
75
|
-
clearFilters,
|
|
112
|
+
confirm,
|
|
113
|
+
clearFilters,
|
|
76
114
|
}: Partial<FilterDropdownProps> & { children: ReactNode}) => {
|
|
77
115
|
return (
|
|
78
116
|
<div style={{ display: 'flex', flexDirection: 'column' }} onKeyDown={(e) => e.stopPropagation()}>
|
|
@@ -80,8 +118,8 @@ export const DynamicOptionsFilterDropdown = ({
|
|
|
80
118
|
<Space className="ant-table-filter-dropdown-btns">
|
|
81
119
|
<Button
|
|
82
120
|
type="link"
|
|
83
|
-
onClick={() => {
|
|
84
|
-
clearFilters();
|
|
121
|
+
onClick={() => {
|
|
122
|
+
clearFilters();
|
|
85
123
|
confirm();
|
|
86
124
|
}}
|
|
87
125
|
size="small"
|
|
@@ -68,6 +68,7 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
68
68
|
popupCreation = false,
|
|
69
69
|
toolBarRender,
|
|
70
70
|
params,
|
|
71
|
+
popupDataState,
|
|
71
72
|
...rest
|
|
72
73
|
}: TTableProps<Entity,
|
|
73
74
|
CreateDto,
|
|
@@ -77,7 +78,7 @@ const Table = <Entity extends Record<string | symbol, any>,
|
|
|
77
78
|
) => {
|
|
78
79
|
const actionRefComponent = useRef<ActionType>();
|
|
79
80
|
const actionRef = actionRefProp || actionRefComponent;
|
|
80
|
-
const [createPopupData, setCreatePopupData] = useState<Partial<Entity> | undefined>();
|
|
81
|
+
const [createPopupData, setCreatePopupData] = popupDataState ?? useState<Partial<Entity> | undefined>();
|
|
81
82
|
const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
|
|
82
83
|
const [selectedRecords, setSelectedRecords] = useState<Entity[]>([]);
|
|
83
84
|
const [lastRequest, setLastRequest] = useState<[TGetAllParams & TPathParams, any] | []>([]);
|
|
@@ -20,19 +20,44 @@ export function getFiltersSearch({
|
|
|
20
20
|
let operator = col.filterOperator || col.operator;
|
|
21
21
|
let value = filters[colDataIndex] || baseFilters[colDataIndex];
|
|
22
22
|
filterKeys.delete(colDataIndex);
|
|
23
|
-
if (
|
|
23
|
+
if (value === '' || value === undefined || col.numeric && !Number.isFinite(Number(value))) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
switch (operator) {
|
|
28
|
+
case Operators.between:
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
if (value?.[0] === undefined) {
|
|
31
|
+
operator = Operators.lowerOrEquals;
|
|
32
|
+
value = value?.[1];
|
|
33
|
+
} else if (value?.[1] === undefined) {
|
|
34
|
+
operator = Operators.greaterOrEquals;
|
|
35
|
+
value = value?.[0];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
|
|
40
|
+
case Operators.isNull:
|
|
41
|
+
if (Array.isArray(value)) {
|
|
42
|
+
value = value[0];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (value !== true) {
|
|
46
|
+
operator = Operators.notNull;
|
|
47
|
+
value = true;
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
case Operators.notNull:
|
|
52
|
+
if (Array.isArray(value)) {
|
|
53
|
+
value = value[0];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (value !== true) {
|
|
57
|
+
operator = Operators.isNull;
|
|
58
|
+
value = true;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
36
61
|
}
|
|
37
62
|
|
|
38
63
|
search.$and?.push({ [field]: { [operator]: value } });
|
|
@@ -54,6 +79,8 @@ export const Operators = {
|
|
|
54
79
|
between: CondOperator.BETWEEN,
|
|
55
80
|
greaterOrEquals: CondOperator.GREATER_THAN_EQUALS,
|
|
56
81
|
lowerOrEquals: CondOperator.LOWER_THAN_EQUALS,
|
|
82
|
+
isNull: CondOperator.IS_NULL,
|
|
83
|
+
notNull: CondOperator.NOT_NULL,
|
|
57
84
|
} as const;
|
|
58
85
|
|
|
59
86
|
export function applyKeywordToSearch(
|
|
@@ -113,6 +140,21 @@ export function collectFieldsFromColumns<T>(
|
|
|
113
140
|
return [Array.from(buildFieldsFromColumns<T>(columns, idColumnName, joinFields, fields)).join(',')];
|
|
114
141
|
}
|
|
115
142
|
|
|
143
|
+
export function buildFieldsFromColumnsForDescriptionsDisplay<T>(
|
|
144
|
+
columns: TIndexableRecord[] | undefined,
|
|
145
|
+
idColumnName: string | string[],
|
|
146
|
+
fields: Set<string> = new Set,
|
|
147
|
+
): Set<string> {
|
|
148
|
+
columns?.forEach(col => {
|
|
149
|
+
if ('children' in col && Array.isArray(col.children)) {
|
|
150
|
+
buildFieldsFromColumnsForDescriptionsDisplay(col.children, idColumnName, fields);
|
|
151
|
+
}
|
|
152
|
+
fields.add(String(Array.isArray(col.dataIndex) ? col.dataIndex[0] : col.dataIndex));
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return fields;
|
|
156
|
+
}
|
|
157
|
+
|
|
116
158
|
export function buildFieldsFromColumns<T>(
|
|
117
159
|
columns: TIndexableRecord[] | undefined,
|
|
118
160
|
idColumnName: string | string[],
|
|
@@ -98,6 +98,7 @@ interface BaseProps<Entity,
|
|
|
98
98
|
popupCreation?: boolean;
|
|
99
99
|
columnsState?: ColumnStateType;
|
|
100
100
|
columnsSetSelect?: () => React.ReactNode;
|
|
101
|
+
popupDataState?: [Partial<Entity>, React.Dispatch<React.SetStateAction<Partial<Entity>>>]
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
interface EditableProps<Entity, CreateDto, UpdateDto, TPathParams = {}> {
|