@antscorp/antsomi-ui 1.3.5-beta.410 → 1.3.5-beta.412

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 (43) hide show
  1. package/es/components/organism/DataTable/components/AddButton/index.js +1 -1
  2. package/es/components/organism/DataTable/components/Table/styled.js +0 -1
  3. package/es/components/organism/DataTable/components/Toolbar/SearchPopover.d.ts +3 -1
  4. package/es/components/organism/DataTable/components/Toolbar/SearchPopover.js +17 -8
  5. package/es/components/organism/DataTable/components/Toolbar/ToolbarActionButtons.js +19 -4
  6. package/es/components/organism/DataTable/components/Toolbar/styled.d.ts +1 -0
  7. package/es/components/organism/DataTable/components/Toolbar/styled.js +3 -0
  8. package/es/components/organism/DataTable/constants/common.d.ts +2 -1
  9. package/es/components/organism/DataTable/constants/common.js +2 -1
  10. package/es/components/organism/DataTable/hooks/useDataTableListing/types.d.ts +16 -4
  11. package/es/components/organism/DataTable/hooks/useDataTableListing/useDataTableListing.d.ts +6 -3
  12. package/es/components/organism/DataTable/hooks/useDataTableListing/useDataTableListing.js +81 -25
  13. package/es/components/organism/DataTable/types/toolbar.d.ts +5 -2
  14. package/es/components/organism/LeftMenu/LeftMenu.js +1 -1
  15. package/es/components/organism/LeftMenu/components/common/ChildMenu/index.js +7 -50
  16. package/es/components/organism/LeftMenu/components/common/ChildMenu/styled.js +15 -10
  17. package/es/components/organism/LeftMenu/components/common/ChildMenu/utils.d.ts +5 -0
  18. package/es/components/organism/LeftMenu/components/common/ChildMenu/utils.js +52 -0
  19. package/es/components/organism/LeftMenu/hooks/usePermission.js +2 -1
  20. package/es/components/organism/LeftMenu/styled.d.ts +1 -0
  21. package/es/components/organism/LeftMenu/styled.js +6 -1
  22. package/es/components/organism/LeftMenu/utils/index.d.ts +2 -1
  23. package/es/components/organism/LeftMenu/utils/index.js +1 -1
  24. package/es/components/template/Layout/constants/menuCode.d.ts +2 -0
  25. package/es/components/template/Layout/constants/menuCode.js +2 -0
  26. package/es/components/template/Layout/constants/permission.d.ts +0 -2
  27. package/es/components/template/Layout/constants/permission.js +0 -2
  28. package/es/components/template/Layout/utils/permission.js +2 -0
  29. package/es/constants/queries.d.ts +1 -0
  30. package/es/constants/queries.js +1 -0
  31. package/es/models/DataTable/DataTableListing.d.ts +7 -0
  32. package/es/models/DataTable/SearchListing.d.ts +4 -0
  33. package/es/models/DataTable/SearchListing.js +1 -0
  34. package/es/models/DataTable/index.d.ts +1 -0
  35. package/es/models/DataTable/index.js +1 -0
  36. package/es/queries/DataTable/index.d.ts +7 -2
  37. package/es/queries/DataTable/index.js +5 -1
  38. package/es/services/DataTable/index.d.ts +11 -1
  39. package/es/services/DataTable/index.js +16 -2
  40. package/es/tests/DataTableTest.js +98 -61
  41. package/es/utils/dataTable.d.ts +6 -0
  42. package/es/utils/dataTable.js +18 -1
  43. package/package.json +2 -2
@@ -25,7 +25,7 @@ const StyledAddButton = styled(Flex) `
25
25
  cursor: pointer;
26
26
  `;
27
27
  export const AddButton = memo(props => {
28
- const { show } = props, restProps = __rest(props, ["show"]);
28
+ const { show = true } = props, restProps = __rest(props, ["show"]);
29
29
  if (!show)
30
30
  return null;
31
31
  return (React.createElement(StyledAddButton, Object.assign({ align: "center", justify: "center" }, restProps),
@@ -55,7 +55,6 @@ export const StyledTable = styled(Table) `
55
55
  align-items: center;
56
56
  justify-content: center;
57
57
  opacity: 0;
58
- transition: opacity 0.2s ease-in-out;
59
58
 
60
59
  &::after {
61
60
  content: '';
@@ -1,8 +1,10 @@
1
1
  import { PopoverProps } from 'antd';
2
2
  import React from 'react';
3
- import { TSearchActionButton } from '../../types';
3
+ import { TSearchActionButton, TSearchItem } from '../../types';
4
4
  interface SearchPopoverProps extends PopoverProps, TSearchActionButton {
5
5
  onAddFilter?: (value: string) => void;
6
+ onSearch?: (value: string) => void;
7
+ onClick?: (searchItem: TSearchItem) => void;
6
8
  }
7
9
  export declare const SearchPopover: React.FC<SearchPopoverProps>;
8
10
  export {};
@@ -13,7 +13,7 @@ import { Link } from 'react-router-dom';
13
13
  import React, { useState } from 'react';
14
14
  import styled from 'styled-components';
15
15
  // Components
16
- import { Input, Popover, Divider, Typography, Scrollbars, Icon, } from '@antscorp/antsomi-ui/es/components/atoms';
16
+ import { Input, Popover, Divider, Typography, Scrollbars, Icon, Spin, Flex, } from '@antscorp/antsomi-ui/es/components/atoms';
17
17
  import { Menu } from '@antscorp/antsomi-ui/es/components/organism';
18
18
  import { EmptyData } from '@antscorp/antsomi-ui/es/components/molecules';
19
19
  // Constants
@@ -24,7 +24,7 @@ import { useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
24
24
  import { searchStringQuery } from '@antscorp/antsomi-ui/es/utils';
25
25
  import i18nInstance from '@antscorp/antsomi-ui/es/locales/i18n';
26
26
  // Styles
27
- import { FilterSection } from './styled';
27
+ import { FilterSection, IconWrapper } from './styled';
28
28
  import { FilterButton } from '../../styled';
29
29
  // Translations
30
30
  import { translations } from '@antscorp/antsomi-ui/es/locales/translations';
@@ -50,7 +50,7 @@ const StyledContent = styled.div `
50
50
  }
51
51
  `;
52
52
  export const SearchPopover = props => {
53
- const { children, objectName, searchList, isClientSearch, onAddFilter = () => { }, itemSearchRender } = props, restProps = __rest(props, ["children", "objectName", "searchList", "isClientSearch", "onAddFilter", "itemSearchRender"]);
53
+ const { children, objectName, searchList, isClientSearch, loading, isAddFilterFromSearchItem, onAddFilter = () => { }, onSearch = () => { }, onClick = () => { }, onClickSearchItem, itemSearchRender } = props, restProps = __rest(props, ["children", "objectName", "searchList", "isClientSearch", "loading", "isAddFilterFromSearchItem", "onAddFilter", "onSearch", "onClick", "onClickSearchItem", "itemSearchRender"]);
54
54
  // State
55
55
  const [state, setState] = useState({
56
56
  searchValue: '',
@@ -70,11 +70,17 @@ export const SearchPopover = props => {
70
70
  draftSearchList = (searchList || []).filter(({ label }) => searchStringQuery(label, searchValue));
71
71
  }
72
72
  return draftSearchList.map((searchItem, index) => {
73
- const { id, label, path } = searchItem;
74
- const renderLabel = () => (React.createElement(Typography.Text, { className: `${path ? 'text-link' : ''}`, ellipsis: { tooltip: true } }, path ? React.createElement(Link, { to: path }, label) : label));
73
+ const { id, label, link, icon } = searchItem;
74
+ const Label = (React.createElement(Flex, { align: "center", gap: 6, style: { height: '100%' } },
75
+ icon && React.createElement(IconWrapper, null, icon),
76
+ React.createElement(Typography.Text, { className: `${link ? 'text-link' : ''}`, ellipsis: { tooltip: true } }, link && !itemSearchRender && !onClickSearchItem && !isAddFilterFromSearchItem ? (React.createElement(Link, { to: link }, label)) : (label))));
75
77
  return {
76
78
  key: id,
77
- label: itemSearchRender ? itemSearchRender(searchItem, index) : renderLabel(),
79
+ label: itemSearchRender ? itemSearchRender(searchItem, index, Label) : Label,
80
+ onClick: () => {
81
+ onClick(searchItem);
82
+ setState(prev => (Object.assign(Object.assign({}, prev), { isOpenPopover: false })));
83
+ },
78
84
  };
79
85
  });
80
86
  }, [isClientSearch, itemSearchRender, searchList, searchValue]);
@@ -109,12 +115,15 @@ export const SearchPopover = props => {
109
115
  React.createElement(Menu, { mode: "vertical", items: filteredSearchList }))));
110
116
  };
111
117
  const content = (React.createElement(StyledContent, null,
112
- React.createElement(Input.CustomSearch, { value: searchValue, onAfterChange: searchValue => setState(prev => (Object.assign(Object.assign({}, prev), { searchValue }))), onPressEnter: () => {
118
+ React.createElement(Input.CustomSearch, { value: searchValue, placeholder: t(translations.global.search).toString(), onAfterChange: searchValue => {
119
+ setState(prev => (Object.assign(Object.assign({}, prev), { searchValue })));
120
+ onSearch(searchValue);
121
+ }, onPressEnter: () => {
113
122
  handleAddFilter();
114
123
  } }),
115
124
  React.createElement(Divider, { style: { margin: '8px 0px' } }),
116
125
  renderFilterSection(),
117
- renderSearchList()));
126
+ React.createElement(Spin, { spinning: loading }, renderSearchList())));
118
127
  return (React.createElement(Popover, Object.assign({ open: isOpenPopover, content: content, overlayInnerStyle: { width: 300, padding: 0 }, trigger: ['click'], arrow: false, placement: "bottomRight" }, restProps, { onOpenChange: open => {
119
128
  // Reset search value to empty when close popover
120
129
  setState(prev => (Object.assign(Object.assign(Object.assign({}, prev), { isOpenPopover: open }), (!open && { searchValue: '' }))));
@@ -1,3 +1,14 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  // Libraries
2
13
  import React, { memo, useMemo } from 'react';
3
14
  import { useShallow } from 'zustand/react/shallow';
@@ -26,13 +37,12 @@ export const ToolbarActionButtons = memo(() => {
26
37
  return null;
27
38
  // Handlers
28
39
  const onAddFilterFromSearch = (value, addFilterInfo) => {
29
- const metric = flattenFilterMetrics.find(metric => metric.id === (addFilterInfo === null || addFilterInfo === void 0 ? void 0 : addFilterInfo.metricId));
40
+ const metric = flattenFilterMetrics.find(metric => { var _a; return metric.id.toString().toUpperCase() === ((_a = addFilterInfo === null || addFilterInfo === void 0 ? void 0 : addFilterInfo.metricId) === null || _a === void 0 ? void 0 : _a.toString().toUpperCase()); });
30
41
  // If metric is exist then call function setFilter to push new filter from metric and value
31
42
  if (metric && addFilterInfo) {
32
43
  const { id, dataType } = metric;
33
44
  const { operator } = addFilterInfo || {};
34
45
  onChangeFilters([
35
- ...(filters || []),
36
46
  {
37
47
  column: id,
38
48
  operator,
@@ -53,8 +63,13 @@ export const ToolbarActionButtons = memo(() => {
53
63
  return customRender(actionButton);
54
64
  switch (key) {
55
65
  case 'SEARCH': {
56
- const { searchList, itemSearchRender, isClientSearch, addFilterInfo } = action;
57
- return (React.createElement(SearchPopover, { key: key, searchList: searchList, isClientSearch: isClientSearch, itemSearchRender: itemSearchRender, onAddFilter: value => onAddFilterFromSearch(value, addFilterInfo) }, actionButton));
66
+ const _a = action, { addFilterInfo, onClickSearchItem, isAddFilterFromSearchItem } = _a, restOfAction = __rest(_a, ["addFilterInfo", "onClickSearchItem", "isAddFilterFromSearchItem"]);
67
+ return (React.createElement(SearchPopover, Object.assign({ key: key }, restOfAction, { isAddFilterFromSearchItem: isAddFilterFromSearchItem, onClickSearchItem: onClickSearchItem, onClick: searchItem => {
68
+ if (isAddFilterFromSearchItem) {
69
+ onAddFilterFromSearch(searchItem.label, addFilterInfo);
70
+ }
71
+ onClickSearchItem === null || onClickSearchItem === void 0 ? void 0 : onClickSearchItem(searchItem);
72
+ }, onAddFilter: value => onAddFilterFromSearch(value, addFilterInfo) }), actionButton));
58
73
  }
59
74
  case 'COLUMN': {
60
75
  return React.createElement(ModifyColumn, { key: key }, actionButton);
@@ -8,3 +8,4 @@ export declare const CollapseButton: import("styled-components").StyledComponent
8
8
  export declare const ToolbarActionButtonWrapper: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("antd/es/flex/interface").FlexProps<import("antd/es/_util/type").AnyObject> & import("react").RefAttributes<HTMLElement>>, any, {}, never>;
9
9
  export declare const FilterSection: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("antd/es/flex/interface").FlexProps<import("antd/es/_util/type").AnyObject> & import("react").RefAttributes<HTMLElement>>, any, {}, never>;
10
10
  export declare const RowSelectedControlWrapper: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("antd/es/flex/interface").FlexProps<import("antd/es/_util/type").AnyObject> & import("react").RefAttributes<HTMLElement>>, any, {}, never>;
11
+ export declare const IconWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -62,3 +62,6 @@ export const RowSelectedControlWrapper = styled(Flex) `
62
62
  }
63
63
  }
64
64
  `;
65
+ export const IconWrapper = styled.div `
66
+ flex-shrink: 0;
67
+ `;
@@ -5,4 +5,5 @@ declare const MIN_COLUMN_WIDTH = 55;
5
5
  declare const DEFAULT_ROW_SELECTION_WIDTH = 47;
6
6
  declare const DEFAULT_TOGGLE_WIDTH = 55;
7
7
  declare const DEFAULT_COLUMN_WIDTHS: number[];
8
- export { DATA_TABLE_DEFAULT_NAME, DATA_TABLE_PREFIX, DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_SELECTION_WIDTH, MIN_COLUMN_WIDTH, DEFAULT_COLUMN_WIDTHS, DEFAULT_TOGGLE_WIDTH, };
8
+ declare const DEFAULT_CELL_EMPTY = "--";
9
+ export { DATA_TABLE_DEFAULT_NAME, DATA_TABLE_PREFIX, DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_SELECTION_WIDTH, MIN_COLUMN_WIDTH, DEFAULT_COLUMN_WIDTHS, DEFAULT_TOGGLE_WIDTH, DEFAULT_CELL_EMPTY, };
@@ -6,4 +6,5 @@ const DEFAULT_FIRST_COLUMN_WIDTH = 200;
6
6
  const DEFAULT_ROW_SELECTION_WIDTH = 47;
7
7
  const DEFAULT_TOGGLE_WIDTH = 55;
8
8
  const DEFAULT_COLUMN_WIDTHS = [DEFAULT_FIRST_COLUMN_WIDTH].concat(Array.from({ length: 20 }, () => DEFAULT_COLUMN_WIDTH));
9
- export { DATA_TABLE_DEFAULT_NAME, DATA_TABLE_PREFIX, DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_SELECTION_WIDTH, MIN_COLUMN_WIDTH, DEFAULT_COLUMN_WIDTHS, DEFAULT_TOGGLE_WIDTH, };
9
+ const DEFAULT_CELL_EMPTY = '--';
10
+ export { DATA_TABLE_DEFAULT_NAME, DATA_TABLE_PREFIX, DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_SELECTION_WIDTH, MIN_COLUMN_WIDTH, DEFAULT_COLUMN_WIDTHS, DEFAULT_TOGGLE_WIDTH, DEFAULT_CELL_EMPTY, };
@@ -1,9 +1,10 @@
1
1
  import { TServiceAuth } from '@antscorp/antsomi-ui/es/types';
2
2
  import { TEnv } from '@antscorp/antsomi-ui/es/types/config';
3
3
  import { AxiosRequestConfig } from 'axios';
4
- import { FilterItem, TableProps } from '../../types';
4
+ import { FilterItem, TSearchActionButton, TSearchItem, TableProps } from '../../types';
5
5
  import { PaginationProps } from '../../components';
6
6
  import { ColumnType } from 'antd/es/table';
7
+ import { ReactNode } from 'react';
7
8
  export type TApiGlobal = AxiosRequestConfig<any> & {
8
9
  enabled?: boolean;
9
10
  };
@@ -14,19 +15,24 @@ export type TConfig = {
14
15
  listing?: TApiGlobal;
15
16
  column?: TApiGlobal;
16
17
  filter?: TApiGlobal;
18
+ search?: TApiGlobal;
17
19
  };
18
20
  object?: {
19
21
  type: number;
20
22
  objectId: number;
21
23
  };
22
24
  };
23
- type TToggleColumnType<TTableType> = ColumnType<TTableType> & {
25
+ type TGeneralTableColumnType<TTableType> = Omit<ColumnType<TTableType>, 'render'> & {
26
+ link?: ((record: TTableType) => string) | string;
27
+ render?: (value: any, record: TTableType, index: number, node: ReactNode) => ReactNode;
28
+ };
29
+ type TToggleColumnType<TTableType> = TGeneralTableColumnType<TTableType> & {
24
30
  value?: ((record: TTableType) => boolean) | boolean;
25
31
  valueKey?: keyof TTableType;
26
32
  onChange?: (checked: boolean, record: TTableType) => void;
27
33
  };
28
- type TTableColumnType<TTableType, K extends keyof TTableType | 'toggle'> = K extends 'toggle' ? TToggleColumnType<TTableType> : ColumnType<TTableType>;
29
- export interface UseDataTableListingProps<TTableType = any> {
34
+ type TTableColumnType<TTableType, K extends keyof TTableType | 'toggle'> = K extends 'toggle' ? TToggleColumnType<TTableType> : TGeneralTableColumnType<TTableType>;
35
+ export interface UseDataTableListingProps<TTableType = any, TSearchType = any> {
30
36
  config: TConfig;
31
37
  name?: string;
32
38
  table?: Omit<TableProps<TTableType>, 'columns'> & {
@@ -35,6 +41,12 @@ export interface UseDataTableListingProps<TTableType = any> {
35
41
  [K in keyof TTableType | 'toggle']?: TTableColumnType<TTableType, K>;
36
42
  };
37
43
  };
44
+ search?: Pick<TSearchActionButton, 'addFilterInfo' | 'isClientSearch' | 'isAddFilterFromSearchItem' | 'onClickSearchItem'> & {
45
+ link?: ((record: TSearchType) => string) | string;
46
+ icon?: (record: TSearchType) => ReactNode | ReactNode;
47
+ itemMapKeys: Record<keyof Omit<TSearchItem, 'icon' | 'link'>, keyof TSearchType>;
48
+ render?: (record: TSearchType, index: number, node: ReactNode) => ReactNode;
49
+ };
38
50
  }
39
51
  export interface DataTableLocalStorage {
40
52
  filter?: {
@@ -1,13 +1,14 @@
1
1
  import React from 'react';
2
- import { useGetColumnMetrics, useGetFilterMetricList, useGetModifyColumnList, useGetSavedFilterList, useGetTableListing } from '@antscorp/antsomi-ui/es/queries';
2
+ import { useGetColumnMetrics, useGetFilterMetricList, useGetModifyColumnList, useGetSavedFilterList, useGetSearchListing, useGetTableListing } from '@antscorp/antsomi-ui/es/queries';
3
3
  import { UseDataTableListingProps } from './types';
4
- import { FilterItem, FilterProps, TColumnActionButton, TableProps } from '../../types';
4
+ import { FilterItem, FilterProps, TColumnActionButton, TSearchActionButton, TableProps } from '../../types';
5
5
  import { PaginationProps } from '../../components';
6
6
  interface TUseDataTableListing<TTableType = any> {
7
7
  modifyColumn: TColumnActionButton;
8
8
  filter: FilterProps;
9
9
  pagination: PaginationProps;
10
10
  table: TableProps<TTableType>;
11
+ search: TSearchActionButton;
11
12
  selectedRowKeys: React.Key[];
12
13
  queries: {
13
14
  getTableListing: ReturnType<typeof useGetTableListing>;
@@ -15,6 +16,7 @@ interface TUseDataTableListing<TTableType = any> {
15
16
  getSavedFilterList: ReturnType<typeof useGetSavedFilterList>;
16
17
  getColumnMetrics: ReturnType<typeof useGetColumnMetrics>;
17
18
  getFilterMetricList: ReturnType<typeof useGetFilterMetricList>;
19
+ getSearchListing: ReturnType<typeof useGetSearchListing>;
18
20
  };
19
21
  setDatTableListingState: React.Dispatch<React.SetStateAction<TState<TTableType>>>;
20
22
  }
@@ -24,6 +26,7 @@ type TState<TTableType = any> = {
24
26
  pagination: PaginationProps;
25
27
  table: TableProps<TTableType>;
26
28
  selectedRowKeys: React.Key[];
29
+ searchValue?: string;
27
30
  };
28
- export declare function useDataTableListing<TTableType = Record<string, any>>(props: UseDataTableListingProps<TTableType>): TUseDataTableListing<TTableType>;
31
+ export declare function useDataTableListing<TTableType = Record<string, any>, TSearchType = any>(props: UseDataTableListingProps<TTableType, TSearchType>): TUseDataTableListing<TTableType>;
29
32
  export {};
@@ -20,22 +20,23 @@ var __rest = (this && this.__rest) || function (s, e) {
20
20
  };
21
21
  // Libraries
22
22
  import React, { useCallback, useMemo, useState } from 'react';
23
- import { isEmpty } from 'lodash';
23
+ import { Link } from 'react-router-dom';
24
+ import { isEmpty, pick } from 'lodash';
24
25
  // Types
25
26
  import { useAppConfigContext } from '@antscorp/antsomi-ui/es/providers';
26
27
  // Components
27
28
  import { Typography, Switch, Flex } from '@antscorp/antsomi-ui/es/components/atoms';
28
29
  // Constants
29
- import { COLUMN_DOMAIN } from '@antscorp/antsomi-ui/es/constants';
30
+ import { COLUMN_DOMAIN, globalToken } from '@antscorp/antsomi-ui/es/constants';
30
31
  import { MODIFY_COLUMN_DISABLE_EDITABLE, MODIFY_COLUMN_DISABLE_REMOVE, SAVED_FILTER_DEFAULT, TABLE_LISTING_PREFIX, } from './constants';
32
+ import { DEFAULT_CELL_EMPTY, DEFAULT_TOGGLE_WIDTH } from '../../constants';
31
33
  // Hooks
32
34
  import { useDeepCompareEffect, useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
33
- import { useCreateModifyColumn, useDeleteModifyColumn, useDeleteSavedFilter, useGetColumnMetrics, useGetFilterMetricList, useGetModifyColumnList, useGetSavedFilterList, useGetTableListing, useSaveFilter, useUpdateFilter, useUpdateModifyColumn, } from '@antscorp/antsomi-ui/es/queries';
35
+ import { useCreateModifyColumn, useDeleteModifyColumn, useDeleteSavedFilter, useGetColumnMetrics, useGetFilterMetricList, useGetModifyColumnList, useGetSavedFilterList, useGetSearchListing, useGetTableListing, useSaveFilter, useUpdateFilter, useUpdateModifyColumn, } from '@antscorp/antsomi-ui/es/queries';
34
36
  // Utils
35
37
  import { flatTree, safeParseJson } from '@antscorp/antsomi-ui/es/utils';
36
38
  import { METRIC_MAP_NUMBER_TYPE } from '../../constants/filter';
37
39
  import { mapFiltersToApiFilters, mapFiltersToRules, mapRulesToFilters } from '../../utils';
38
- import { DEFAULT_TOGGLE_WIDTH } from '../../constants';
39
40
  const { Text } = Typography;
40
41
  const initialState = {
41
42
  filters: [],
@@ -49,24 +50,27 @@ const initialState = {
49
50
  loading: false,
50
51
  },
51
52
  selectedRowKeys: [],
53
+ searchValue: '',
52
54
  };
53
55
  export function useDataTableListing(props) {
54
56
  // Props
55
- const { config, name = 'default', table: tableProps } = props || {};
57
+ const { config, name = 'default', table: tableProps, search: searchProps } = props || {};
56
58
  // Hooks
57
59
  const { appConfig } = useAppConfigContext();
58
60
  // State
59
61
  const [state, setState] = useState(initialState);
60
62
  // Variables
61
63
  const { env = appConfig === null || appConfig === void 0 ? void 0 : appConfig.env, auth = appConfig === null || appConfig === void 0 ? void 0 : appConfig.auth, api, object } = config;
62
- const { column: apiColumn, filter: apiFilter, listing: apiListing } = api || {};
64
+ const { column: apiColumn, filter: apiFilter, listing: apiListing, search: apiSearch, } = api || {};
63
65
  const _a = apiColumn || {}, { url: columnUrl = `${COLUMN_DOMAIN[env || 'development']}/api/column`, enabled: enabledApiColumn = true } = _a, restOfApiColumnRequest = __rest(_a, ["url", "enabled"]);
64
66
  const _b = apiFilter || {}, { url: filterUrl = `${COLUMN_DOMAIN[env || 'development']}/api/filter`, enabled: enabledApiFilter = true } = _b, restOfApiFilterRequest = __rest(_b, ["url", "enabled"]);
65
67
  const _c = apiListing || {}, { url: listingUrl = '', enabled: enabledApiListing = true } = _c, restOfApiListingRequest = __rest(_c, ["url", "enabled"]);
66
- const { filters, selectedFilterId, pagination, selectedRowKeys } = state;
68
+ const _d = apiSearch || {}, { url: searchUrl = '', enabled: enabledApiSearch = true } = _d, restOfApiSearchRequest = __rest(_d, ["url", "enabled"]);
69
+ const { filters, selectedFilterId, pagination, selectedRowKeys, searchValue } = state;
67
70
  const modifyColumnAuth = Object.assign(Object.assign({}, auth), { url: columnUrl });
68
71
  const filterAuth = Object.assign(Object.assign({}, auth), { url: filterUrl });
69
72
  const listingAuth = Object.assign(Object.assign({}, auth), { url: listingUrl });
73
+ const searchAuth = Object.assign(Object.assign({}, auth), { url: searchUrl });
70
74
  // Memos
71
75
  const mapObject = useMemo(() => ({
72
76
  objType: object === null || object === void 0 ? void 0 : object.type,
@@ -133,6 +137,18 @@ export function useDataTableListing(props) {
133
137
  enabled: !!(listingAuth === null || listingAuth === void 0 ? void 0 : listingAuth.url) && !!(listingAuth === null || listingAuth === void 0 ? void 0 : listingAuth.token) && enabledApiListing,
134
138
  },
135
139
  });
140
+ const getSearchListing = useGetSearchListing({
141
+ args: {
142
+ auth: searchAuth,
143
+ params: {
144
+ search: searchValue,
145
+ },
146
+ request: restOfApiSearchRequest,
147
+ },
148
+ options: {
149
+ enabled: !!(searchAuth === null || searchAuth === void 0 ? void 0 : searchAuth.url) && !!(searchAuth === null || searchAuth === void 0 ? void 0 : searchAuth.token) && enabledApiSearch,
150
+ },
151
+ });
136
152
  // Variables
137
153
  const { data: columnMetricsData } = getColumnMetrics || {};
138
154
  const { data: modifyColumnsData, isLoading: isModifyColumnsLoading } = getModifyColumnList || {};
@@ -140,6 +156,8 @@ export function useDataTableListing(props) {
140
156
  const { data: filterMetricsData } = getFilterMetricList || {};
141
157
  const { data: tableListing, isLoading: isTableListingLoading, isRefetching: isTableListingRefetching, refetch: refetchTableListing, } = getTableListing || {};
142
158
  const { body: tableBody, header: tableHeader, total } = tableListing || {};
159
+ const { data: searchListingData, isLoading: isSearchListingLoading, isFetching: isSearchListingFetching, } = getSearchListing || {};
160
+ const { body: searchListingBody } = searchListingData || {};
143
161
  // Mutations
144
162
  const { mutateAsync: updateModifyColumn } = useUpdateModifyColumn({
145
163
  auth: modifyColumnAuth,
@@ -208,10 +226,10 @@ export function useDataTableListing(props) {
208
226
  const tableColumns = useMemo(() => {
209
227
  let data = [];
210
228
  const { columns } = tableProps || {};
211
- // Check if has column toggle then add toggle column
229
+ // Check if has column toggle then add toggle switch column
212
230
  if (columns === null || columns === void 0 ? void 0 : columns.toggle) {
213
231
  const { key, dataIndex, valueKey, title, value, onChange } = columns.toggle || {};
214
- data.push(Object.assign({ key: 'toggle' || key, fixed: 'left', align: 'center', dataIndex: 'toggle' || dataIndex, title: 'Toggle' || title, render: (_, record) => {
232
+ data.push(Object.assign(Object.assign({ key: 'toggle' || key, fixed: 'left', align: 'center', dataIndex: 'toggle' || dataIndex, title: 'Toggle' || title, width: DEFAULT_TOGGLE_WIDTH }, columns.toggle), { render: (_, record) => {
215
233
  const checked = value
216
234
  ? typeof value === 'function'
217
235
  ? value(record)
@@ -223,17 +241,35 @@ export function useDataTableListing(props) {
223
241
  onChange(checked, record);
224
242
  }
225
243
  } })));
226
- }, width: DEFAULT_TOGGLE_WIDTH }, columns.toggle));
244
+ } }));
227
245
  }
228
246
  data = data.concat((tableHeader === null || tableHeader === void 0 ? void 0 : tableHeader.map(headerCol => {
229
247
  const { name, label, fixColumn } = headerCol;
230
- return Object.assign({ key: name, dataIndex: name, title: label, fixed: fixColumn ? 'left' : undefined, render(value) {
231
- return (React.createElement(Text, { ellipsis: { tooltip: true } }, typeof value !== 'object' ? value : null));
232
- } }, columns === null || columns === void 0 ? void 0 : columns[name]);
248
+ return Object.assign(Object.assign({ key: name, dataIndex: name, title: label, fixed: fixColumn ? 'left' : undefined }, columns === null || columns === void 0 ? void 0 : columns[name]), { render(value, record, index) {
249
+ var _a;
250
+ const { link } = (columns === null || columns === void 0 ? void 0 : columns[name]) || {};
251
+ const renderComponent = (React.createElement(Text, { ellipsis: { tooltip: true }, style: Object.assign({}, (link
252
+ ? {
253
+ fontWeight: globalToken === null || globalToken === void 0 ? void 0 : globalToken.fontWeightStrong,
254
+ color: globalToken === null || globalToken === void 0 ? void 0 : globalToken.colorPrimary,
255
+ }
256
+ : {})) }, typeof value !== 'object' ? value || DEFAULT_CELL_EMPTY : DEFAULT_CELL_EMPTY));
257
+ if ((_a = columns === null || columns === void 0 ? void 0 : columns[name]) === null || _a === void 0 ? void 0 : _a.render) {
258
+ return columns[name].render(value, record, index, renderComponent);
259
+ }
260
+ if (link) {
261
+ return (React.createElement(Link, { to: typeof link === 'function' ? link(record) : link }, renderComponent));
262
+ }
263
+ return renderComponent;
264
+ } });
233
265
  })) || []);
234
266
  return data;
235
267
  }, [tableHeader, tableProps]);
236
268
  const tableData = useDeepCompareMemo(() => (tableBody === null || tableBody === void 0 ? void 0 : tableBody.map((row) => (Object.assign(Object.assign({}, row), { key: row === null || row === void 0 ? void 0 : row[tableProps === null || tableProps === void 0 ? void 0 : tableProps.mainColumnKey] })))) || [], [tableBody]);
269
+ const searchList = useDeepCompareMemo(() => {
270
+ const { itemMapKeys, icon, link } = searchProps || {};
271
+ 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 })))) || []);
272
+ }, [searchListingData, searchProps]);
237
273
  // Effects
238
274
  /**
239
275
  * Update values from local storage to state
@@ -269,10 +305,12 @@ export function useDataTableListing(props) {
269
305
  data: Object.assign(Object.assign({}, mapObject), { modifyColumnId: id, isLasted: 1 }),
270
306
  });
271
307
  // Refetch Data table listing
272
- refetchTableListing();
308
+ setTimeout(() => {
309
+ refetchTableListing();
310
+ }, 500);
273
311
  }, [mapObject, refetchTableListing, updateModifyColumn]);
274
312
  const onApplyModifyColumn = useCallback((args) => __awaiter(this, void 0, void 0, function* () {
275
- var _d;
313
+ var _e;
276
314
  const { selectedMetrics, columnSetName, existColumnSet } = args || {};
277
315
  const flattenMetrics = flatTree(columnMetricsData, 'child');
278
316
  const selectedColumnMetrics = selectedMetrics
@@ -285,7 +323,7 @@ export function useDataTableListing(props) {
285
323
  exitModifyColumnId = (existColumnSet === null || existColumnSet === void 0 ? void 0 : existColumnSet.id) || '';
286
324
  if (columnSetName === '') {
287
325
  exitModifyColumnId =
288
- ((_d = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(modifyColumn => modifyColumn.modifyName === 'Custom')) === null || _d === void 0 ? void 0 : _d.modifyColId) || '';
326
+ ((_e = modifyColumnsData === null || modifyColumnsData === void 0 ? void 0 : modifyColumnsData.find(modifyColumn => modifyColumn.modifyName === 'Custom')) === null || _e === void 0 ? void 0 : _e.modifyColId) || '';
289
327
  }
290
328
  }
291
329
  /**
@@ -295,14 +333,12 @@ export function useDataTableListing(props) {
295
333
  */
296
334
  if (exitModifyColumnId) {
297
335
  const { status } = yield updateModifyColumn({
298
- data: {
299
- modifyColumnId: exitModifyColumnId,
300
- columns: JSON.stringify(selectedColumnMetrics),
301
- isLasted: 1,
302
- },
336
+ data: Object.assign(Object.assign({}, mapObject), { modifyColumnId: exitModifyColumnId, columns: JSON.stringify(selectedColumnMetrics), isLasted: 1 }),
303
337
  });
304
- // Refetch Data table listing
305
- refetchTableListing();
338
+ setTimeout(() => {
339
+ // Refetch Data table listing
340
+ refetchTableListing();
341
+ }, 500);
306
342
  return {
307
343
  success: !!status,
308
344
  };
@@ -311,8 +347,10 @@ export function useDataTableListing(props) {
311
347
  const { status } = yield createModifyColumn({
312
348
  data: Object.assign(Object.assign({}, mapObject), { name: columnSetName || 'Custom', columns: JSON.stringify(selectedColumnMetrics), isLasted: 1 }),
313
349
  });
314
- // Refetch Data table listing
315
- refetchTableListing();
350
+ setTimeout(() => {
351
+ // Refetch Data table listing
352
+ refetchTableListing();
353
+ }, 500);
316
354
  return {
317
355
  success: !!status,
318
356
  };
@@ -433,6 +471,23 @@ export function useDataTableListing(props) {
433
471
  },
434
472
  },
435
473
  selectedRowKeys,
474
+ /* Search */
475
+ search: Object.assign(Object.assign(Object.assign({ loading: isSearchListingLoading || isSearchListingFetching, searchList }, (!!(searchProps === null || searchProps === void 0 ? void 0 : searchProps.render) && {
476
+ itemSearchRender(_item, index, node) {
477
+ var _a;
478
+ return (((_a = searchProps === null || searchProps === void 0 ? void 0 : searchProps.render) === null || _a === void 0 ? void 0 : _a.call(searchProps, ((searchListingBody === null || searchListingBody === void 0 ? void 0 : searchListingBody[index]) || {}), index, node)) ||
479
+ null);
480
+ },
481
+ })), { onSearch(valueSearch) {
482
+ if (!(searchProps === null || searchProps === void 0 ? void 0 : searchProps.isClientSearch)) {
483
+ setState(prev => (Object.assign(Object.assign({}, prev), { searchValue: valueSearch })));
484
+ }
485
+ } }), pick(searchProps, [
486
+ 'isClientSearch',
487
+ 'addFilterInfo',
488
+ 'isAddFilterFromSearchItem',
489
+ 'onClickSearchItem',
490
+ ])),
436
491
  /* Queries */
437
492
  queries: {
438
493
  getTableListing,
@@ -440,6 +495,7 @@ export function useDataTableListing(props) {
440
495
  getSavedFilterList,
441
496
  getColumnMetrics,
442
497
  getFilterMetricList,
498
+ getSearchListing,
443
499
  },
444
500
  // Handles
445
501
  setDatTableListingState: setState,
@@ -10,7 +10,7 @@ export type TActionToolbarButtonKey<T extends string[] = []> = (typeof TOOLBAR_A
10
10
  export type TSearchItem = {
11
11
  id: string | number;
12
12
  label: string;
13
- path?: string;
13
+ link?: string;
14
14
  icon?: ReactNode;
15
15
  };
16
16
  export type TSelectedRowButton = TActionButton & {
@@ -29,12 +29,15 @@ export type TSearchActionButton = TActionButton & {
29
29
  searchList?: TSearchItem[];
30
30
  objectName?: string;
31
31
  isClientSearch?: boolean;
32
+ isAddFilterFromSearchItem?: boolean;
32
33
  addFilterInfo?: {
33
34
  metricId?: string | number;
34
35
  operator: TOperatorKey;
35
36
  };
36
- itemSearchRender?: (item: TSearchItem, index: number) => React.ReactNode;
37
+ loading?: boolean;
38
+ itemSearchRender?: (item: TSearchItem, index: number, node: ReactNode) => React.ReactNode;
37
39
  onSearch?: (valueSearch: string) => void;
40
+ onClickSearchItem?: (item: TSearchItem) => void;
38
41
  };
39
42
  export type TColumnActionButton = TActionButton & {
40
43
  modalTitle?: string;
@@ -105,7 +105,7 @@ export const LeftMenuComponent = memo(props => {
105
105
  React.createElement(FeatureMenu, { role: "menu", className: "antsomi-scroll-box" },
106
106
  React.createElement("div", { className: "menu-content scroll-content" }, renderAppMenuItems()),
107
107
  React.createElement("div", { className: "nav-blank", onMouseEnter: onHoverMenuBar }),
108
- React.createElement(PopoverWrapper, { show: state.isShowPopover && isExpandable, className: "antsomi-scroll-box antsomi-child-menu-popover" },
108
+ React.createElement(PopoverWrapper, { show: state.isShowPopover && isExpandable, hasMarginTop: !isRecommendation, className: "antsomi-scroll-box antsomi-child-menu-popover" },
109
109
  React.createElement("div", { className: "scroll-content", style: { width: '200px', maxHeight: '100%' } }, childHoverMenu))),
110
110
  React.createElement("div", { style: { flexShrink: 0 } }, renderSettings())),
111
111
  isExpandable && !isRecommendation && (React.createElement(ExpandWrapper, { onMouseEnter: onMouseLeave },
@@ -16,13 +16,12 @@ import { IconWrapper } from '../../../styled';
16
16
  import { HOME_MENU_ITEMS, ICON_SIZE } from '../../../constants';
17
17
  // Utils
18
18
  import { findActiveAppCodeByUrl, findLastMatchedItemByUrl, getMenuItem } from '../../../utils';
19
- import { findItemByPermissionCode, recursiveFindItemByKey, recursiveFindParentOfActiveItem, } from './utils';
19
+ import { handleActiveRecommendationItem, recursiveFindItemByKey, recursiveFindParentOfActiveItem, } from './utils';
20
20
  // Hooks
21
21
  import { useNavigatePath } from '../../../hooks';
22
22
  import { useDeepCompareEffect } from '@antscorp/antsomi-ui/es/hooks';
23
23
  // Contexts
24
24
  import { useLeftMenuContext } from '../../../contexts';
25
- import { MARKETING_CHANNEL_CODE } from '@antscorp/antsomi-ui/es/components/template/Layout/constants';
26
25
  const noDashboardItem = {
27
26
  key: 'no_dashboard',
28
27
  label: 'No dashboard available',
@@ -79,53 +78,11 @@ export const ChildMenu = memo(props => {
79
78
  break;
80
79
  }
81
80
  case isRecommendation: {
82
- const activeItem = findItemByPermissionCode({
83
- permissionCode: customActiveCurrentKey,
84
- menuItems: items,
81
+ const menuActiveKey = handleActiveRecommendationItem({
82
+ customActiveCurrentKey,
83
+ currentActiveItem,
84
+ items,
85
85
  });
86
- const { key, permission_code } = activeItem || {};
87
- let menuActiveKey;
88
- if (permission_code && key) {
89
- switch (permission_code) {
90
- case 'JOURNEY':
91
- if (!Object.values(MARKETING_CHANNEL_CODE).includes(currentActiveItem)) {
92
- menuActiveKey = MARKETING_CHANNEL_CODE.ALL_CHANNEL;
93
- }
94
- break;
95
- case 'EVENT_SOURCES':
96
- if (!['EVENT', 'EVENT_ATTRIBUTE', 'CONVERSION'].includes(currentActiveItem))
97
- menuActiveKey = 'SOURCE';
98
- break;
99
- case 'DATAFLOWS':
100
- if (!['BATCH_STREAMING', 'REALTIME_STREAMING'].includes(currentActiveItem))
101
- menuActiveKey = 'BATCH_STREAM';
102
- break;
103
- case 'BUSINESS_OBJECT': {
104
- if (!['UPLOAD', 'EXPORT'].includes(currentActiveItem)) {
105
- menuActiveKey = 'UPLOAD';
106
- }
107
- break;
108
- }
109
- case 'DATASOURCES':
110
- menuActiveKey = 'DATA_SOURCE';
111
- break;
112
- default:
113
- menuActiveKey = key;
114
- break;
115
- }
116
- }
117
- else {
118
- switch (customActiveCurrentKey) {
119
- case 'DATASOURCES-SQL_WORKSPACE':
120
- menuActiveKey = 'DATA_SOURCE';
121
- break;
122
- case 'DATASOURCES-DATAFLOWS':
123
- menuActiveKey = 'DF_DATA_SOURCE';
124
- break;
125
- default:
126
- break;
127
- }
128
- }
129
86
  if (menuActiveKey) {
130
87
  setCurrentActiveItem(menuActiveKey);
131
88
  /** Find parent key of active menu item to open it */
@@ -216,9 +173,9 @@ export const ChildMenu = memo(props => {
216
173
  return (_a = args === null || args === void 0 ? void 0 : args.items) === null || _a === void 0 ? void 0 : _a.map(item => {
217
174
  const { key, label, children, icon, logo_url, menu_item_path = null, menu_item_domain = null, options, disabled, optionCallback, } = item;
218
175
  const isOwnerDashboardKey = key === HOME_MENU_ITEMS.DASHBOARD.menu_item_code;
219
- const renderLabel = () => (React.createElement(LabelWrapper, null,
176
+ const renderLabel = () => (React.createElement(LabelWrapper, { gap: 10, align: "center", justify: "space-between" },
220
177
  React.createElement(LabelCustom, { ellipsis: { tooltip: label } }, label),
221
- (options === null || options === void 0 ? void 0 : options.length) && !isRecommendation && (React.createElement(OptionDropdownWrapper, null,
178
+ (options === null || options === void 0 ? void 0 : options.length) && !isRecommendation && (React.createElement(OptionDropdownWrapper, { align: "center" },
222
179
  React.createElement(Dropdown, { menu: {
223
180
  items: options,
224
181
  onClick: e => {