@antscorp/antsomi-ui 1.3.5-beta.473 → 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.
Files changed (37) hide show
  1. package/es/components/icons/EventIcon.js +1 -1
  2. package/es/components/molecules/DatePicker/DatePicker.js +6 -0
  3. package/es/components/molecules/MatchAnySelect/MatchesAnySelect.js +14 -11
  4. package/es/components/molecules/MatchAnySelect/styled.js +14 -1
  5. package/es/components/molecules/MatchAnySelect/types.d.ts +5 -3
  6. package/es/components/organism/DataTable/components/Filter/AddFilterButton.js +11 -2
  7. package/es/components/organism/DataTable/components/Filter/FilterCondition/index.d.ts +3 -1
  8. package/es/components/organism/DataTable/components/Filter/FilterCondition/index.js +11 -4
  9. package/es/components/organism/DataTable/components/Filter/FilterConditionList.js +12 -10
  10. package/es/components/organism/DataTable/components/Filter/FilterItem.js +36 -6
  11. package/es/components/organism/DataTable/components/Toolbar/styled.js +1 -1
  12. package/es/components/organism/DataTable/constants/theme.js +2 -0
  13. package/es/components/organism/DataTable/hooks/useAddFilterButton.d.ts +5 -0
  14. package/es/components/organism/DataTable/hooks/useAddFilterButton.js +4 -2
  15. package/es/components/organism/DataTable/hooks/useDataTableListing/types.d.ts +15 -3
  16. package/es/components/organism/DataTable/hooks/useDataTableListing/useDataTableListing.d.ts +1 -0
  17. package/es/components/organism/DataTable/hooks/useDataTableListing/useDataTableListing.js +59 -13
  18. package/es/components/organism/DataTable/types/filter.d.ts +7 -0
  19. package/es/components/organism/DataTable/utils/filter.d.ts +4 -2
  20. package/es/components/organism/DataTable/utils/filter.js +46 -10
  21. package/es/constants/condition.d.ts +15 -0
  22. package/es/constants/condition.js +15 -0
  23. package/es/constants/datetime.d.ts +4 -0
  24. package/es/constants/datetime.js +4 -0
  25. package/es/constants/queries.d.ts +1 -0
  26. package/es/constants/queries.js +1 -0
  27. package/es/constants/theme.js +1 -0
  28. package/es/locales/en/translation.json +2 -1
  29. package/es/locales/i18n.d.ts +2 -0
  30. package/es/locales/translations.d.ts +1 -0
  31. package/es/locales/vi/translation.json +2 -1
  32. package/es/queries/DataTable/index.d.ts +6 -1
  33. package/es/queries/DataTable/index.js +5 -1
  34. package/es/services/DataTable/index.d.ts +7 -0
  35. package/es/services/DataTable/index.js +16 -4
  36. package/es/tests/DataTableTest.js +45 -12
  37. 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: "M19 4h-1V2h-2v2H8V2H6v2H5c-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-2zm0 16H5V10h14v10zm0-12H5V6h14v2zm-7 5h5v5h-5z" })));
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, isLoading = false, showExtendValue = true, items, onApply = () => { }, onCancel = () => { } } = props, restOfProps = __rest(props, ["objectName", "isLoading", "showExtendValue", "items", "onApply", "onCancel"]);
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(Text, { ellipsis: { tooltip: true } }, title),
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: isLoading },
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, title: t(translations.noData).toString() })))))));
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: isLoading },
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, isLoading, onChange = () => { } } = props, restProps = __rest(props, ["placeholder", "dropdownStyle", "objectName", "selectedItems", "items", "isLoading", "onChange"]);
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, isLoading: isLoading, objectName: objectName, style: { margin: '-8px 0px' }, onApply: onApplyMatchesAny, onCancel: () => setState(prev => (Object.assign(Object.assign({}, prev), { isOpenPopover: false }))) }), overlayStyle: { width: 700 }, trigger: ['click'], destroyTooltipOnHide: true, onOpenChange: () => setState(prev => (Object.assign(Object.assign({}, prev), { isOpenPopover: !isOpenPopover }))) },
254
- React.createElement(Tooltip, { mouseEnterDelay: 0.5, title: `${selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.map(item => item.title).join(', ')}` },
255
- React.createElement(Select, Object.assign({ title: "", value: value, placeholder: placeholder, popupMatchSelectWidth: 700, dropdownStyle: Object.assign(Object.assign({}, dropdownStyle), { display: 'none', padding: 0 }) }, restProps)))));
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
- isLoading?: MatchesAnySelectProps['isLoading'];
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 operator = Form.useWatch('operator', form);
18
- const value = Form.useWatch('value', form);
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
- }), getPopupContainer: node => node.parentElement, dropdownRender: menu => (React.createElement("div", { className: EXCEPTION_OFF_FILTER_CLASS, onClick: e => e.stopPropagation() }, menu)) })),
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 { OPERATORS_OPTION, globalToken } from '@antscorp/antsomi-ui/es/constants';
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: operatorLabel, value: value, onClickRemove: () => onClickRemoveFilter(index) })));
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: operatorLabel, value: value, onClickRemove: () => onClickRemoveFilter(index) }));
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
- const tooltipContent = `${name} ${operator} ${value}`;
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, { strong: true }, name),
25
- " \u00A0",
26
- React.createElement(Text, null, operator),
53
+ React.createElement(Text, null, name),
27
54
  " \u00A0",
28
- React.createElement(Text, { strong: true, className: "filter-item__value" }, value)),
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) {
@@ -38,7 +38,7 @@ export const FilterSection = styled(Flex) `
38
38
  cursor: pointer;
39
39
  `;
40
40
  export const RowSelectedControlWrapper = styled(Flex) `
41
- flex: 1;
41
+ flex-shrink: 0;
42
42
  height: ${toolbarHeight}px;
43
43
  background-color: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.colorPrimary};
44
44
  color: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.bw0};
@@ -20,6 +20,8 @@ export const DATA_TABLE_THEME = {
20
20
  rowHoverBg: '#DEEFFE',
21
21
  borderRadius: 0,
22
22
  headerBorderRadius: 0,
23
+ rowSelectedBg: '#DEEFFE',
24
+ rowSelectedHoverBg: '#F2F9FF',
23
25
  },
24
26
  Menu: {
25
27
  itemBorderRadius: 0,
@@ -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
- } & Partial<Record<keyof TTableType, TApiGlobal>>;
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 {};
@@ -28,17 +28,18 @@ import { useAppConfigContext } from '@antscorp/antsomi-ui/es/providers';
28
28
  // Components
29
29
  import { Typography, Switch, Flex } from '@antscorp/antsomi-ui/es/components/atoms';
30
30
  // Constants
31
- import { COLUMN_DOMAIN, QUERY_KEYS, globalToken } from '@antscorp/antsomi-ui/es/constants';
31
+ import { COLUMN_DOMAIN, OPERATORS_CODE, QUERY_KEYS, globalToken, } from '@antscorp/antsomi-ui/es/constants';
32
32
  import { MODIFY_COLUMN_DISABLE_EDITABLE, MODIFY_COLUMN_DISABLE_REMOVE, SAVED_FILTER_DEFAULT, TABLE_LISTING_PREFIX, } from './constants';
33
33
  import { DEFAULT_CELL_EMPTY, DEFAULT_TOGGLE_WIDTH, SORT_MAP } from '../../constants';
34
34
  // Hooks
35
35
  import { useDeepCompareEffect, useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
36
- import { useCreateModifyColumn, useDeleteModifyColumn, useDeleteSavedFilter, useGetColumnMetrics, useGetFilterMetricList, useGetModifyColumnList, useGetSavedFilterList, useGetSearchListing, useGetTableListing, useSaveFilter, useUpdateFilter, useUpdateModifyColumn, } from '@antscorp/antsomi-ui/es/queries';
36
+ import { useCreateModifyColumn, useDeleteModifyColumn, useDeleteSavedFilter, useGetColumnMetrics, useGetFilterMetricList, useGetMatchesAnyList, useGetModifyColumnList, useGetSavedFilterList, useGetSearchListing, useGetTableListing, useSaveFilter, useUpdateFilter, useUpdateModifyColumn, } from '@antscorp/antsomi-ui/es/queries';
37
37
  // Utils
38
38
  import { flatTree, mapResponseSearchToGeneral, parseJSONFromLocalStorage, } from '@antscorp/antsomi-ui/es/utils';
39
39
  import { METRIC_MAP_NUMBER_TYPE } from '../../constants/filter';
40
40
  import { mapFiltersToApiFilters, mapFiltersToRules, mapRulesToFilters } from '../../utils';
41
41
  const { Text } = Typography;
42
+ const { MATCHES, MATCHES_ANY, NOT_MATCHES } = OPERATORS_CODE;
42
43
  const initialState = {
43
44
  filters: [],
44
45
  selectedFilterId: SAVED_FILTER_DEFAULT[0].id,
@@ -58,9 +59,10 @@ const initialState = {
58
59
  },
59
60
  searchValue: '',
60
61
  sorter: {},
62
+ selectedFilterItem: undefined,
61
63
  };
62
64
  export function useDataTableListing(props) {
63
- var _a, _b;
65
+ var _a, _b, _c;
64
66
  // Props
65
67
  const { config, name = 'default', table: tableProps, search: searchProps, filter: filterProps, queryOptions, } = props || {};
66
68
  // Hooks
@@ -70,18 +72,25 @@ export function useDataTableListing(props) {
70
72
  const [state, setState] = useState(initialState);
71
73
  // Variables
72
74
  const { env = appConfig === null || appConfig === void 0 ? void 0 : appConfig.env, auth = appConfig === null || appConfig === void 0 ? void 0 : appConfig.auth, api, object } = config;
73
- const { column: apiColumn, filter: apiFilter, listing: apiListing, search: apiSearch, } = api || {};
74
- const _c = apiColumn || {}, { url: columnUrl = `${COLUMN_DOMAIN[env || 'development']}/api/column`, enabled: enabledApiColumn = true } = _c, restOfApiColumnRequest = __rest(_c, ["url", "enabled"]);
75
- const _d = apiFilter || {}, { url: filterUrl = `${COLUMN_DOMAIN[env || 'development']}/api/filter`, enabled: enabledApiFilter = true } = _d, restOfApiFilterRequest = __rest(_d, ["url", "enabled"]);
76
- const _e = apiListing || {}, { url: listingUrl = '', enabled: enabledApiListing = true } = _e, restOfApiListingRequest = __rest(_e, ["url", "enabled"]);
77
- const _f = apiSearch || {}, { url: searchUrl = '', enabled: enabledApiSearch = true } = _f, restOfApiSearchRequest = __rest(_f, ["url", "enabled"]);
78
- const { filters, selectedFilterId, pagination, selectedRowKeys, searchValue, table, sorter, selectedRow, } = state;
79
- const { externalFilters, includeDataType = false } = filterProps || {};
75
+ const { column: apiColumn, filter: apiFilter, listing: apiListing, search: apiSearch, matchesAny: apiMatchesAny, } = api || {};
76
+ const _d = apiColumn || {}, { url: columnUrl = `${COLUMN_DOMAIN[env || 'development']}/api/column`, enabled: enabledApiColumn = true } = _d, restOfApiColumnRequest = __rest(_d, ["url", "enabled"]);
77
+ const _e = apiFilter || {}, { url: filterUrl = `${COLUMN_DOMAIN[env || 'development']}/api/filter`, enabled: enabledApiFilter = true } = _e, restOfApiFilterRequest = __rest(_e, ["url", "enabled"]);
78
+ const _f = apiListing || {}, { url: listingUrl = '', enabled: enabledApiListing = true } = _f, restOfApiListingRequest = __rest(_f, ["url", "enabled"]);
79
+ const _g = apiSearch || {}, { url: searchUrl = '', enabled: enabledApiSearch = true } = _g, restOfApiSearchRequest = __rest(_g, ["url", "enabled"]);
80
+ const { filters, selectedFilterId, pagination, selectedRowKeys, searchValue, table, sorter, selectedRow, selectedFilterItem, } = state;
81
+ const { externalFilters, includeDataType = false, matchesAny } = filterProps || {};
80
82
  const { sortDirectionKey = 'az', mainColumnKey } = tableProps || {};
81
83
  const modifyColumnAuth = Object.assign(Object.assign({}, auth), { url: columnUrl });
82
84
  const filterAuth = Object.assign(Object.assign({}, auth), { url: filterUrl });
83
85
  const listingAuth = Object.assign(Object.assign({}, auth), { url: listingUrl });
84
86
  const searchAuth = Object.assign(Object.assign({}, auth), { url: searchUrl });
87
+ /**
88
+ * If has api config for specific selectedFilterItem, use it
89
+ * Otherwise use general api config
90
+ */
91
+ const matchesAnyRequest = (apiMatchesAny === null || apiMatchesAny === void 0 ? void 0 : apiMatchesAny[`${selectedFilterItem === null || selectedFilterItem === void 0 ? void 0 : selectedFilterItem.column}`.toLowerCase()])
92
+ ? apiMatchesAny === null || apiMatchesAny === void 0 ? void 0 : apiMatchesAny[`${selectedFilterItem === null || selectedFilterItem === void 0 ? void 0 : selectedFilterItem.column}`.toLowerCase()]
93
+ : apiMatchesAny === null || apiMatchesAny === void 0 ? void 0 : apiMatchesAny.general;
85
94
  // Memos
86
95
  const mapObject = useMemo(() => ({
87
96
  objType: object === null || object === void 0 ? void 0 : object.type,
@@ -122,13 +131,26 @@ export function useDataTableListing(props) {
122
131
  },
123
132
  options: Object.assign({ enabled: enabledApiFilter }, queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.getFilterMetricList),
124
133
  });
134
+ const getMatchesAnyList = useGetMatchesAnyList({
135
+ args: {
136
+ auth,
137
+ params: (_a = matchesAnyRequest === null || matchesAnyRequest === void 0 ? void 0 : matchesAnyRequest.params) === null || _a === void 0 ? void 0 : _a.call(matchesAnyRequest, selectedFilterItem),
138
+ request: matchesAnyRequest,
139
+ },
140
+ options: {
141
+ enabled: !!selectedFilterItem &&
142
+ [MATCHES_ANY, NOT_MATCHES, MATCHES].includes(selectedFilterItem.operator),
143
+ keepPreviousData: true,
144
+ retry: false,
145
+ },
146
+ });
125
147
  // Variables
126
148
  const { data: modifyColumnsData, isLoading: isModifyColumnsLoading } = getModifyColumnList || {};
127
149
  const modifyColumnSelected = useDeepCompareMemo(() => { var _a; return ((_a = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(({ isLasted }) => +isLasted === 1)) === null || _a === void 0 ? void 0 : _a.modifyColId) || ''; }, [modifyColumnsData]);
128
150
  const getTableListing = useGetTableListing({
129
151
  args: {
130
152
  auth: listingAuth,
131
- params: Object.assign({ limit: pagination.pageSize, page: pagination.page, filter: JSON.stringify(mapFiltersToApiFilters([...(filters || []), ...(externalFilters || [])], includeDataType)), columns: JSON.stringify(((_b = (_a = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(modifyColumnItem => modifyColumnItem.modifyColId === modifyColumnSelected)) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.map(col => { var _a; return (_a = col.metricCode) === null || _a === void 0 ? void 0 : _a.toUpperCase(); })) || []) }, ((sorter === null || sorter === void 0 ? void 0 : sorter.order) &&
153
+ params: Object.assign({ limit: pagination.pageSize, page: pagination.page, filter: JSON.stringify(mapFiltersToApiFilters([...(filters || []), ...(externalFilters || [])], includeDataType)), columns: JSON.stringify(((_c = (_b = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(modifyColumnItem => modifyColumnItem.modifyColId === modifyColumnSelected)) === null || _b === void 0 ? void 0 : _b.columns) === null || _c === void 0 ? void 0 : _c.map(col => { var _a; return (_a = col.metricCode) === null || _a === void 0 ? void 0 : _a.toUpperCase(); })) || []) }, ((sorter === null || sorter === void 0 ? void 0 : sorter.order) &&
132
154
  (sorter === null || sorter === void 0 ? void 0 : sorter.columnKey) && {
133
155
  sort: sorter.columnKey.toString(),
134
156
  [sortDirectionKey]: SORT_MAP[sorter.order],
@@ -154,6 +176,7 @@ export function useDataTableListing(props) {
154
176
  const { data: tableListing, isLoading: isTableListingLoading, isRefetching: isTableListingRefetching, } = getTableListing || {};
155
177
  const { body: tableBody, header: tableHeader, total } = tableListing || {};
156
178
  const { data: searchListingData, isLoading: isSearchListingLoading, isFetching: isSearchListingFetching, } = getSearchListing || {};
179
+ const { data: matchesAnyListData, isLoading: isMatchesAnyListLoading } = getMatchesAnyList || {};
157
180
  // Conditionally format search listing data based on the presence of a formatData function in searchProps.
158
181
  // If formatData is defined, use it to format searchListingData.
159
182
  // Otherwise, use the mapResponseSearchToGeneral function to format searchListingData.
@@ -272,6 +295,20 @@ export function useDataTableListing(props) {
272
295
  const { itemMapKeys, icon, link } = searchProps || {};
273
296
  return ((searchListingBody === null || searchListingBody === void 0 ? void 0 : searchListingBody.map(searchItem => (Object.assign(Object.assign({}, Object.entries(itemMapKeys || {}).reduce((acc, [key, value]) => (Object.assign(Object.assign({}, acc), { [key]: searchItem[value] })), {})), { icon: typeof icon === 'function' ? icon(searchItem) : icon, link: typeof link === 'function' ? link(searchItem) : link })))) || []);
274
297
  }, [searchListingData, searchProps]);
298
+ const matchesAnyList = useMemo(() => {
299
+ /**
300
+ * If `selectedFilterItem` has a column, the function will attempt to find a matching property in the `matchesAny`
301
+ * object by converting the column name to lowercase. If such a property does not exist, it will default to using
302
+ * the `general` property from the `matchesAny` object.
303
+ */
304
+ const matchesAnyProps = (matchesAny === null || matchesAny === void 0 ? void 0 : matchesAny[`${selectedFilterItem === null || selectedFilterItem === void 0 ? void 0 : selectedFilterItem.column}`.toLowerCase()])
305
+ ? matchesAny === null || matchesAny === void 0 ? void 0 : matchesAny[`${selectedFilterItem === null || selectedFilterItem === void 0 ? void 0 : selectedFilterItem.column}`.toLowerCase()]
306
+ : matchesAny === null || matchesAny === void 0 ? void 0 : matchesAny.general;
307
+ if (matchesAnyListData) {
308
+ return matchesAnyProps.formatData(matchesAnyListData);
309
+ }
310
+ return [];
311
+ }, [matchesAny, matchesAnyListData, selectedFilterItem === null || selectedFilterItem === void 0 ? void 0 : selectedFilterItem.column]);
275
312
  // Effects
276
313
  /**
277
314
  * Update values from local storage to state
@@ -314,7 +351,7 @@ export function useDataTableListing(props) {
314
351
  });
315
352
  }, [mapObject, updateModifyColumn]);
316
353
  const onApplyModifyColumn = useCallback((args) => __awaiter(this, void 0, void 0, function* () {
317
- var _g;
354
+ var _h;
318
355
  const { selectedMetrics, columnSetName, existColumnSet } = args || {};
319
356
  const flattenMetrics = flatTree(columnMetricsData, 'child');
320
357
  const selectedColumnMetrics = selectedMetrics
@@ -327,7 +364,7 @@ export function useDataTableListing(props) {
327
364
  exitModifyColumnId = (existColumnSet === null || existColumnSet === void 0 ? void 0 : existColumnSet.id) || '';
328
365
  if (columnSetName === '') {
329
366
  exitModifyColumnId =
330
- ((_g = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(modifyColumn => modifyColumn.modifyName === 'Custom')) === null || _g === void 0 ? void 0 : _g.modifyColId) || '';
367
+ ((_h = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(modifyColumn => modifyColumn.modifyName === 'Custom')) === null || _h === void 0 ? void 0 : _h.modifyColId) || '';
331
368
  }
332
369
  }
333
370
  /**
@@ -379,12 +416,16 @@ export function useDataTableListing(props) {
379
416
  // Set Local Storage
380
417
  localStorage.setItem(localStorageKey, JSON.stringify(Object.assign(Object.assign({}, localStorageValues), { sorter })));
381
418
  }, [localStorageKey]);
419
+ /* Filter */
382
420
  const onChangeFilters = useCallback((filters) => {
383
421
  handleUpdateFilter({
384
422
  filters,
385
423
  selectedFilterId: SAVED_FILTER_DEFAULT[0].id,
386
424
  });
387
425
  }, [handleUpdateFilter]);
426
+ const onChangeFilterCondition = useCallback((filterItem) => {
427
+ setState(prev => (Object.assign(Object.assign({}, prev), { selectedFilterItem: filterItem })));
428
+ }, []);
388
429
  const onSaveFilter = useCallback((args) => __awaiter(this, void 0, void 0, function* () {
389
430
  const { filters, name, existSavedFilter } = args;
390
431
  // Update exits filter
@@ -483,8 +524,13 @@ export function useDataTableListing(props) {
483
524
  },
484
525
  filters,
485
526
  filterMetrics,
527
+ matchesAny: {
528
+ list: matchesAnyList,
529
+ isLoading: isMatchesAnyListLoading,
530
+ },
486
531
  onSaveFilter,
487
532
  onChangeFilters,
533
+ onChangeFilterCondition,
488
534
  },
489
535
  /* Pagination */
490
536
  pagination: Object.assign(Object.assign({}, pagination), { total, onChange: onChangePagination }),
@@ -1,3 +1,4 @@
1
+ import { MatchesAnyItem } from '../../../molecules';
1
2
  import { FILTER_ACTION_KEYS } from '../constants/filter';
2
3
  import { TActionButton, TConfirmResponse } from '@antscorp/antsomi-ui/es/types';
3
4
  export type TActionFilterButtonKey<T extends string[] = []> = (typeof FILTER_ACTION_KEYS)[keyof typeof FILTER_ACTION_KEYS] | T[number];
@@ -40,8 +41,14 @@ export interface FilterProps<TActionKey extends string[] = []> {
40
41
  savedFilter?: SavedFilter;
41
42
  filterMetrics?: FilterMetricItem[];
42
43
  filters?: FilterItem[];
44
+ matchesAny?: {
45
+ list?: MatchesAnyItem[];
46
+ isLoading?: boolean;
47
+ };
43
48
  actionButtons?: Partial<Record<TActionFilterButtonKey<TActionKey>, TActionButton>>;
44
49
  onChangeFilters?: (filters: FilterItem[]) => void;
45
50
  onSaveFilter?: (args: TOnSaveFilterArgs) => Promise<TConfirmResponse>;
51
+ /** Handle callback when filter condition changed */
52
+ onChangeFilterCondition?: (filterItem: FilterItem) => void;
46
53
  }
47
54
  export type TApiFilter = Record<string, any>[];
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { MenuProps } from 'antd';
3
3
  import { FilterItem, FilterMetricItem, TApiFilter } from '../types';
4
4
  import { SavedFilter } from '@antscorp/antsomi-ui/es/models/DataTable/SavedFilter';
5
+ import { FilterProps } from '../..';
5
6
  type MenuItem = Required<MenuProps>['items'][number];
6
7
  type TSerializeFilterMetricsToMenuItems = {
7
8
  filterMetrics: FilterMetricItem[];
@@ -12,7 +13,8 @@ type TSerializeFilterMetricsToMenuItems = {
12
13
  type TRenderValueField = {
13
14
  filterMetric: FilterMetricItem;
14
15
  operator: string;
15
- value?: string;
16
+ value?: any;
17
+ matchesAny?: FilterProps['matchesAny'];
16
18
  onChangeValue?: (value: any) => void;
17
19
  };
18
20
  type TGetFilterMetricByName = {
@@ -71,7 +73,7 @@ export declare const serializeFilterMetricsToMenuItems: ({ filterMetrics, level,
71
73
  * // ]
72
74
  */
73
75
  export declare const flatFilterMetrics: (filterMetrics: FilterMetricItem[]) => FilterMetricItem[];
74
- export declare const renderValueField: ({ filterMetric, operator, value, onChangeValue, }: TRenderValueField) => React.JSX.Element | null;
76
+ export declare const renderValueField: ({ filterMetric, operator, value, matchesAny, onChangeValue, }: TRenderValueField) => React.JSX.Element | null;
75
77
  /**
76
78
  * Retrieves a filter metric by its name from a collection of filter metrics.
77
79
  *
@@ -2,17 +2,19 @@
2
2
  import React from 'react';
3
3
  import { isEmpty } from 'lodash';
4
4
  import i18nInstance from '@antscorp/antsomi-ui/es/locales/i18n';
5
+ import dayjs from 'dayjs';
5
6
  // Components
6
7
  import { Popover, Typography, Icon, FormatInputNumber, Flex, Input } from '../../../atoms';
7
- import { METRIC_TYPE } from '@antscorp/antsomi-ui/es/constants';
8
+ import { DATE_TIME_FORMAT, DATE_TIME_FORMAT_DISPLAY, METRIC_TYPE, } from '@antscorp/antsomi-ui/es/constants';
8
9
  import { Menu } from '../..';
10
+ import { DatePicker, MatchesAnySelect } from '../../../molecules';
9
11
  // Styled
10
12
  import { FilterMetricLabel } from '../styled';
11
13
  import { OPERATORS_CODE } from '@antscorp/antsomi-ui/es/constants/condition';
12
14
  // Translations
13
15
  import { translations } from '@antscorp/antsomi-ui/es/locales/translations';
14
- import { METRIC_MAP_NUMBER_TYPE, METRIC_MAP_STRING_TYPE } from '../constants/filter';
15
- import { MatchesAnySelect } from '../../../molecules';
16
+ import { EXCEPTION_OFF_FILTER_CLASS, METRIC_MAP_NUMBER_TYPE, METRIC_MAP_STRING_TYPE, } from '../constants/filter';
17
+ const { MATCHES, MATCHES_ANY, NOT_MATCHES, ON, BEFORE, BEFORE_DATE, AFTER, AFTER_DATE } = OPERATORS_CODE;
16
18
  const { t } = i18nInstance;
17
19
  const { Text } = Typography;
18
20
  /* Filter */
@@ -102,9 +104,8 @@ export const flatFilterMetrics = (filterMetrics) => filterMetrics.reduce((acc, c
102
104
  return [...acc, cur];
103
105
  }, []);
104
106
  /* Render Value Field */
105
- export const renderValueField = ({ filterMetric, operator, value, onChangeValue = () => { }, }) => {
106
- const { dataType } = filterMetric;
107
- console.log('🚀 ~ filterMetric:', filterMetric);
107
+ export const renderValueField = ({ filterMetric, operator, value, matchesAny, onChangeValue = () => { }, }) => {
108
+ const { dataType, name } = filterMetric;
108
109
  switch (operator) {
109
110
  case OPERATORS_CODE.GREATER_THAN:
110
111
  case OPERATORS_CODE.GREATER_THAN_EQUAL:
@@ -143,7 +144,15 @@ export const renderValueField = ({ filterMetric, operator, value, onChangeValue
143
144
  case OPERATORS_CODE.MATCHES:
144
145
  case OPERATORS_CODE.MATCHES_ANY:
145
146
  case OPERATORS_CODE.NOT_MATCHES: {
146
- return React.createElement(MatchesAnySelect, null);
147
+ const { list, isLoading } = matchesAny || {};
148
+ return (React.createElement(MatchesAnySelect, { selectedItems: value, popupClassName: EXCEPTION_OFF_FILTER_CLASS, objectName: name, items: list, loading: isLoading, onChange: onChangeValue }));
149
+ }
150
+ case OPERATORS_CODE.AFTER:
151
+ case OPERATORS_CODE.AFTER_DATE:
152
+ case OPERATORS_CODE.BEFORE:
153
+ case OPERATORS_CODE.ON:
154
+ case OPERATORS_CODE.BEFORE_DATE: {
155
+ return (React.createElement(DatePicker, { placeholder: DATE_TIME_FORMAT_DISPLAY.FILTER_CONDITION, format: DATE_TIME_FORMAT_DISPLAY.FILTER_CONDITION, allowClear: false, popupClassName: EXCEPTION_OFF_FILTER_CLASS, value: dayjs(value).isValid() ? dayjs(value) : undefined, onChange: onChangeValue }));
147
156
  }
148
157
  default:
149
158
  return null;
@@ -179,6 +188,33 @@ export const mapRulesToFilters = (rules) => rules.map(({ dataType, metricCode, o
179
188
  operator: operatorValue,
180
189
  value: filterValue,
181
190
  }));
182
- export const mapFiltersToApiFilters = (filters, includeDataType = false) => filters.map(({ column, operator, value, dataType }) => ({
183
- [column]: Object.assign({ [operator]: value }, (includeDataType && { dataType: METRIC_MAP_STRING_TYPE[dataType || 'string'] })),
184
- }));
191
+ export const mapFiltersToApiFilters = (filters, includeDataType = false) => filters.map(({ column, operator, value, dataType }) => {
192
+ let serializeValue = '';
193
+ switch (operator) {
194
+ case MATCHES:
195
+ case MATCHES_ANY:
196
+ case NOT_MATCHES: {
197
+ if (Array.isArray(value)) {
198
+ serializeValue = value.map(item => item.key);
199
+ }
200
+ break;
201
+ }
202
+ /** Date time */
203
+ case AFTER:
204
+ case AFTER_DATE:
205
+ case BEFORE:
206
+ case ON:
207
+ case BEFORE_DATE: {
208
+ if (dayjs(value).isValid()) {
209
+ serializeValue = dayjs(value).format(DATE_TIME_FORMAT.FILTER_CONDITION);
210
+ }
211
+ break;
212
+ }
213
+ default:
214
+ serializeValue = value;
215
+ break;
216
+ }
217
+ return {
218
+ [column]: Object.assign({ [operator]: serializeValue }, (includeDataType && { dataType: METRIC_MAP_STRING_TYPE[dataType || 'string'] })),
219
+ };
220
+ });
@@ -29,6 +29,9 @@ export declare const OPERATORS_CODE: {
29
29
  readonly CONTAIN: "contain";
30
30
  readonly DOES_NOT_CONTAIN: "does_not_contain";
31
31
  readonly IS: "is";
32
+ readonly ON: "on";
33
+ readonly AFTER: "after";
34
+ readonly BEFORE: "before";
32
35
  };
33
36
  export declare const OPERATORS_OPTION: {
34
37
  GREATER_THAN: {
@@ -151,6 +154,18 @@ export declare const OPERATORS_OPTION: {
151
154
  label: string;
152
155
  value: "is";
153
156
  };
157
+ ON: {
158
+ label: string;
159
+ value: "on";
160
+ };
161
+ AFTER: {
162
+ label: string;
163
+ value: "after";
164
+ };
165
+ BEFORE: {
166
+ label: string;
167
+ value: "before";
168
+ };
154
169
  };
155
170
  export declare const OPERATORS: {
156
171
  number: {
@@ -29,6 +29,9 @@ export const OPERATORS_CODE = {
29
29
  CONTAIN: 'contain',
30
30
  DOES_NOT_CONTAIN: 'does_not_contain',
31
31
  IS: 'is',
32
+ ON: 'on',
33
+ AFTER: 'after',
34
+ BEFORE: 'before',
32
35
  };
33
36
  const { GREATER_THAN, GREATER_THAN_EQUAL, LESS_THAN, LESS_THAN_EQUAL, NOT_EQUALS, EQUALS, BETWEEN, EXISTS, NOT_EXISTS, CONTAINS, DOESNT_CONTAIN, START_WITH, NOT_START_WITH, END_WITH, NOT_END_WITH, BEFORE_DATE, } = OPERATORS_CODE;
34
37
  export const OPERATORS_OPTION = {
@@ -152,6 +155,18 @@ export const OPERATORS_OPTION = {
152
155
  label: 'is',
153
156
  value: OPERATORS_CODE.IS,
154
157
  },
158
+ ON: {
159
+ label: 'on',
160
+ value: OPERATORS_CODE.ON,
161
+ },
162
+ AFTER: {
163
+ label: 'is',
164
+ value: OPERATORS_CODE.AFTER,
165
+ },
166
+ BEFORE: {
167
+ label: 'before',
168
+ value: OPERATORS_CODE.BEFORE,
169
+ },
155
170
  };
156
171
  export const OPERATORS = {
157
172
  number: {
@@ -5,4 +5,8 @@ export declare const TIME_ZONES: {
5
5
  export declare const DATE_TIME_FORMAT: {
6
6
  TITLE_DATE_TIME: string;
7
7
  DATE_TIME: string;
8
+ FILTER_CONDITION: string;
9
+ };
10
+ export declare const DATE_TIME_FORMAT_DISPLAY: {
11
+ FILTER_CONDITION: string;
8
12
  };
@@ -1591,4 +1591,8 @@ export const TIME_ZONES = [
1591
1591
  export const DATE_TIME_FORMAT = {
1592
1592
  TITLE_DATE_TIME: 'YYYY-MM-DD HH:mm:ss',
1593
1593
  DATE_TIME: 'DD/MM/YYYY - HH:mm:ss',
1594
+ FILTER_CONDITION: 'DD/MM/YYYY',
1595
+ };
1596
+ export const DATE_TIME_FORMAT_DISPLAY = {
1597
+ FILTER_CONDITION: 'MM/DD/YYYY',
1594
1598
  };
@@ -33,4 +33,5 @@ export declare const QUERY_KEYS: {
33
33
  GET_SAVED_FILTER_LIST: string;
34
34
  GET_FILTER_METRIC_LIST: string;
35
35
  GET_SEARCH_LIST: string;
36
+ GET_MATCHES_ANY_LIST: string;
36
37
  };
@@ -46,4 +46,5 @@ export const QUERY_KEYS = {
46
46
  GET_SAVED_FILTER_LIST: 'GET_SAVED_FILTER_LIST',
47
47
  GET_FILTER_METRIC_LIST: 'GET_FILTER_METRIC_LIST',
48
48
  GET_SEARCH_LIST: 'GET_SEARCH_LIST',
49
+ GET_MATCHES_ANY_LIST: 'GET_MATCHES_ANY_LIST',
49
50
  };
@@ -152,6 +152,7 @@ THEME.components = {
152
152
  borderRadiusSM: 0,
153
153
  borderRadiusOuter: 0,
154
154
  borderRadiusXS: 0,
155
+ paddingInline: 5,
155
156
  colorBorder: (_s = THEME.token) === null || _s === void 0 ? void 0 : _s.blue1,
156
157
  controlItemBgActive: '#E0EBF7',
157
158
  colorBgContainerDisabled: (_t = THEME.token) === null || _t === void 0 ? void 0 : _t.bw2,
@@ -9,7 +9,8 @@
9
9
  "removeAll": "Remove All",
10
10
  "selectAll": "Select All",
11
11
  "selected": "Selected",
12
- "selectItemsFromList": "Select items from the list"
12
+ "selectItemsFromList": "Select items from the list",
13
+ "noResultsMatchesKeyWord": "No result matches for your keyword"
13
14
  },
14
15
  "form": {
15
16
  "placeholder": {
@@ -12,6 +12,7 @@ export declare const translationsJson: {
12
12
  selectAll: string;
13
13
  selected: string;
14
14
  selectItemsFromList: string;
15
+ noResultsMatchesKeyWord: string;
15
16
  };
16
17
  form: {
17
18
  placeholder: {
@@ -610,6 +611,7 @@ export declare const translationsJson: {
610
611
  selectAll: string;
611
612
  selected: string;
612
613
  selectItemsFromList: string;
614
+ noResultsMatchesKeyWord: string;
613
615
  };
614
616
  form: {
615
617
  placeholder: {
@@ -12,6 +12,7 @@ export declare const convertLanguageJsonToObject: (json: any, objToConvertTo?: C
12
12
  selectAll: string;
13
13
  selected: string;
14
14
  selectItemsFromList: string;
15
+ noResultsMatchesKeyWord: string;
15
16
  };
16
17
  form: {
17
18
  placeholder: {
@@ -9,7 +9,8 @@
9
9
  "removeAll": "Xóa tất cả",
10
10
  "selectAll": "Chọn tất cả",
11
11
  "selected": "Đã chọn",
12
- "selectItemsFromList": "Chọn các mục từ danh sách"
12
+ "selectItemsFromList": "Chọn các mục từ danh sách",
13
+ "noResultsMatchesKeyWord": "Không có kết quả nào phù hợp với từ khóa của bạn"
13
14
  },
14
15
  "form": {
15
16
  "placeholder": {
@@ -1,5 +1,5 @@
1
1
  import { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
2
- import { TCreateModifyColumnArgs, TDeleteModifyColumnArgs, TDeleteSavedFilterArgs, TGetFilterMetricListArgs, TGetMetricListArgs, TGetModifyColumnListArgs, TGetSavedFilterListArgs, TGetSearchListingArgs, TGetTableListingArgs, TSaveFilterArgs, TUpdateFilterArgs, TUpdateModifyColumnArgs } from '../../services/DataTable';
2
+ import { TCreateModifyColumnArgs, TDeleteModifyColumnArgs, TDeleteSavedFilterArgs, TGetFilterMetricListArgs, TGetMatchesAnyListArgs, TGetMetricListArgs, TGetModifyColumnListArgs, TGetSavedFilterListArgs, TGetSearchListingArgs, TGetTableListingArgs, TSaveFilterArgs, TUpdateFilterArgs, TUpdateModifyColumnArgs } from '../../services/DataTable';
3
3
  import { ColumnMetric, FilterMetric, ModifyColumn } from '../../models/DataTable';
4
4
  import { SavedFilter } from '../../models/DataTable/SavedFilter';
5
5
  import { DataTableListing } from '../../models/DataTable/DataTableListing';
@@ -37,6 +37,10 @@ export type TGetFilterMetricList = {
37
37
  args: TGetFilterMetricListArgs;
38
38
  options?: UseQueryOptions<FilterMetric[], any, FilterMetric[], any[]>;
39
39
  };
40
+ export type TGetMatchesAnyList = {
41
+ args: TGetMatchesAnyListArgs;
42
+ options?: UseQueryOptions<any, any, any, any[]>;
43
+ };
40
44
  export type TSaveFilter = {
41
45
  auth: TSaveFilterArgs['auth'];
42
46
  options?: UseMutationOptions<{
@@ -87,3 +91,4 @@ export declare const useDeleteSavedFilter: (params?: TDeleteSavedFilter) => impo
87
91
  }, any, TDeleteSavedFilterArgs, unknown>;
88
92
  export declare const useGetTableListing: <T>(params: TGetTableListing<T>) => import("@tanstack/react-query").UseQueryResult<DataTableListing<T>, any>;
89
93
  export declare const useGetSearchListing: (params: TGetSearchListing) => import("@tanstack/react-query").UseQueryResult<any, any>;
94
+ export declare const useGetMatchesAnyList: (params: TGetMatchesAnyList) => import("@tanstack/react-query").UseQueryResult<any, any>;
@@ -5,7 +5,7 @@ import { omit } from 'lodash';
5
5
  import { dataTableServices, } from '../../services/DataTable';
6
6
  // Constants
7
7
  import { QUERY_KEYS } from '../../constants';
8
- const { GET_COLUMN_METRICS, GET_MODIFY_COLUMN_LIST, GET_SAVED_FILTER_LIST, GET_FILTER_METRIC_LIST, GET_SEARCH_LIST, GET_DATA_TABLE_LISTING, } = QUERY_KEYS;
8
+ const { GET_COLUMN_METRICS, GET_MODIFY_COLUMN_LIST, GET_SAVED_FILTER_LIST, GET_FILTER_METRIC_LIST, GET_SEARCH_LIST, GET_MATCHES_ANY_LIST, GET_DATA_TABLE_LISTING, } = QUERY_KEYS;
9
9
  /* Column */
10
10
  export const useGetColumnMetrics = (params) => {
11
11
  const { args, options } = params;
@@ -87,3 +87,7 @@ export const useGetSearchListing = (params) => {
87
87
  const { args, options } = params || {};
88
88
  return useQuery(Object.assign({ queryKey: [GET_SEARCH_LIST, args], queryFn: ({ signal }) => dataTableServices.search.getSearchListing(Object.assign(Object.assign({}, args), { request: Object.assign(Object.assign({}, args.request), { signal }) })) }, options));
89
89
  };
90
+ export const useGetMatchesAnyList = (params) => {
91
+ const { args, options } = params || {};
92
+ return useQuery(Object.assign({ queryKey: [GET_MATCHES_ANY_LIST, args], queryFn: ({ signal }) => dataTableServices.filter.getMatchesAnyList(Object.assign(Object.assign({}, args), { request: Object.assign(Object.assign({}, args.request), { signal }) })) }, options));
93
+ };
@@ -8,6 +8,7 @@ export type TGlobalApiParams = {
8
8
  objType?: number;
9
9
  objId?: number;
10
10
  actionType?: number;
11
+ [key: string]: any;
11
12
  };
12
13
  export type TGetMetricListArgs = {
13
14
  auth?: TServiceAuth;
@@ -51,6 +52,11 @@ export type TGetFilterMetricListArgs = {
51
52
  params?: TGlobalApiParams;
52
53
  request?: AxiosRequestConfig<any>;
53
54
  };
55
+ export type TGetMatchesAnyListArgs = {
56
+ auth?: TServiceAuth;
57
+ params?: TGlobalApiParams;
58
+ request?: AxiosRequestConfig<any>;
59
+ };
54
60
  export type TSaveFilterArgs = {
55
61
  auth?: TServiceAuth;
56
62
  data?: TGlobalApiParams & {
@@ -118,6 +124,7 @@ export declare const dataTableServices: {
118
124
  deleteSavedFilter: ({ auth, params, }: TDeleteSavedFilterArgs) => Promise<{
119
125
  status: number;
120
126
  }>;
127
+ getMatchesAnyList: ({ auth, params, request }: TGetMatchesAnyListArgs) => Promise<any>;
121
128
  };
122
129
  listing: {
123
130
  getTableListing<T = any>({ auth, params, request, }: TGetTableListingArgs): Promise<DataTableListing<T>>;
@@ -104,7 +104,7 @@ export const dataTableServices = {
104
104
  try {
105
105
  const { url } = auth || {};
106
106
  const { type = GET_SAVED_FILTER, objType: object, objId } = params || {};
107
- const response = yield axios(Object.assign(Object.assign({}, request), { url, method: 'GET', params: Object.assign(Object.assign({ type,
107
+ const response = yield axios(Object.assign(Object.assign({ url, method: 'GET' }, request), { params: Object.assign(Object.assign({ type,
108
108
  object,
109
109
  objId }, mapAuth(auth)), request === null || request === void 0 ? void 0 : request.params) }));
110
110
  return get(response, 'data.data.filters', []);
@@ -117,7 +117,7 @@ export const dataTableServices = {
117
117
  try {
118
118
  const { url } = auth || {};
119
119
  const { type = GET_LIST_FILTER, objType: object, objId } = params || {};
120
- const response = yield axios(Object.assign(Object.assign({}, request), { url, method: 'GET', params: Object.assign(Object.assign({ type,
120
+ const response = yield axios(Object.assign(Object.assign({ url, method: 'GET' }, request), { params: Object.assign(Object.assign({ type,
121
121
  object,
122
122
  objId }, mapAuth(auth)), request === null || request === void 0 ? void 0 : request.params) }));
123
123
  return get(response, 'data.data.filters', []);
@@ -180,12 +180,24 @@ export const dataTableServices = {
180
180
  return Promise.reject(error);
181
181
  }
182
182
  }),
183
+ getMatchesAnyList: (_r) => __awaiter(void 0, [_r], void 0, function* ({ auth, params, request }) {
184
+ try {
185
+ const { url } = auth || {};
186
+ const _s = request || {}, { method = 'GET' } = _s, restOfRequest = __rest(_s, ["method"]);
187
+ const response = yield axios(Object.assign(Object.assign({ url,
188
+ method }, restOfRequest), { params: Object.assign(Object.assign(Object.assign({}, mapAuth(auth)), params), request === null || request === void 0 ? void 0 : request.params) }));
189
+ return get(response, 'data.data', {});
190
+ }
191
+ catch (error) {
192
+ return Promise.reject(error);
193
+ }
194
+ }),
183
195
  },
184
196
  listing: {
185
197
  getTableListing(_a) {
186
198
  return __awaiter(this, arguments, void 0, function* ({ auth, params, request, }) {
187
199
  try {
188
- const response = yield axios(Object.assign(Object.assign({}, request), { url: `${auth === null || auth === void 0 ? void 0 : auth.url}`, method: 'GET', params: Object.assign(Object.assign(Object.assign({}, params), mapAuth(auth)), request === null || request === void 0 ? void 0 : request.params) }));
200
+ const response = yield axios(Object.assign(Object.assign({ url: `${auth === null || auth === void 0 ? void 0 : auth.url}`, method: 'GET' }, request), { params: Object.assign(Object.assign(Object.assign({}, params), mapAuth(auth)), request === null || request === void 0 ? void 0 : request.params) }));
189
201
  return mapResponseListingToGeneral(get(response, 'data.data', {}));
190
202
  }
191
203
  catch (error) {
@@ -200,7 +212,7 @@ export const dataTableServices = {
200
212
  const { search } = params || {};
201
213
  const _b = request || {}, { method = 'GET' } = _b, restOfRequest = __rest(_b, ["method"]);
202
214
  try {
203
- const response = yield axios(Object.assign(Object.assign({}, restOfRequest), { method, url: `${auth === null || auth === void 0 ? void 0 : auth.url}`, params: Object.assign(Object.assign({ search }, mapAuth(auth)), request === null || request === void 0 ? void 0 : request.params) }));
215
+ const response = yield axios(Object.assign(Object.assign({ method, url: `${auth === null || auth === void 0 ? void 0 : auth.url}` }, restOfRequest), { params: Object.assign(Object.assign({ search }, mapAuth(auth)), request === null || request === void 0 ? void 0 : request.params) }));
204
216
  return get(response, 'data.data', {});
205
217
  }
206
218
  catch (error) {
@@ -5,11 +5,11 @@ import { BrowserRouter } from 'react-router-dom';
5
5
  import { DataTable } from '../components/organism/DataTable';
6
6
  // Styled
7
7
  import { TableTestWrapper } from './styled';
8
+ // Constants
8
9
  import { useDataTableListing } from '../components/organism/DataTable/hooks/useDataTableListing';
9
- import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
10
10
  export const DataTableTest = () => {
11
11
  // Hooks
12
- const { filter, modifyColumn, pagination, table, search, queries, refetchTableListing } = useDataTableListing({
12
+ const { filter, modifyColumn, pagination, table, search } = useDataTableListing({
13
13
  name: 'survey-project',
14
14
  config: {
15
15
  // NOTES: This is no need pass auth props when had
@@ -38,15 +38,33 @@ export const DataTableTest = () => {
38
38
  page: 1,
39
39
  },
40
40
  },
41
+ matchesAny: {
42
+ general: {
43
+ url: `https://sandbox-survey.antsomi.com/api/v1/survey/filter/get-value-matches-any`,
44
+ params(filterItem) {
45
+ var _a;
46
+ return {
47
+ metric_code: (_a = filterItem === null || filterItem === void 0 ? void 0 : filterItem.column) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase(),
48
+ };
49
+ },
50
+ },
51
+ survey_id: {
52
+ url: 'https://sandbox-survey.antsomi.com/api/v1/survey/filter/get-value-matches-any',
53
+ params(filterItem) {
54
+ var _a;
55
+ return {
56
+ test: 'survey_id',
57
+ metric_code: (_a = filterItem === null || filterItem === void 0 ? void 0 : filterItem.column) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase(),
58
+ };
59
+ },
60
+ },
61
+ },
41
62
  },
42
63
  object: {
43
64
  type: 5, // Survey,
44
65
  objectId: -1, // NOTES: will note detail when to use objectId, current is no need
45
66
  },
46
67
  },
47
- // table: {
48
- // sortDirectionKey: 'sortDirection',
49
- // },
50
68
  search: {
51
69
  itemMapKeys: {
52
70
  id: 'survey_id',
@@ -64,20 +82,36 @@ export const DataTableTest = () => {
64
82
  formatData(response) {
65
83
  return (response === null || response === void 0 ? void 0 : response.body) || [];
66
84
  },
67
- onClickSearchItem(item) {
68
- console.log(item);
69
- },
70
85
  },
71
86
  queryOptions: {
72
87
  getTableListing: {
73
88
  refetchOnMount: 'always',
74
89
  },
75
90
  },
91
+ filter: {
92
+ matchesAny: {
93
+ general: {
94
+ formatData(response) {
95
+ return response === null || response === void 0 ? void 0 : response.rows.map(record => ({
96
+ key: record.value,
97
+ title: record.label,
98
+ }));
99
+ },
100
+ },
101
+ survey_id: {
102
+ formatData(response) {
103
+ return response === null || response === void 0 ? void 0 : response.rows.map(record => ({
104
+ key: record.value,
105
+ title: record.value,
106
+ }));
107
+ },
108
+ },
109
+ },
110
+ },
76
111
  });
77
112
  return (React.createElement(BrowserRouter, null,
78
113
  React.createElement(TableTestWrapper, null,
79
- React.createElement(DataTable, { table: Object.assign(Object.assign({}, table), { rowSelection: undefined }), filter: filter, toolbar: {
80
- addButton: {},
114
+ React.createElement(DataTable, { table: table, filter: filter, toolbar: {
81
115
  actionButtons: {
82
116
  SEARCH: search,
83
117
  COLUMN: modifyColumn,
@@ -97,6 +131,5 @@ export const DataTableTest = () => {
97
131
  },
98
132
  },
99
133
  },
100
- }, pagination: pagination })),
101
- React.createElement(ReactQueryDevtools, { initialIsOpen: false })));
134
+ }, pagination: pagination }))));
102
135
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.473",
3
+ "version": "1.3.5-beta.474",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",