@antscorp/antsomi-ui 1.3.5-beta.472 → 1.3.5-beta.474
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/es/components/icons/EventIcon.js +1 -1
- package/es/components/molecules/DatePicker/DatePicker.js +6 -0
- package/es/components/molecules/MatchAnySelect/MatchesAnySelect.js +14 -11
- package/es/components/molecules/MatchAnySelect/styled.js +14 -1
- package/es/components/molecules/MatchAnySelect/types.d.ts +5 -3
- package/es/components/organism/DataTable/components/Filter/AddFilterButton.js +11 -2
- package/es/components/organism/DataTable/components/Filter/FilterCondition/index.d.ts +3 -1
- package/es/components/organism/DataTable/components/Filter/FilterCondition/index.js +11 -4
- package/es/components/organism/DataTable/components/Filter/FilterConditionList.js +12 -10
- package/es/components/organism/DataTable/components/Filter/FilterItem.js +36 -6
- package/es/components/organism/DataTable/components/Toolbar/RowSelectedControl.js +1 -1
- package/es/components/organism/DataTable/components/Toolbar/styled.js +1 -0
- package/es/components/organism/DataTable/constants/theme.js +2 -0
- package/es/components/organism/DataTable/hooks/useAddFilterButton.d.ts +5 -0
- package/es/components/organism/DataTable/hooks/useAddFilterButton.js +4 -2
- package/es/components/organism/DataTable/hooks/useDataTableListing/types.d.ts +15 -3
- package/es/components/organism/DataTable/hooks/useDataTableListing/useDataTableListing.d.ts +1 -0
- package/es/components/organism/DataTable/hooks/useDataTableListing/useDataTableListing.js +59 -13
- package/es/components/organism/DataTable/types/filter.d.ts +7 -0
- package/es/components/organism/DataTable/utils/filter.d.ts +4 -2
- package/es/components/organism/DataTable/utils/filter.js +46 -10
- package/es/constants/condition.d.ts +15 -0
- package/es/constants/condition.js +15 -0
- package/es/constants/datetime.d.ts +4 -0
- package/es/constants/datetime.js +4 -0
- package/es/constants/queries.d.ts +1 -0
- package/es/constants/queries.js +1 -0
- package/es/constants/theme.js +1 -0
- package/es/locales/en/translation.json +2 -1
- package/es/locales/i18n.d.ts +2 -0
- package/es/locales/translations.d.ts +1 -0
- package/es/locales/vi/translation.json +2 -1
- package/es/queries/DataTable/index.d.ts +6 -1
- package/es/queries/DataTable/index.js +5 -1
- package/es/services/DataTable/index.d.ts +7 -0
- package/es/services/DataTable/index.js +16 -4
- package/es/tests/DataTableTest.js +45 -12
- package/es/types/actionsButton.d.ts +1 -1
- package/package.json +1 -1
|
@@ -14,5 +14,5 @@ export const EventIcon = (_a) => {
|
|
|
14
14
|
var props = __rest(_a, []);
|
|
15
15
|
return (React.createElement("svg", Object.assign({ xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 0 24 24", width: "24px", fill: "currentColor" }, props),
|
|
16
16
|
React.createElement("path", { d: "M0 0h24v24H0V0z", fill: "none" }),
|
|
17
|
-
React.createElement("path", { d: "
|
|
17
|
+
React.createElement("path", { d: "M16 13h-3c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1zm0-10v1H8V3c0-.55-.45-1-1-1s-1 .45-1 1v1H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-1V3c0-.55-.45-1-1-1s-1 .45-1 1zm2 17H6c-.55 0-1-.45-1-1V9h14v10c0 .55-.45 1-1 1z" })));
|
|
18
18
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
// Libraries
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import { DatePicker as AntdDatePicker } from 'antd';
|
|
3
4
|
// Components
|
|
4
5
|
import { AdvancedPicker } from './components/AdvancedPicker';
|
|
5
6
|
import { AdvancedRangePicker } from './components/AdvancedRangePicker';
|
|
7
|
+
import { EventIcon } from '../../icons';
|
|
8
|
+
import { globalToken } from '@antscorp/antsomi-ui/es/constants';
|
|
6
9
|
export const DatePicker = AntdDatePicker;
|
|
10
|
+
DatePicker.defaultProps = {
|
|
11
|
+
suffixIcon: React.createElement(EventIcon, { width: 20, height: 20, color: globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw8 }),
|
|
12
|
+
};
|
|
7
13
|
DatePicker.AdvancedPicker = AdvancedPicker;
|
|
8
14
|
DatePicker.AdvancedRangePicker = AdvancedRangePicker;
|
|
@@ -41,7 +41,7 @@ const { t } = i18nInstance;
|
|
|
41
41
|
const { Text } = Typography;
|
|
42
42
|
export const MatchesAny = props => {
|
|
43
43
|
// Props
|
|
44
|
-
const { objectName,
|
|
44
|
+
const { objectName, loading = false, showExtendValue = true, items, onApply = () => { }, onCancel = () => { } } = props, restOfProps = __rest(props, ["objectName", "loading", "showExtendValue", "items", "onApply", "onCancel"]);
|
|
45
45
|
// State
|
|
46
46
|
const [state, setState] = useState(matchesAnyInitialState);
|
|
47
47
|
// Variables
|
|
@@ -104,9 +104,11 @@ export const MatchesAny = props => {
|
|
|
104
104
|
setState(prev => (Object.assign(Object.assign({}, prev), { selectedItems: [] })));
|
|
105
105
|
};
|
|
106
106
|
const renderItemNodeTitle = ({ item, onSelectItem, onRemoveItem, }) => {
|
|
107
|
-
const { isExtendValue, title } = item; // Destructure properties from item
|
|
107
|
+
const { isExtendValue, title, subTitle } = item; // Destructure properties from item
|
|
108
108
|
return (React.createElement(React.Fragment, null,
|
|
109
|
-
React.createElement(
|
|
109
|
+
React.createElement("div", { className: "title-content" },
|
|
110
|
+
React.createElement(Text, { ellipsis: { tooltip: true } }, title),
|
|
111
|
+
subTitle && (React.createElement(Text, { className: "sub-title", ellipsis: { tooltip: true }, style: { color: globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw8 } }, subTitle))),
|
|
110
112
|
React.createElement(Flex, { align: "center", gap: 5 },
|
|
111
113
|
isExtendValue && (React.createElement(Icon, { type: "icon-ants-empty-flag", size: 20, color: globalToken === null || globalToken === void 0 ? void 0 : globalToken.colorPrimary })),
|
|
112
114
|
React.createElement(ActionButton, { className: "select-button", align: "center", justify: "center", onClick: () => {
|
|
@@ -191,18 +193,18 @@ export const MatchesAny = props => {
|
|
|
191
193
|
React.createElement(Flex, { align: "center", justify: "space-between" },
|
|
192
194
|
React.createElement(Text, { strong: true }, `${objectName} (${flatTree(items, 'children').filter(item => !item.children).length})`),
|
|
193
195
|
React.createElement(TextButton, { disabled: isDisableSelectAll, onClick: onSelectAll }, t(translations.global.selectAll).toString())),
|
|
194
|
-
React.createElement(Spin, { spinning:
|
|
196
|
+
React.createElement(Spin, { spinning: loading },
|
|
195
197
|
React.createElement(Scrollbars, { style: { height: '100%' } }, (treeData === null || treeData === void 0 ? void 0 : treeData.length) ? (React.createElement(StyledTree, { key: searchValue, defaultExpandedKeys: matchedParents.map(item => item.key), selectable: false, treeData: treeData, switcherIcon: props => (React.createElement(Icon, { type: "icon-ants-caret-down", style: {
|
|
196
198
|
transform: props.expanded ? 'rotate(0)' : 'rotate(-90deg)',
|
|
197
199
|
transition: 'transform 0.3s ease',
|
|
198
|
-
}, color: globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw8 })) })) : (React.createElement(EmptyData, { showIcon: false,
|
|
200
|
+
}, color: globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw8 })) })) : (React.createElement(EmptyData, { showIcon: false, description: t(translations.global.noResultsMatchesKeyWord).toString() })))))));
|
|
199
201
|
};
|
|
200
202
|
const renderSelectedList = () => (React.createElement("div", { className: "matches-any__section" },
|
|
201
203
|
React.createElement(Flex, { className: "matches-any__header", justify: "space-between" },
|
|
202
204
|
React.createElement(Text, { strong: true }, `${t(translations.global.selected)} (${(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) || 0})`),
|
|
203
205
|
React.createElement(TextButton, { disabled: isDisableRemoveAll, onClick: onRemoveAll }, t(translations.global.removeAll).toString())),
|
|
204
206
|
React.createElement("div", { className: "matches-any__body" },
|
|
205
|
-
React.createElement(Spin, { spinning:
|
|
207
|
+
React.createElement(Spin, { spinning: loading },
|
|
206
208
|
React.createElement(Scrollbars, { style: { height: '100%' } }, !(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) ? (React.createElement(EmptyData, { icon: "icon-ants-database", description: t(translations.global.selectItemsFromList).toString() })) : (React.createElement(StyledTree, { selectable: false, treeData: selectedTreeData, switcherIcon: props => (React.createElement(Icon, { type: "icon-ants-caret-down", style: {
|
|
207
209
|
transform: props.expanded ? 'rotate(0)' : 'rotate(-90deg)',
|
|
208
210
|
transition: 'transform 0.3s ease',
|
|
@@ -236,12 +238,11 @@ export const MatchesAny = props => {
|
|
|
236
238
|
};
|
|
237
239
|
export const MatchesAnySelect = props => {
|
|
238
240
|
var _a, _b, _c;
|
|
239
|
-
const { placeholder = 'Select an item', dropdownStyle, objectName, selectedItems, items,
|
|
241
|
+
const { placeholder = 'Select an item', dropdownStyle, objectName, selectedItems, items, loading, popupClassName, onChange = () => { } } = props, restProps = __rest(props, ["placeholder", "dropdownStyle", "objectName", "selectedItems", "items", "loading", "popupClassName", "onChange"]);
|
|
240
242
|
// State
|
|
241
243
|
const [state, setState] = useState(initialState);
|
|
242
244
|
// Variables
|
|
243
245
|
const { isOpenPopover } = state;
|
|
244
|
-
// Memo
|
|
245
246
|
const value = Array.isArray(selectedItems) && (selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length)
|
|
246
247
|
? `${(_a = selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.map(item => item.title)) === null || _a === void 0 ? void 0 : _a[0]}${((_b = selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.slice(1)) === null || _b === void 0 ? void 0 : _b.length) ? `, and +${(_c = selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.slice(1)) === null || _c === void 0 ? void 0 : _c.length} more` : ''}` || []
|
|
247
248
|
: undefined;
|
|
@@ -250,7 +251,9 @@ export const MatchesAnySelect = props => {
|
|
|
250
251
|
onChange(selectedItems);
|
|
251
252
|
setState(prev => (Object.assign(Object.assign({}, prev), { isOpenPopover: false })));
|
|
252
253
|
};
|
|
253
|
-
return (React.createElement(Popover, { open: isOpenPopover, arrow: false, placement: "bottomLeft", content: React.createElement(MatchesAny, { items: items, selectedItems: selectedItems,
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
return (React.createElement(Popover, { open: isOpenPopover, arrow: false, placement: "bottomLeft", content: React.createElement(MatchesAny, { className: popupClassName, items: items, selectedItems: selectedItems, loading: loading, objectName: objectName, onApply: onApplyMatchesAny, onCancel: () => setState(prev => (Object.assign(Object.assign({}, prev), { isOpenPopover: false }))) }), overlayStyle: { width: 700 }, overlayInnerStyle: {
|
|
255
|
+
padding: 0,
|
|
256
|
+
}, trigger: ['click'], destroyTooltipOnHide: true, onOpenChange: () => setState(prev => (Object.assign(Object.assign({}, prev), { isOpenPopover: !isOpenPopover }))) },
|
|
257
|
+
React.createElement(Tooltip, { mouseEnterDelay: 0.5, title: `${selectedItems ? selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.map(item => item.title).join(', ') : ''}` },
|
|
258
|
+
React.createElement(Select, Object.assign({ title: "", value: value, placeholder: placeholder, popupMatchSelectWidth: 700, dropdownStyle: Object.assign(Object.assign({}, dropdownStyle), { display: 'none', padding: 0 }), loading: loading }, restProps)))));
|
|
256
259
|
};
|
|
@@ -90,6 +90,19 @@ export const MatchesAnyWrapper = styled(Flex) `
|
|
|
90
90
|
align-items: center;
|
|
91
91
|
justify-content: space-between;
|
|
92
92
|
gap: 10px;
|
|
93
|
+
|
|
94
|
+
.title-content {
|
|
95
|
+
padding: 5px 0px;
|
|
96
|
+
display: flex;
|
|
97
|
+
flex-direction: column;
|
|
98
|
+
width: 100%;
|
|
99
|
+
height: 100%;
|
|
100
|
+
overflow: auto;
|
|
101
|
+
|
|
102
|
+
.sub-title {
|
|
103
|
+
font-size: 11px;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
93
106
|
}
|
|
94
107
|
}
|
|
95
108
|
|
|
@@ -113,7 +126,7 @@ export const MatchesAnyWrapper = styled(Flex) `
|
|
|
113
126
|
|
|
114
127
|
&.antsomi-tree-treenode-disabled {
|
|
115
128
|
.antsomi-typography {
|
|
116
|
-
color: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw6};
|
|
129
|
+
color: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw6} !important;
|
|
117
130
|
}
|
|
118
131
|
|
|
119
132
|
.select-button {
|
|
@@ -2,14 +2,16 @@ import { TreeDataNode } from 'antd';
|
|
|
2
2
|
import type { SelectProps } from '@antscorp/antsomi-ui/es/components/molecules';
|
|
3
3
|
import type { FlexProps } from '@antscorp/antsomi-ui/es/components/atoms';
|
|
4
4
|
export type MatchesAnyItem = TreeDataNode & {
|
|
5
|
+
/** Addition title of the item. */
|
|
6
|
+
subTitle?: string;
|
|
7
|
+
/** Indicates whether the item is extended */
|
|
5
8
|
isExtendValue?: boolean;
|
|
9
|
+
/** An array of children items. */
|
|
6
10
|
children?: MatchesAnyItem[];
|
|
7
11
|
};
|
|
8
12
|
export interface MatchesAnySelectProps extends SelectProps {
|
|
9
13
|
/** The name of object to be displayed in Popover */
|
|
10
14
|
objectName?: string;
|
|
11
|
-
/** Indicates whether the component is loading */
|
|
12
|
-
isLoading?: boolean;
|
|
13
15
|
/** Indicates whether show the extend value button */
|
|
14
16
|
showExtendValue?: boolean;
|
|
15
17
|
/** An array of items. */
|
|
@@ -23,7 +25,7 @@ export interface MatchesAnyProps extends Omit<FlexProps, 'children'> {
|
|
|
23
25
|
/** The name of the object, corresponding to the `objectName` property in `MatchesAnySelectProps`. */
|
|
24
26
|
objectName?: MatchesAnySelectProps['objectName'];
|
|
25
27
|
/** Indicates whether the component is in a loading state, corresponding to the `isLoading` property in `MatchesAnySelectProps`. */
|
|
26
|
-
|
|
28
|
+
loading?: MatchesAnySelectProps['loading'];
|
|
27
29
|
/** Determines whether to show the extended value, corresponding to the `showExtendValue` property in `MatchesAnySelectProps`. */
|
|
28
30
|
showExtendValue?: MatchesAnySelectProps['showExtendValue'];
|
|
29
31
|
/** An array of items. */
|
|
@@ -13,8 +13,8 @@ import { translations } from '@antscorp/antsomi-ui/es/locales/translations';
|
|
|
13
13
|
import { EXCEPTION_OFF_FILTER_CLASS } from '../../constants/filter';
|
|
14
14
|
export const AddFilterButton = memo(() => {
|
|
15
15
|
const { t } = i18nInstance;
|
|
16
|
-
const { openPopover, selectedFilterMetric, onSelectFilterMetric, onApplyFilterMetricCondition, onClickAddFilter, setState: setAddFilterConditionState, } = useAddFilterCondition();
|
|
17
|
-
return (React.createElement(Popover, { open: openPopover, content: React.createElement("div", { className: EXCEPTION_OFF_FILTER_CLASS }, selectedFilterMetric ? (React.createElement(FilterCondition, { filterMetric: selectedFilterMetric, onCancel: () => onSelectFilterMetric(undefined), onApply: ({ operator, value }) => {
|
|
16
|
+
const { openPopover, selectedFilterMetric, matchesAny, onSelectFilterMetric, onApplyFilterMetricCondition, onClickAddFilter, onChangeFilterCondition, setState: setAddFilterConditionState, } = useAddFilterCondition();
|
|
17
|
+
return (React.createElement(Popover, { open: openPopover, content: React.createElement("div", { className: EXCEPTION_OFF_FILTER_CLASS }, selectedFilterMetric ? (React.createElement(FilterCondition, { filterMetric: selectedFilterMetric, matchesAny: matchesAny, onCancel: () => onSelectFilterMetric(undefined), onApply: ({ operator, value }) => {
|
|
18
18
|
onApplyFilterMetricCondition({
|
|
19
19
|
filterMetric: selectedFilterMetric,
|
|
20
20
|
operator,
|
|
@@ -22,6 +22,15 @@ export const AddFilterButton = memo(() => {
|
|
|
22
22
|
});
|
|
23
23
|
onSelectFilterMetric(undefined);
|
|
24
24
|
setAddFilterConditionState(prev => (Object.assign(Object.assign({}, prev), { openPopover: false })));
|
|
25
|
+
}, onChange: condition => {
|
|
26
|
+
const { id, dataType } = selectedFilterMetric;
|
|
27
|
+
const { operator, value } = condition || {};
|
|
28
|
+
onChangeFilterCondition({
|
|
29
|
+
column: id,
|
|
30
|
+
operator,
|
|
31
|
+
value,
|
|
32
|
+
dataType,
|
|
33
|
+
});
|
|
25
34
|
} })) : (React.createElement(SavedFilterAndMetrics, { onSelectFilterMetric: onSelectFilterMetric, onSelectSavedFilter: () => {
|
|
26
35
|
setAddFilterConditionState(prev => (Object.assign(Object.assign({}, prev), { openPopover: false })));
|
|
27
36
|
} }))), trigger: ['click'], overlayInnerStyle: { width: 300, padding: 0 }, arrow: false, placement: "bottomLeft", destroyTooltipOnHide: true, onOpenChange: open => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { FilterItem, FilterMetricItem } from '../../../types';
|
|
2
|
+
import { FilterItem, FilterMetricItem, FilterProps } from '../../../types';
|
|
3
3
|
type TFormType = {
|
|
4
4
|
operator: string;
|
|
5
5
|
value: any;
|
|
@@ -7,8 +7,10 @@ type TFormType = {
|
|
|
7
7
|
interface FilterConditionProps {
|
|
8
8
|
filterMetric: FilterMetricItem;
|
|
9
9
|
filterCondition?: FilterItem;
|
|
10
|
+
matchesAny?: FilterProps['matchesAny'];
|
|
10
11
|
onCancel?: () => void;
|
|
11
12
|
onApply?: (values: TFormType) => void;
|
|
13
|
+
onChange?: (values: TFormType) => void;
|
|
12
14
|
}
|
|
13
15
|
export declare const FilterCondition: React.FC<FilterConditionProps>;
|
|
14
16
|
export {};
|
|
@@ -10,12 +10,12 @@ import { EXCEPTION_OFF_FILTER_CLASS } from '../../../constants/filter';
|
|
|
10
10
|
const { BETWEEN, EXISTS, NOT_EXISTS } = OPERATORS_OPTION;
|
|
11
11
|
export const FilterCondition = props => {
|
|
12
12
|
// Props
|
|
13
|
-
const { filterMetric, filterCondition, onCancel, onApply } = props;
|
|
13
|
+
const { filterMetric, filterCondition, matchesAny, onChange, onCancel, onApply } = props;
|
|
14
14
|
// Hooks
|
|
15
15
|
const [form] = Form.useForm();
|
|
16
16
|
// Form
|
|
17
|
-
const
|
|
18
|
-
const value =
|
|
17
|
+
const formValues = Form.useWatch([], form);
|
|
18
|
+
const { operator, value } = formValues || {};
|
|
19
19
|
// Variables
|
|
20
20
|
const { name, dataType, operators } = filterMetric;
|
|
21
21
|
// Memos
|
|
@@ -53,6 +53,12 @@ export const FilterCondition = props => {
|
|
|
53
53
|
operator: ((_a = operatorList[0]) === null || _a === void 0 ? void 0 : _a.value) || '',
|
|
54
54
|
});
|
|
55
55
|
}, [form, operatorList]);
|
|
56
|
+
/** Handle callback change values */
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (formValues) {
|
|
59
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(formValues);
|
|
60
|
+
}
|
|
61
|
+
}, [formValues, onChange]);
|
|
56
62
|
/* Update filter condition values */
|
|
57
63
|
useEffect(() => {
|
|
58
64
|
if (filterCondition) {
|
|
@@ -82,12 +88,13 @@ export const FilterCondition = props => {
|
|
|
82
88
|
React.createElement(Form.Item, { name: "operator", noStyle: true },
|
|
83
89
|
React.createElement(Select, { value: operator, options: operatorList, onChange: () => form.setFieldsValue({
|
|
84
90
|
value: '',
|
|
85
|
-
}),
|
|
91
|
+
}), dropdownRender: menu => (React.createElement("div", { className: EXCEPTION_OFF_FILTER_CLASS, onClick: e => e.stopPropagation() }, menu)) })),
|
|
86
92
|
React.createElement(Form.Item, { name: "value", noStyle: true }),
|
|
87
93
|
renderValueField({
|
|
88
94
|
filterMetric,
|
|
89
95
|
operator,
|
|
90
96
|
value,
|
|
97
|
+
matchesAny,
|
|
91
98
|
onChangeValue: value => {
|
|
92
99
|
form.setFieldsValue({
|
|
93
100
|
value,
|
|
@@ -6,7 +6,7 @@ import { Button, Flex, Icon, Popover } from '@antscorp/antsomi-ui/es/components/
|
|
|
6
6
|
import { FilterCondition } from './FilterCondition';
|
|
7
7
|
// Constants
|
|
8
8
|
import { EXCEPTION_OFF_FILTER_CLASS, FILTER_SHOW_MAX } from '../../constants/filter';
|
|
9
|
-
import {
|
|
9
|
+
import { globalToken } from '@antscorp/antsomi-ui/es/constants';
|
|
10
10
|
// Contexts
|
|
11
11
|
import { useDataTableContext } from '../../contexts/DataTableContext';
|
|
12
12
|
// Hooks
|
|
@@ -22,7 +22,7 @@ import { translations } from '@antscorp/antsomi-ui/es/locales/translations';
|
|
|
22
22
|
const { t } = i18nInstance;
|
|
23
23
|
export const FilterConditionList = memo(() => {
|
|
24
24
|
// Store
|
|
25
|
-
const { filterMetrics, filters, isFilterActive, onChangeFilters = () => { }, } = useDataTableContext(store => store.filter);
|
|
25
|
+
const { filterMetrics, filters, isFilterActive, matchesAny, onChangeFilters = () => { }, onChangeFilterCondition = () => { }, } = useDataTableContext(store => store.filter);
|
|
26
26
|
const setFilter = useDataTableContext(store => store.setFilter);
|
|
27
27
|
// State
|
|
28
28
|
/* Reserve for handle popover open per filter condition */
|
|
@@ -60,36 +60,38 @@ export const FilterConditionList = memo(() => {
|
|
|
60
60
|
onChangeFilters(cloneFilters || []);
|
|
61
61
|
};
|
|
62
62
|
const renderFilterItem = () => serializeFilters === null || serializeFilters === void 0 ? void 0 : serializeFilters.map((filter, index) => {
|
|
63
|
-
var _a;
|
|
64
63
|
const { column, operator, value, isOpenPopover } = filter;
|
|
65
64
|
const metric = flattenFilterMetrics === null || flattenFilterMetrics === void 0 ? void 0 : flattenFilterMetrics.find(filterMetric => filterMetric.id === column);
|
|
66
|
-
const operatorLabel = ((_a = Object.values(OPERATORS_OPTION).find(({ value }) => value === operator)) === null || _a === void 0 ? void 0 : _a.label) || '';
|
|
67
65
|
// Hide too many filter when filter is active
|
|
68
66
|
if (!metric || (!isFilterActive && index + 1 > FILTER_SHOW_MAX))
|
|
69
67
|
return null;
|
|
70
68
|
return (React.createElement(Popover, { key: `${column}-${operator}-${value}-${index}`, open: isOpenPopover, content: React.createElement("div", { className: EXCEPTION_OFF_FILTER_CLASS },
|
|
71
|
-
React.createElement(FilterCondition, { filterMetric: metric, filterCondition: filter, onApply: ({ operator, value }) => {
|
|
69
|
+
React.createElement(FilterCondition, { matchesAny: matchesAny, filterMetric: metric, filterCondition: filter, onApply: ({ operator, value }) => {
|
|
72
70
|
onApplyFilterMetricCondition({
|
|
73
71
|
operator,
|
|
74
72
|
value,
|
|
75
73
|
existMetricIdx: index,
|
|
76
74
|
});
|
|
77
75
|
handleTogglePopover(index, false);
|
|
76
|
+
}, onChange: condition => {
|
|
77
|
+
onChangeFilterCondition({
|
|
78
|
+
column: metric.id,
|
|
79
|
+
operator: condition.operator,
|
|
80
|
+
value: condition.value,
|
|
81
|
+
dataType: metric.dataType,
|
|
82
|
+
});
|
|
78
83
|
}, onCancel: () => handleTogglePopover(index, false) })), trigger: ['click'], overlayInnerStyle: { width: 300, padding: 0 }, arrow: false, placement: "bottomLeft", onOpenChange: open => handleTogglePopover(index, open) },
|
|
79
84
|
React.createElement(FilterItem, { gap: 5, onClick: () => setFilter({
|
|
80
85
|
isFilterActive: true,
|
|
81
|
-
}), name: (metric === null || metric === void 0 ? void 0 : metric.name) || column.toString() || '', operator:
|
|
86
|
+
}), name: (metric === null || metric === void 0 ? void 0 : metric.name) || column.toString() || '', operator: operator, value: value, onClickRemove: () => onClickRemoveFilter(index) })));
|
|
82
87
|
});
|
|
83
88
|
const renderViewAll = () => {
|
|
84
89
|
var _a;
|
|
85
90
|
if (isFilterActive || (serializeFilters === null || serializeFilters === void 0 ? void 0 : serializeFilters.length) <= FILTER_SHOW_MAX)
|
|
86
91
|
return null;
|
|
87
92
|
return (React.createElement(Popover, { open: isOpenViewAllPopover, content: React.createElement(Flex, { vertical: true, gap: 5 }, (_a = serializeFilters === null || serializeFilters === void 0 ? void 0 : serializeFilters.slice(3)) === null || _a === void 0 ? void 0 : _a.map((filter, index) => {
|
|
88
|
-
var _a;
|
|
89
93
|
const { column, operator, value } = filter;
|
|
90
94
|
const metric = flattenFilterMetrics === null || flattenFilterMetrics === void 0 ? void 0 : flattenFilterMetrics.find(filterMetric => filterMetric.id === column);
|
|
91
|
-
const operatorLabel = ((_a = Object.values(OPERATORS_OPTION).find(({ value }) => value === operator)) === null || _a === void 0 ? void 0 : _a.label) ||
|
|
92
|
-
'';
|
|
93
95
|
if (!metric)
|
|
94
96
|
return null;
|
|
95
97
|
return (React.createElement(FilterItem, { key: `${column}-${operator}-${value}-${index}`, gap: 5, onClick: () => {
|
|
@@ -100,7 +102,7 @@ export const FilterConditionList = memo(() => {
|
|
|
100
102
|
handleTogglePopover(FILTER_SHOW_MAX + index, true);
|
|
101
103
|
// Close popover view all
|
|
102
104
|
setState(prev => (Object.assign(Object.assign({}, prev), { isOpenViewAllPopover: false })));
|
|
103
|
-
}, name: (metric === null || metric === void 0 ? void 0 : metric.name) || column.toString() || '', operator:
|
|
105
|
+
}, name: (metric === null || metric === void 0 ? void 0 : metric.name) || column.toString() || '', operator: operator, value: value, onClickRemove: () => onClickRemoveFilter(index) }));
|
|
104
106
|
})), trigger: ['click'], overlayInnerStyle: { width: 300, padding: 15 }, arrow: false, onOpenChange: open => setState(prev => (Object.assign(Object.assign({}, prev), { isOpenViewAllPopover: open }))) },
|
|
105
107
|
React.createElement(Button, { type: "text", style: Object.assign({}, (isOpenViewAllPopover && { backgroundColor: globalToken === null || globalToken === void 0 ? void 0 : globalToken.blue1_1 })) },
|
|
106
108
|
t(translations.viewAll).toString(),
|
|
@@ -10,22 +10,52 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
// Libraries
|
|
13
|
-
import React from 'react';
|
|
13
|
+
import React, { useMemo } from 'react';
|
|
14
|
+
import dayjs from 'dayjs';
|
|
14
15
|
// Components
|
|
15
16
|
import { Icon, Typography } from '@antscorp/antsomi-ui/es/components/atoms';
|
|
16
17
|
// Styled
|
|
17
18
|
import { StyledFilterItem } from './styled';
|
|
19
|
+
// Constants
|
|
20
|
+
import { DATE_TIME_FORMAT, OPERATORS_CODE, OPERATORS_OPTION, } from '@antscorp/antsomi-ui/es/constants';
|
|
21
|
+
const { MATCHES_ANY, MATCHES, NOT_MATCHES, IS } = OPERATORS_CODE;
|
|
18
22
|
const { Text } = Typography;
|
|
19
23
|
export const FilterItem = props => {
|
|
20
24
|
const { name, operator, value, onClickRemove } = props, restProps = __rest(props, ["name", "operator", "value", "onClickRemove"]);
|
|
21
|
-
|
|
25
|
+
// Memo
|
|
26
|
+
const serializeValue = useMemo(() => {
|
|
27
|
+
// Check type of value is valid date
|
|
28
|
+
if (dayjs(value).isValid()) {
|
|
29
|
+
return dayjs(value).format(DATE_TIME_FORMAT.FILTER_CONDITION);
|
|
30
|
+
}
|
|
31
|
+
// Check value is an array and operator is MATCHES_ANY
|
|
32
|
+
if (Array.isArray(value) && operator === MATCHES_ANY) {
|
|
33
|
+
return value.map(item => item.title).join(', ');
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}, [operator, value]);
|
|
37
|
+
const serializeOperator = useMemo(() => {
|
|
38
|
+
var _a;
|
|
39
|
+
const operatorLabel = ((_a = Object.values(OPERATORS_OPTION).find(({ value }) => value === operator)) === null || _a === void 0 ? void 0 : _a.label) || '';
|
|
40
|
+
switch (operator) {
|
|
41
|
+
case MATCHES_ANY:
|
|
42
|
+
case NOT_MATCHES:
|
|
43
|
+
case MATCHES:
|
|
44
|
+
case IS:
|
|
45
|
+
return null;
|
|
46
|
+
default:
|
|
47
|
+
return operatorLabel;
|
|
48
|
+
}
|
|
49
|
+
}, [operator]);
|
|
50
|
+
const tooltipContent = `${name} ${operator} ${serializeValue}`;
|
|
22
51
|
return (React.createElement(StyledFilterItem, Object.assign({ gap: 5 }, restProps),
|
|
23
52
|
React.createElement(Text, { ellipsis: { tooltip: tooltipContent } },
|
|
24
|
-
React.createElement(Text,
|
|
25
|
-
" \u00A0",
|
|
26
|
-
React.createElement(Text, null, operator),
|
|
53
|
+
React.createElement(Text, null, name),
|
|
27
54
|
" \u00A0",
|
|
28
|
-
React.createElement(Text,
|
|
55
|
+
serializeOperator && React.createElement(Text, null,
|
|
56
|
+
serializeOperator,
|
|
57
|
+
" \u00A0"),
|
|
58
|
+
React.createElement(Text, { strong: true, className: "filter-item__value" }, serializeValue)),
|
|
29
59
|
React.createElement("div", { className: "filter-item__close-btn", onClick: e => {
|
|
30
60
|
e.stopPropagation();
|
|
31
61
|
if (onClickRemove) {
|
|
@@ -19,7 +19,7 @@ export const RowSelectedControl = memo(() => {
|
|
|
19
19
|
}
|
|
20
20
|
return (dropdownProps === null || dropdownProps === void 0 ? void 0 : dropdownProps.menu) ? (React.createElement(Dropdown, Object.assign({ key: key, trigger: ['click'], arrow: false, placement: "bottomLeft", overlayStyle: { minWidth: 200 } }, dropdownProps), buttonComponent)) : (buttonComponent);
|
|
21
21
|
};
|
|
22
|
-
return (React.createElement(RowSelectedControlWrapper, { align: "center" },
|
|
22
|
+
return (React.createElement(RowSelectedControlWrapper, { className: "selected-control", align: "center" },
|
|
23
23
|
React.createElement(Flex, { className: "selected-count-label", align: "center" },
|
|
24
24
|
(selectedRowKeys === null || selectedRowKeys === void 0 ? void 0 : selectedRowKeys.length) || 0,
|
|
25
25
|
" selected"),
|
|
@@ -38,6 +38,7 @@ export const FilterSection = styled(Flex) `
|
|
|
38
38
|
cursor: pointer;
|
|
39
39
|
`;
|
|
40
40
|
export const RowSelectedControlWrapper = styled(Flex) `
|
|
41
|
+
flex-shrink: 0;
|
|
41
42
|
height: ${toolbarHeight}px;
|
|
42
43
|
background-color: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.colorPrimary};
|
|
43
44
|
color: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw0};
|
|
@@ -12,10 +12,15 @@ type OnApplyFilterMetricConditionValue = {
|
|
|
12
12
|
};
|
|
13
13
|
export declare const useAddFilterCondition: () => {
|
|
14
14
|
filters: import("../types").FilterItem[] | undefined;
|
|
15
|
+
matchesAny: {
|
|
16
|
+
list?: import("../../..").MatchesAnyItem[] | undefined;
|
|
17
|
+
isLoading?: boolean | undefined;
|
|
18
|
+
} | undefined;
|
|
15
19
|
setState: import("react").Dispatch<import("react").SetStateAction<TState>>;
|
|
16
20
|
onSelectFilterMetric: (filterMetric?: FilterMetricItem) => void;
|
|
17
21
|
onApplyFilterMetricCondition: (values: OnApplyFilterMetricConditionValue) => void;
|
|
18
22
|
onClickAddFilter: () => void;
|
|
23
|
+
onChangeFilterCondition: (filterItem: import("../types").FilterItem) => void;
|
|
19
24
|
openPopover?: boolean | undefined;
|
|
20
25
|
selectedFilterMetric?: FilterMetricItem | undefined;
|
|
21
26
|
};
|
|
@@ -10,7 +10,7 @@ export const useAddFilterCondition = () => {
|
|
|
10
10
|
selectedFilterMetric: undefined,
|
|
11
11
|
});
|
|
12
12
|
// Store
|
|
13
|
-
const { filters, onChangeFilters = () => { } } = useDataTableContext(store => store.filter);
|
|
13
|
+
const { filters, matchesAny, onChangeFilters = () => { }, onChangeFilterCondition = () => { }, } = useDataTableContext(store => store.filter);
|
|
14
14
|
const setFilter = useDataTableContext(store => store.setFilter);
|
|
15
15
|
// Handlers
|
|
16
16
|
const onSelectFilterMetric = useCallback((filterMetric) => {
|
|
@@ -48,9 +48,11 @@ export const useAddFilterCondition = () => {
|
|
|
48
48
|
return Object.assign(Object.assign({}, state), {
|
|
49
49
|
// Filter
|
|
50
50
|
filters,
|
|
51
|
+
matchesAny,
|
|
51
52
|
// Handlers
|
|
52
53
|
setState,
|
|
53
54
|
onSelectFilterMetric,
|
|
54
55
|
onApplyFilterMetricCondition,
|
|
55
|
-
onClickAddFilter
|
|
56
|
+
onClickAddFilter,
|
|
57
|
+
onChangeFilterCondition });
|
|
56
58
|
};
|
|
@@ -7,9 +7,14 @@ import { PaginationProps } from '../../components';
|
|
|
7
7
|
import { ColumnType } from 'antd/es/table';
|
|
8
8
|
import { SorterResult } from 'antd/es/table/interface';
|
|
9
9
|
import { TGetColumnMetrics, TGetFilterMetricList, TGetModifyColumnList, TGetSavedFilterList, TGetSearchListing, TGetTableListing } from '@antscorp/antsomi-ui/es/queries';
|
|
10
|
+
import { MatchesAnyItem } from '@antscorp/antsomi-ui/es/components/molecules';
|
|
10
11
|
export type TApiGlobal = AxiosRequestConfig<any> & {
|
|
11
12
|
enabled?: boolean;
|
|
12
13
|
};
|
|
14
|
+
type TMatchesAnyParams = (filterItem?: FilterItem) => any | any;
|
|
15
|
+
type TMatchesAnyProps = {
|
|
16
|
+
formatData: (response: any) => MatchesAnyItem[];
|
|
17
|
+
};
|
|
13
18
|
export type TConfig<TTableType = any> = {
|
|
14
19
|
env?: TEnv;
|
|
15
20
|
auth?: TServiceAuth;
|
|
@@ -19,8 +24,12 @@ export type TConfig<TTableType = any> = {
|
|
|
19
24
|
filter?: TApiGlobal;
|
|
20
25
|
search?: TApiGlobal;
|
|
21
26
|
matchesAny?: {
|
|
22
|
-
general: TApiGlobal
|
|
23
|
-
|
|
27
|
+
general: Omit<TApiGlobal, 'params'> & {
|
|
28
|
+
params?: TMatchesAnyParams;
|
|
29
|
+
};
|
|
30
|
+
} & Partial<Record<keyof TTableType, Omit<TApiGlobal, 'params'> & {
|
|
31
|
+
params?: TMatchesAnyParams;
|
|
32
|
+
}>>;
|
|
24
33
|
};
|
|
25
34
|
object?: {
|
|
26
35
|
type: number;
|
|
@@ -48,7 +57,7 @@ type TSearchProps<TSearchType> = Partial<Pick<TSearchActionButton, 'addFilterInf
|
|
|
48
57
|
};
|
|
49
58
|
export interface UseDataTableListingProps<TTableType = any, TSearchType = any> {
|
|
50
59
|
name?: string;
|
|
51
|
-
config: TConfig
|
|
60
|
+
config: TConfig<TTableType>;
|
|
52
61
|
queryOptions?: {
|
|
53
62
|
getTableListing?: TGetTableListing['options'];
|
|
54
63
|
getColumnMetricList?: TGetColumnMetrics['options'];
|
|
@@ -68,6 +77,9 @@ export interface UseDataTableListingProps<TTableType = any, TSearchType = any> {
|
|
|
68
77
|
filter?: {
|
|
69
78
|
externalFilters?: FilterItem[];
|
|
70
79
|
includeDataType?: boolean;
|
|
80
|
+
matchesAny?: {
|
|
81
|
+
general: TMatchesAnyProps;
|
|
82
|
+
} & Partial<Record<keyof TTableType, TMatchesAnyProps>>;
|
|
71
83
|
};
|
|
72
84
|
}
|
|
73
85
|
export interface DataTableLocalStorage<TTableType = any> {
|
|
@@ -47,6 +47,7 @@ type TState<TTableType = any> = {
|
|
|
47
47
|
};
|
|
48
48
|
searchValue?: string;
|
|
49
49
|
sorter?: SorterResult<TTableType>;
|
|
50
|
+
selectedFilterItem?: FilterItem;
|
|
50
51
|
};
|
|
51
52
|
export declare function useDataTableListing<TTableType = Record<string, any>, TSearchType = any>(props: UseDataTableListingProps<TTableType, TSearchType>): TUseDataTableListing<TTableType>;
|
|
52
53
|
export {};
|