@antscorp/antsomi-ui 1.3.5-beta.291 → 1.3.5-beta.293

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 (30) hide show
  1. package/es/components/molecules/HeaderV2/HeaderV2.js +1 -3
  2. package/es/components/organism/LeftMenu/components/HomeMenu/index.js +2 -2
  3. package/es/components/organism/LeftMenu/components/HomeMenu/styled.js +1 -0
  4. package/es/components/organism/LeftMenu/components/HomeMenu/useHomeMenu.d.ts +2 -1
  5. package/es/components/organism/LeftMenu/components/HomeMenu/useHomeMenu.js +13 -24
  6. package/es/components/organism/LeftMenu/components/common/ChildMenu/index.js +39 -34
  7. package/es/components/organism/LeftMenu/components/common/ChildMenu/styled.d.ts +3 -1
  8. package/es/components/organism/LeftMenu/components/common/ChildMenu/styled.js +87 -27
  9. package/es/components/organism/LeftMenu/hooks/useLeftMenu.d.ts +0 -1
  10. package/es/components/organism/LeftMenu/hooks/useLeftMenu.js +39 -49
  11. package/es/components/organism/LeftMenu/index.js +6 -20
  12. package/es/components/organism/LeftMenu/styled.js +1 -2
  13. package/es/components/organism/LeftMenu/utils/index.d.ts +1 -1
  14. package/es/components/organism/LeftMenu/utils/index.js +12 -7
  15. package/es/components/template/Layout/Layout.js +10 -4
  16. package/es/components/template/Layout/constants/permission.d.ts +0 -3
  17. package/es/components/template/Layout/constants/permission.js +0 -3
  18. package/es/components/template/Layout/stores/index.d.ts +6 -0
  19. package/es/components/template/Layout/stores/index.js +12 -0
  20. package/es/components/template/Layout/utils/permission.d.ts +1 -1
  21. package/es/components/template/TemplateListing/components/CategoryListing/index.js +1 -7
  22. package/es/components/template/TemplateListing/index.js +0 -4
  23. package/es/hooks/index.d.ts +3 -0
  24. package/es/hooks/index.js +3 -0
  25. package/es/hooks/useEventListener.d.ts +6 -0
  26. package/es/hooks/useEventListener.js +28 -0
  27. package/es/hooks/useListingItemResize.js +19 -40
  28. package/es/hooks/useWindowSize.d.ts +11 -0
  29. package/es/hooks/useWindowSize.js +35 -0
  30. package/package.json +1 -1
@@ -28,14 +28,13 @@ export const HeaderV2 = memo(props => {
28
28
  const { auth, env: envContext, languageCode = 'en', appCode: contextAppCode, urlLogout: urlLogoutProvider = '', menuCode: contextMenuCode, } = useContextSelector(AppConfigContext, state => state);
29
29
  const { search } = useLocation();
30
30
  const history = useHistory();
31
- /** Prefer to use Header in AppConfigContext */
31
+ // * Prefer to use Header in AppConfigContext
32
32
  const { className, style, breadcrumbs, pageTitle = '', accountSelection = {}, helpConfig, notificationConfig = {}, accountSharingConfig, useURLParam, config, } = props;
33
33
  /** General config for children component */
34
34
  const { env = envContext, language = languageCode, userId = isNaN(Number(auth === null || auth === void 0 ? void 0 : auth.userId)) ? 0 : Number(auth === null || auth === void 0 ? void 0 : auth.userId), portalId = auth === null || auth === void 0 ? void 0 : auth.portalId, token = auth === null || auth === void 0 ? void 0 : auth.token, permissionDomain = PERMISSION_API, iamDomain = IAM_API, appCode = contextAppCode, menuCode = contextMenuCode, } = config || {};
35
35
  const { currentAccount, inputStyle = 'select', onSelectAccount } = accountSelection, accountSelectionProps = __rest(accountSelection, ["currentAccount", "inputStyle", "onSelectAccount"]);
36
36
  const urlParams = useMemo(() => new URLSearchParams(search), [search]);
37
37
  const oidParam = (_a = urlParams.get('oid')) !== null && _a !== void 0 ? _a : 'all';
38
- // States
39
38
  const [selectedAccount, setSelectedAccount] = useState(`${useURLParam ? oidParam : `${(_b = currentAccount !== null && currentAccount !== void 0 ? currentAccount : userId) !== null && _b !== void 0 ? _b : 'all'}`}`);
40
39
  // Memo
41
40
  const accountSelectionDomain = useMemo(() => {
@@ -85,7 +84,6 @@ export const HeaderV2 = memo(props => {
85
84
  token,
86
85
  lang: language,
87
86
  };
88
- // Handlers
89
87
  const handleChangeAccount = (userId) => {
90
88
  setSelectedAccount(userId);
91
89
  if (useURLParam) {
@@ -10,9 +10,9 @@ import { CreateButton, HomeMenuWrapper } from './styled';
10
10
  // Hooks
11
11
  import { useHomeMenu } from './useHomeMenu';
12
12
  export const HomeMenu = memo(() => {
13
- // Handlers
14
13
  const { children, onCreateNewReport, onMenuClick } = useHomeMenu();
15
- return (React.createElement(HomeMenuWrapper, { vertical: true },
14
+ // console.log({});
15
+ return (React.createElement(HomeMenuWrapper, { gap: 10, vertical: true },
16
16
  React.createElement(CreateButton, { type: "primary", onClick: onCreateNewReport },
17
17
  React.createElement(Flex, { gap: 10, align: "center" },
18
18
  React.createElement(Icon, { type: "icon-ants-plus-slim", style: { fontSize: 14 } }),
@@ -7,6 +7,7 @@ import { Button, Flex } from '../../../../atoms';
7
7
  import { THEME } from '@antscorp/antsomi-ui/es/constants';
8
8
  export const HomeMenuWrapper = styled(Flex) `
9
9
  height: 100%;
10
+ width: 100%;
10
11
 
11
12
  .menu-list {
12
13
  width: 100%;
@@ -1,6 +1,7 @@
1
+ /// <reference types="react" />
1
2
  export declare const useHomeMenu: () => {
2
3
  children: import("@antscorp/antsomi-ui/es/components/organism/LeftMenu/types").TMenuItem[];
3
- onCreateNewReport: () => void;
4
+ onCreateNewReport: import("react").MouseEventHandler<HTMLElement>;
4
5
  onOptionCallback: (args: {
5
6
  menuItemKey: string;
6
7
  optionKey: string;
@@ -8,29 +8,14 @@ import { HOME_REPORT_ROUTES, HOME_ROUTE } from '../../constants';
8
8
  import { getGeneratePath, getMenuItem } from '../../utils';
9
9
  // Types
10
10
  import { useLeftMenuStore } from '../../stores';
11
+ import { useLayoutStore } from '@antscorp/antsomi-ui/es/components/template';
11
12
  export const useHomeMenu = () => {
12
- // Hooks
13
- const { pathname, hash, search } = window.location;
13
+ const { pathname, search } = window.location;
14
14
  const history = useHistory();
15
- // Stores
16
15
  const appMenuChildren = useLeftMenuStore(store => store.state.appMenuChildren);
17
16
  const auth = useLeftMenuStore(store => { var _a; return (_a = store.state.appConfig) === null || _a === void 0 ? void 0 : _a.auth; });
18
- // Memos
17
+ const onClickCreateDashboard = useLayoutStore(store => store.state.leftMenu.onClickCreateDashboard);
19
18
  const urlParams = useMemo(() => new URLSearchParams(search), [search]);
20
- // Handlers
21
- const handleSetSearchParams = useCallback((searchParam) => {
22
- const url = `${pathname}${hash}`;
23
- if (url.includes(getGeneratePath(HOME_ROUTE, Object.assign({}, auth)))) {
24
- urlParams.set('type', searchParam);
25
- history.replace({ search: urlParams.toString() });
26
- }
27
- else {
28
- history.push(getGeneratePath(HOME_ROUTE, Object.assign({}, auth)));
29
- urlParams.set('type', searchParam);
30
- history.replace({ search: urlParams.toString() });
31
- }
32
- }, [auth, hash, history, pathname, urlParams]);
33
- // Memos
34
19
  const onOptionCallback = useCallback((args) => {
35
20
  const { optionKey, menuItemKey } = args;
36
21
  switch (optionKey) {
@@ -51,12 +36,16 @@ export const useHomeMenu = () => {
51
36
  var _a;
52
37
  return getMenuItem(Object.assign(Object.assign({}, appMenuItem), { children: (_a = appMenuItem === null || appMenuItem === void 0 ? void 0 : appMenuItem.children) === null || _a === void 0 ? void 0 : _a.map(item => (Object.assign(Object.assign({}, item), { options: Object.values(CONFIG_OPTIONS), optionCallback: onOptionCallback }))) }));
53
38
  }), [appMenuChildren, onOptionCallback]);
54
- // Callbacks
55
- const onCreateNewReport = useCallback(() => {
56
- history.push(getGeneratePath(HOME_ROUTE, auth));
57
- urlParams.set('type', HOME_REPORT_ROUTES.CREATE);
58
- history.replace({ search: urlParams.toString() });
59
- }, [auth, history, urlParams]);
39
+ const onCreateNewReport = useCallback(e => {
40
+ if (onClickCreateDashboard) {
41
+ onClickCreateDashboard(e);
42
+ }
43
+ else {
44
+ history.push(getGeneratePath(HOME_ROUTE, auth));
45
+ urlParams.set('type', HOME_REPORT_ROUTES.CREATE);
46
+ history.replace({ search: urlParams.toString() });
47
+ }
48
+ }, [auth, history, onClickCreateDashboard, urlParams]);
60
49
  const onMenuClick = useCallback((key, _) => {
61
50
  const newPathName = getGeneratePath(HOME_REPORT_ROUTES.DETAIL, Object.assign(Object.assign({}, auth), { dashboardId: key }));
62
51
  if (newPathName !== pathname) {
@@ -6,10 +6,10 @@ import classNames from 'classnames';
6
6
  import { Link } from 'react-router-dom';
7
7
  // Components
8
8
  import { Dropdown, Menu } from 'antd';
9
- import { Flex } from '../../../../../atoms';
10
9
  import { MenuItemImage } from './components';
10
+ import { Flex } from '../../../../../atoms';
11
11
  // Styled
12
- import { LabelCustom, MenuWrapper } from './styled';
12
+ import { LabelCustom, LabelWrapper, MenuWrapper, OptionDropdownWrapper } from './styled';
13
13
  import { IconWrapper } from '../../../styled';
14
14
  // Constants
15
15
  import { ICON_SIZE } from '../../../constants';
@@ -19,9 +19,17 @@ import { recursiveFindParentOfActiveItem } from './utils';
19
19
  // Hooks
20
20
  import { useLeftMenuStore } from '../../../stores';
21
21
  import { useNavigatePath } from '../../../hooks';
22
+ const styles = {
23
+ dropdownMenu: { width: '130px', padding: '8px 0' },
24
+ icon: { marginTop: '2px', zIndex: 1000, flexShrink: 0 },
25
+ expandIcon: {
26
+ fontSize: ICON_SIZE,
27
+ color: 'inherit',
28
+ },
29
+ menuItemTitle: { flex: '1 1 0%', maxWidth: '100%' },
30
+ };
22
31
  export const ChildMenu = memo(props => {
23
32
  const { items = [], onMenuClick } = props;
24
- // Stores
25
33
  const auth = useLeftMenuStore(store => { var _a; return (_a = store.state.appConfig) === null || _a === void 0 ? void 0 : _a.auth; });
26
34
  const activeAppCode = useLeftMenuStore(store => store.state.activeAppCode);
27
35
  const menuItems = useLeftMenuStore(store => store.state.menuItems);
@@ -29,18 +37,15 @@ export const ChildMenu = memo(props => {
29
37
  const isCustomized = useLeftMenuStore(store => store.state.isCustomized);
30
38
  const customActiveCurrentKey = useLeftMenuStore(store => store.state.customActiveCurrentKey);
31
39
  const setLeftMenuState = useLeftMenuStore(store => store.setState);
32
- // States
33
40
  const [currentActiveItem, setCurrentActiveItem] = useState('');
34
41
  const [openKeys, setOpenKeys] = useState([]);
35
- // Hooks
36
42
  const { pathname, hash } = window.location;
37
43
  const { isPushDifferentDomain, getPath, navigatePath } = useNavigatePath();
38
- // Side Effects
39
44
  useEffect(() => {
40
45
  var _a;
41
46
  if (isCustomized) {
42
47
  setCurrentActiveItem(customActiveCurrentKey);
43
- /** Find parent key of active menu item to open it */
48
+ // Find parent key of active menu item to open it
44
49
  const parentKey = recursiveFindParentOfActiveItem({
45
50
  activeMenuItem: customActiveCurrentKey,
46
51
  menuItems: customItems,
@@ -51,11 +56,11 @@ export const ChildMenu = memo(props => {
51
56
  }
52
57
  else {
53
58
  const url = `${pathname}${hash}`;
54
- /** Active menu item by current url */
59
+ // Active menu item by current url
55
60
  const activeMenuItem = (_a = findLastMatchedItemByUrl({ url, menuItems, auth })) === null || _a === void 0 ? void 0 : _a.menu_item_code;
56
61
  if (activeMenuItem && activeMenuItem !== currentActiveItem) {
57
62
  setCurrentActiveItem(activeMenuItem);
58
- /** Find parent key of active menu item to open it */
63
+ // Find parent key of active menu item to open it
59
64
  const parentKey = recursiveFindParentOfActiveItem({
60
65
  activeMenuItem,
61
66
  menuItems: menuItems === null || menuItems === void 0 ? void 0 : menuItems.map(item => getMenuItem(item)),
@@ -63,7 +68,7 @@ export const ChildMenu = memo(props => {
63
68
  if (parentKey) {
64
69
  setOpenKeys(prev => [...prev, parentKey]);
65
70
  }
66
- /** Active App Item having code matching url */
71
+ // Active App Item having code matching url
67
72
  const matchAppCode = findActiveAppCodeByUrl({ menuItems, url, auth });
68
73
  if (matchAppCode && matchAppCode !== activeAppCode) {
69
74
  setLeftMenuState({ activeAppCode: matchAppCode });
@@ -83,43 +88,43 @@ export const ChildMenu = memo(props => {
83
88
  customActiveCurrentKey,
84
89
  customItems,
85
90
  ]);
86
- // Handlers
87
91
  const onClick = e => {
88
92
  onMenuClick === null || onMenuClick === void 0 ? void 0 : onMenuClick(e.key, e.keyPath);
89
93
  };
90
- // Render components
91
94
  const customMenuItems = (args) => {
92
95
  var _a;
93
96
  return (_a = args === null || args === void 0 ? void 0 : args.items) === null || _a === void 0 ? void 0 : _a.map(item => {
94
- var _a;
95
97
  const { key, label, children, icon, logo_url, menu_item_path = null, menu_item_domain = null, options, optionCallback, } = item;
96
- const labelComponent = () => (!children || isEmpty(children)) && !isEmpty(options) ? (React.createElement(Flex, { gap: 10, align: "center", justify: "space-between", style: { width: '100%' }, className: "child-menu-label" },
97
- React.createElement(LabelCustom, { ellipsis: { tooltip: label } }, label),
98
- React.createElement(Dropdown, { menu: {
99
- items: options,
100
- onClick: e => {
101
- e.domEvent.stopPropagation();
102
- e.domEvent.preventDefault();
103
- optionCallback === null || optionCallback === void 0 ? void 0 : optionCallback({ menuItemKey: key, optionKey: e.key });
104
- },
105
- }, trigger: ['click'] },
106
- React.createElement(Icon, { className: "child-menu-item-icon", type: "icon-ants-three-dot-vertical", style: { marginTop: '2px', zIndex: 1000 } })))) : (React.createElement(LabelCustom, { ellipsis: { tooltip: label } }, label));
98
+ const renderLabel = () => (!children || isEmpty(children)) && !isEmpty(options) ? (React.createElement(LabelWrapper, null,
99
+ React.createElement(LabelCustom, { ellipsis: { tooltip: label }, style: { flex: '1 1 0%' } }, label),
100
+ React.createElement(OptionDropdownWrapper, null,
101
+ React.createElement(Dropdown, { menu: {
102
+ items: options,
103
+ onClick: e => {
104
+ e.domEvent.stopPropagation();
105
+ e.domEvent.preventDefault();
106
+ optionCallback === null || optionCallback === void 0 ? void 0 : optionCallback({ menuItemKey: key, optionKey: e.key });
107
+ },
108
+ style: styles.dropdownMenu,
109
+ }, trigger: ['click'] },
110
+ React.createElement(Icon, { className: "child-menu-item-icon", type: "icon-ants-three-dot-vertical", style: styles.icon }))))) : (React.createElement(LabelCustom, { ellipsis: { tooltip: label } }, label));
111
+ const renderIcon = () => {
112
+ var _a;
113
+ return !isNil(icon) || !isNil(logo_url) ? (React.createElement(Flex, { style: { flexShrink: 0 }, align: "center" }, !isNil(icon) ? (React.createElement(IconWrapper, null,
114
+ React.createElement(Icon, { type: icon }))) : !isNil(logo_url) ? (React.createElement(MenuItemImage, { imageUrl: logo_url, fallbackIcon: (_a = args === null || args === void 0 ? void 0 : args.parent) === null || _a === void 0 ? void 0 : _a.icon, className: classNames({ isActive: currentActiveItem === key }) })) : null)) : null;
115
+ };
116
+ const renderTitle = () => !menu_item_path ? (renderLabel()) : isPushDifferentDomain(menu_item_domain, menu_item_path) ? (React.createElement("div", { onClick: () => navigatePath(menu_item_domain, menu_item_path), className: "menu-link" }, renderLabel())) : (React.createElement(Link, { to: getPath(menu_item_path), className: "menu-link" }, renderLabel()));
107
117
  return {
108
118
  key,
109
- label: !menu_item_path ? (labelComponent()) : isPushDifferentDomain(menu_item_domain, menu_item_path) ? (React.createElement("div", { onClick: () => navigatePath(menu_item_domain, menu_item_path), className: "menu-link" }, labelComponent())) : (React.createElement(Link, { to: getPath(menu_item_path), className: "menu-link" }, labelComponent())),
110
- icon: !isNil(icon) ? (React.createElement(IconWrapper, null,
111
- React.createElement(Icon, { type: icon }))) : !isNil(logo_url) ? (React.createElement(MenuItemImage, { imageUrl: logo_url, fallbackIcon: (_a = args === null || args === void 0 ? void 0 : args.parent) === null || _a === void 0 ? void 0 : _a.icon, className: classNames({ isActive: currentActiveItem === key }) })) : null,
119
+ label: (React.createElement(Flex, { gap: 10, align: "center", justify: "space-between", style: { height: '100%' } },
120
+ renderIcon(),
121
+ React.createElement(Flex, { style: styles.menuItemTitle, align: "center" }, renderTitle()))),
112
122
  children: customMenuItems({ parent: item, items: children }),
113
123
  };
114
124
  });
115
125
  };
116
126
  return (React.createElement(MenuWrapper, null,
117
- React.createElement(Menu, { selectedKeys: [currentActiveItem], defaultOpenKeys: [currentActiveItem], openKeys: uniq(openKeys), mode: "inline", items: customMenuItems({ items }), inlineIndent: 10, onOpenChange: openKeys => {
127
+ React.createElement(Menu, { selectedKeys: [currentActiveItem], defaultOpenKeys: [currentActiveItem], openKeys: uniq(openKeys), mode: "inline", items: customMenuItems({ items }), inlineIndent: 12, onOpenChange: openKeys => {
118
128
  setOpenKeys(openKeys);
119
- }, expandIcon: ({ isOpen }) => (React.createElement(Icon, { type: "icon-ants-expand-more", style: {
120
- fontSize: ICON_SIZE,
121
- color: 'inherit',
122
- // color: THEME.token?.bw8,
123
- transform: `rotate(${isOpen ? '180deg' : '0deg'})`,
124
- } })), onClick: onClick })));
129
+ }, expandIcon: ({ isOpen }) => (React.createElement(Icon, { type: "icon-ants-expand-more", style: Object.assign(Object.assign({}, styles.expandIcon), { transform: `rotate(${isOpen ? '180deg' : '0deg'})` }) })), onClick: onClick })));
125
130
  });
@@ -1,3 +1,5 @@
1
1
  /// <reference types="react" />
2
- export declare const MenuWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
2
+ export declare const LabelWrapper: 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>;
3
3
  export declare const LabelCustom: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("antd/es/typography/Text").TextProps & import("react").RefAttributes<HTMLSpanElement>>, any, {}, never>;
4
+ export declare const OptionDropdownWrapper: 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>;
5
+ export declare const MenuWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -1,11 +1,27 @@
1
- var _a;
1
+ var _a, _b;
2
2
  // Libraries
3
3
  import styled from 'styled-components';
4
4
  // Components
5
- import { Typography } from '../../../../../atoms';
5
+ import { Flex, Typography } from '../../../../../atoms';
6
6
  // Constants
7
7
  import { THEME } from '@antscorp/antsomi-ui/es/constants';
8
8
  import { ICON_SIZE } from '../../../constants';
9
+ export const LabelWrapper = styled(Flex) `
10
+ width: 100%;
11
+ `;
12
+ LabelWrapper.defaultProps = {
13
+ gap: 10,
14
+ align: 'center',
15
+ justify: 'space-between',
16
+ };
17
+ export const LabelCustom = styled(Typography.Text) `
18
+ font-size: inherit !important;
19
+ color: inherit !important;
20
+ `;
21
+ export const OptionDropdownWrapper = styled(Flex) `
22
+ width: 24px;
23
+ `;
24
+ OptionDropdownWrapper.defaultProps = { align: 'center' };
9
25
  export const MenuWrapper = styled.div `
10
26
  width: 100%;
11
27
  height: 100%;
@@ -14,15 +30,81 @@ export const MenuWrapper = styled.div `
14
30
  font-weight: bold !important;
15
31
  border-right: none !important;
16
32
 
17
- & > ul {
33
+ & > ul.antsomi-menu.antsomi-menu-root {
18
34
  height: 100%;
19
35
 
20
- li {
21
- width: 100% !important;
36
+ & > li {
37
+ padding-left: 0px !important;
38
+
39
+ &.antsomi-menu-submenu > [role='menuitem'] {
40
+ margin: 0;
41
+ padding-left: 0px !important;
42
+ width: 100%;
43
+ border-radius: ${(_a = THEME === null || THEME === void 0 ? void 0 : THEME.token) === null || _a === void 0 ? void 0 : _a.borderRadiusXL}px;
44
+ padding-right: 4px !important;
45
+ }
46
+ }
47
+
48
+ & li {
49
+ width: 100%;
50
+ margin: 0;
51
+ padding-right: 0px;
52
+ background-color: transparent !important;
53
+
54
+ & .antsomi-menu-title-content {
55
+ width: 100%;
56
+ height: 100%;
57
+ border-radius: ${(_b = THEME === null || THEME === void 0 ? void 0 : THEME.token) === null || _b === void 0 ? void 0 : _b.borderRadiusXL}px;
58
+ padding: 0 8px;
59
+
60
+ &:hover {
61
+ background-color: #f2f9ff !important;
62
+ }
63
+ }
64
+
65
+ &.antsomi-menu-item-selected {
66
+ & > .antsomi-menu-title-content {
67
+ background-color: #deeffe !important;
68
+ }
69
+ }
22
70
 
23
71
  [role='icon'] {
24
72
  font-size: ${ICON_SIZE}px !important;
25
73
  }
74
+
75
+ & a.menu-link {
76
+ width: 100%;
77
+ height: 100%;
78
+ display: flex;
79
+ align-items: center;
80
+ color: inherit;
81
+ text-decoration: none;
82
+ }
83
+
84
+ &.antsomi-menu-submenu {
85
+ & > [role='menuitem'] {
86
+ padding-right: 0;
87
+ }
88
+
89
+ & > ul.antsomi-menu.antsomi-menu-sub {
90
+ & > [role='menuitem'] {
91
+ width: 100%;
92
+ padding-right: 0px;
93
+
94
+ & > .antsomi-menu-title-content {
95
+ & ${OptionDropdownWrapper} {
96
+ display: none;
97
+ }
98
+
99
+ &:hover {
100
+ & ${OptionDropdownWrapper} {
101
+ display: flex;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
26
108
  }
27
109
  }
28
110
 
@@ -31,30 +113,8 @@ export const MenuWrapper = styled.div `
31
113
  border: none !important;
32
114
  }
33
115
 
34
- [role='menuitem'] {
35
- margin: 0 !important;
36
- border-radius: ${(_a = THEME === null || THEME === void 0 ? void 0 : THEME.token) === null || _a === void 0 ? void 0 : _a.borderRadiusXL}px !important;
37
- padding-right: 10px !important;
38
- }
39
-
40
- [role='menuitem'].antsomi-menu-item-selected {
41
- background-color: #deeffe !important;
42
- }
43
-
44
116
  .antsomi-menu-item-active,
45
117
  .antsomi-menu-submenu-title:hover {
46
118
  background-color: #f2f9ff !important;
47
119
  }
48
-
49
- .menu-link {
50
- width: 100% !important;
51
- height: 100% !important;
52
- display: flex !important;
53
- color: inherit !important;
54
- text-decoration: none !important;
55
- }
56
- `;
57
- export const LabelCustom = styled(Typography.Text) `
58
- font-size: inherit !important;
59
- color: inherit !important;
60
120
  `;
@@ -7,7 +7,6 @@ export declare const useLeftMenu: (props: LeftMenuProps) => {
7
7
  state: TState;
8
8
  activeAppCode: string;
9
9
  permissionMenu: import("@antscorp/antsomi-ui/es/models/LeftMenu").TFeatureMenu[];
10
- /** Variables */
11
10
  customActiveAppKey: string;
12
11
  onToggleChildMenu: () => void;
13
12
  onMouseEnter: (key: string) => void;
@@ -9,7 +9,7 @@ import { findActiveAppCodeByChild, findActiveAppCodeByUrl, findLastMatchedItemBy
9
9
  import { useLeftMenuStore } from '../stores';
10
10
  import { POST_MESSAGE_TYPES } from '@antscorp/antsomi-ui/es/constants/postMessage';
11
11
  // Constants
12
- import { CDP_API, PERMISSION_API, PERMISSION_ENV_API } from '@antscorp/antsomi-ui/es/constants';
12
+ import { CDP_API, PERMISSION_API } from '@antscorp/antsomi-ui/es/constants';
13
13
  const initialState = {
14
14
  hoverItem: '',
15
15
  isExpandMenu: true,
@@ -18,23 +18,31 @@ export const useLeftMenu = (props) => {
18
18
  // Props
19
19
  const { objectType = 'OVERVIEW', objectId = 1, isGrouped = true, appConfig, customization, onActiveMenuCodeChange, } = props;
20
20
  const { isExpandable = true, isCustomized = false, items, activeKey } = customization || {};
21
- // Hooks
22
- const { pathname, hash, search } = window.location;
23
- const urlParams = useMemo(() => new URLSearchParams(search), [search]);
24
- // Stores
21
+ const { pathname, hash } = window.location;
25
22
  const activeAppCode = useLeftMenuStore(store => store.state.activeAppCode);
26
23
  const customActiveAppKey = useLeftMenuStore(store => store.state.customActiveAppKey);
27
24
  const setLeftMenuState = useLeftMenuStore(store => store.setState);
28
- // Destructuring variables
29
- const { auth, languageCode, env } = appConfig || {};
30
- // State
25
+ const { auth, languageCode = 'en', env = 'development' } = appConfig || {};
31
26
  const [state, setState] = useState(initialState);
32
- // Queries
27
+ // const { data: menuList } = useGetListMenu({
28
+ // args: {
29
+ // auth: {
30
+ // token: env === 'production' ? auth?.token : '5474r2x214z284d4w2b4y444d464b444q4y274u4t5x5',
31
+ // url: 'https://permission.antsomi.com',
32
+ // portalId: env === 'production' ? auth?.portalId : 561236459,
33
+ // userId: env === 'production' ? auth?.userId : '1600083836',
34
+ // accountId: env === 'production' ? auth?.accountId : '1600083836',
35
+ // },
36
+ // params: {
37
+ // type: 'menu-item-permission',
38
+ // },
39
+ // },
40
+ // });
33
41
  const { data: menuList } = useGetListMenu({
34
42
  args: {
35
43
  auth: {
36
- token: env === 'production' ? auth === null || auth === void 0 ? void 0 : auth.token : '5474r2x214r2b4b4v2d4y444u2v5q2p5o4d4c4f424e4',
37
- url: env ? PERMISSION_ENV_API[env] : '',
44
+ token: '5474r2x214r2b4b4v2d4y444u2v5q2p5o4d4c4f424e4' || (auth === null || auth === void 0 ? void 0 : auth.token),
45
+ url: 'https://sandbox-permission.ants.vn',
38
46
  portalId: auth === null || auth === void 0 ? void 0 : auth.portalId,
39
47
  userId: auth === null || auth === void 0 ? void 0 : auth.userId,
40
48
  accountId: auth === null || auth === void 0 ? void 0 : auth.accountId,
@@ -63,10 +71,10 @@ export const useLeftMenu = (props) => {
63
71
  const { data: dashboardData, refetch: refetchDashboard } = useGetDashboard({
64
72
  args: {
65
73
  auth: {
66
- token: auth === null || auth === void 0 ? void 0 : auth.token,
67
- url: env ? `${CDP_API.production}/hub` : '',
68
- portalId: auth === null || auth === void 0 ? void 0 : auth.portalId,
69
- userId: auth === null || auth === void 0 ? void 0 : auth.userId,
74
+ token: env === 'development' ? '5474r2x214z284d4w2b4y494d43464k5a4v2j464m5a4' : auth === null || auth === void 0 ? void 0 : auth.token,
75
+ url: env === 'development' ? `${CDP_API.production}/hub` : `${CDP_API === null || CDP_API === void 0 ? void 0 : CDP_API[env]}/hub`,
76
+ portalId: env === 'development' ? 561236459 : auth === null || auth === void 0 ? void 0 : auth.portalId,
77
+ userId: env === 'development' ? '1600083836' : auth === null || auth === void 0 ? void 0 : auth.userId,
70
78
  },
71
79
  params: {
72
80
  objectType,
@@ -90,9 +98,7 @@ export const useLeftMenu = (props) => {
90
98
  },
91
99
  },
92
100
  });
93
- // Variables
94
101
  const flattenMenuPermission = flattenMenuArray(menuListPermission || [], 'childs');
95
- // Memos
96
102
  const permissionMenu = useMemo(() => recursivePermissionMenu(sortBy((menuList === null || menuList === void 0 ? void 0 : menuList.rows) || [], ['level_position']), flattenMenuPermission), [menuList === null || menuList === void 0 ? void 0 : menuList.rows, flattenMenuPermission]);
97
103
  const mappingChildrenMenu = useMemo(() => getMappingAppChildren({
98
104
  menuList: permissionMenu,
@@ -100,7 +106,6 @@ export const useLeftMenu = (props) => {
100
106
  dashboardData,
101
107
  destinationChannelEntries: destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries,
102
108
  }), [auth, dashboardData, destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries, permissionMenu]);
103
- /* Handlers */
104
109
  const receivePostMessage = (event) => {
105
110
  const { data } = event;
106
111
  const { type } = data || {};
@@ -113,7 +118,6 @@ export const useLeftMenu = (props) => {
113
118
  break;
114
119
  }
115
120
  };
116
- // Side Effects
117
121
  // Receive Post Message
118
122
  useEffect(() => {
119
123
  if (!isCustomized) {
@@ -125,9 +129,7 @@ export const useLeftMenu = (props) => {
125
129
  useEffect(() => {
126
130
  setLeftMenuState({ appConfig, isCustomized });
127
131
  }, [appConfig, isCustomized, setLeftMenuState]);
128
- /**
129
- * Active Custom App Key when active key is changed
130
- */
132
+ // Active Custom App Key when active key is changed
131
133
  useEffect(() => {
132
134
  if (activeKey && items)
133
135
  setLeftMenuState({
@@ -138,9 +140,7 @@ export const useLeftMenu = (props) => {
138
140
  customActiveCurrentKey: activeKey,
139
141
  });
140
142
  }, [activeKey, appConfig, isCustomized, items, setLeftMenuState]);
141
- /**
142
- * Change list menu children when hovering or activating items, giving priority to hovering items
143
- */
143
+ // Change list menu children when hovering or activating items, giving priority to hovering items
144
144
  useEffect(() => {
145
145
  var _a, _b;
146
146
  if (isCustomized) {
@@ -160,33 +160,33 @@ export const useLeftMenu = (props) => {
160
160
  }
161
161
  }
162
162
  }, [
163
- isCustomized,
164
163
  activeAppCode,
164
+ customActiveAppKey,
165
+ isCustomized,
166
+ items,
165
167
  mappingChildrenMenu,
166
168
  state.hoverItem,
167
169
  setLeftMenuState,
168
- items,
169
- customActiveAppKey,
170
170
  ]);
171
171
  useEffect(() => {
172
- var _a;
173
172
  if (!isCustomized) {
174
173
  const url = `${pathname}${hash}`;
175
- /**
176
- * Active App Item having code matching url
177
- */
174
+ // Active App Item having code matching url
178
175
  const matchAppCode = findActiveAppCodeByUrl({ url, menuItems: mappingChildrenMenu, auth });
179
176
  if (matchAppCode && matchAppCode !== activeAppCode) {
180
177
  setLeftMenuState({ activeAppCode: matchAppCode });
181
178
  }
182
- /**
183
- * Callback function when url change
184
- */
185
- const matchedCode = (_a = findLastMatchedItemByUrl({
179
+ }
180
+ }, [activeAppCode, auth, hash, isCustomized, mappingChildrenMenu, pathname, setLeftMenuState]);
181
+ useEffect(() => {
182
+ if (!isCustomized) {
183
+ const url = `${pathname}${hash}`;
184
+ // Callback function using at Layout when url change
185
+ const matchedCode = findLastMatchedItemByUrl({
186
186
  url,
187
187
  menuItems: mappingChildrenMenu,
188
188
  auth,
189
- })) === null || _a === void 0 ? void 0 : _a.menu_item_code;
189
+ });
190
190
  const activeItemPath = matchedCode
191
191
  ? findPathOfActiveItem({
192
192
  activeMenuItem: matchedCode,
@@ -196,19 +196,14 @@ export const useLeftMenu = (props) => {
196
196
  onActiveMenuCodeChange === null || onActiveMenuCodeChange === void 0 ? void 0 : onActiveMenuCodeChange(activeItemPath, flattenMenuPermission);
197
197
  }
198
198
  }, [
199
- isCustomized,
200
- activeAppCode,
201
199
  auth,
200
+ flattenMenuPermission,
202
201
  hash,
202
+ isCustomized,
203
203
  mappingChildrenMenu,
204
204
  pathname,
205
- permissionMenu,
206
- setLeftMenuState,
207
205
  onActiveMenuCodeChange,
208
- flattenMenuPermission,
209
- urlParams,
210
206
  ]);
211
- /* Callbacks */
212
207
  const onToggleChildMenu = useCallback(() => {
213
208
  setState(prev => (Object.assign(Object.assign({}, prev), { isExpandMenu: !prev.isExpandMenu })));
214
209
  }, []);
@@ -226,15 +221,10 @@ export const useLeftMenu = (props) => {
226
221
  onMouseEnter(isCustomized ? customActiveAppKey : activeAppCode);
227
222
  };
228
223
  return {
229
- /* State */
230
224
  state,
231
- /* Zustand */
232
225
  activeAppCode,
233
- /* Data Queries */
234
226
  permissionMenu,
235
- /** Variables */
236
227
  customActiveAppKey,
237
- /* Callbacks */
238
228
  onToggleChildMenu,
239
229
  onMouseEnter,
240
230
  onMouseLeave,
@@ -18,42 +18,28 @@ import { useLeftMenu, useNavigatePath } from './hooks';
18
18
  export const LeftMenu = memo(props => {
19
19
  const { style, className, customization } = props;
20
20
  const { isExpandable = true, isCustomized = false, items = [], onMenuItemClick, } = customization || {};
21
- // Hooks
22
- const {
23
- /* State */
24
- state,
25
- /* Store */
26
- activeAppCode,
27
- /* Data Queries */
28
- permissionMenu,
29
- /** Variables */
30
- customActiveAppKey,
31
- /* Callbacks */
32
- onToggleChildMenu, onMouseEnter, onMouseLeave, onHoverMenuBar, } = useLeftMenu(props);
21
+ const { state, activeAppCode, permissionMenu, customActiveAppKey, onToggleChildMenu, onMouseEnter, onMouseLeave, onHoverMenuBar, } = useLeftMenu(props);
33
22
  const { isPushDifferentDomain, getPath, navigatePath } = useNavigatePath();
34
- // Memo
35
23
  const childMenu = useMemo(() => {
36
24
  const selectedFeatureKey = state.hoverItem ? state.hoverItem : activeAppCode;
37
25
  if (isCustomized)
38
26
  return React.createElement(CustomMenu, { onMenuItemClick: onMenuItemClick });
39
27
  switch (selectedFeatureKey) {
40
- case APP_KEYS.HOME: {
28
+ case APP_KEYS.HOME:
41
29
  return React.createElement(HomeMenu, null);
42
- }
43
30
  default:
44
31
  return React.createElement(CommonMenu, null);
45
32
  }
46
33
  }, [activeAppCode, isCustomized, state.hoverItem, onMenuItemClick]);
47
- // Render components
48
34
  const renderFeatureMenuItems = useCallback((item) => {
49
35
  const { menu_item_name, menu_item, icon_name, menu_item_code, menu_item_path, menu_item_domain, } = item;
50
36
  const isActive = activeAppCode === menu_item_code;
51
37
  const isHover = state.hoverItem === menu_item_code;
52
- const labelComponent = () => (React.createElement("li", { role: "menuitem", className: classNames({ isActive, isHover }) },
38
+ const renderLabel = () => (React.createElement("li", { role: "menuitem", className: classNames({ isActive, isHover }) },
53
39
  React.createElement(IconWrapper, null, isNil(icon_name) ? null : React.createElement(Icon, { type: icon_name })),
54
40
  React.createElement(Typography.Text, null, menu_item_name),
55
41
  React.createElement("div", { className: "popup-triangle" })));
56
- return (React.createElement(FeatureMenuItem, { key: menu_item, onMouseEnter: () => onMouseEnter(menu_item_code) }, isString(menu_item_path) ? (isPushDifferentDomain(menu_item_domain, menu_item_path) ? (React.createElement("div", { onClick: () => navigatePath(menu_item_domain, menu_item_path) }, labelComponent())) : (React.createElement(Link, { to: getPath(menu_item_path), className: "menu-link" }, labelComponent()))) : (labelComponent())));
42
+ return (React.createElement(FeatureMenuItem, { key: menu_item, onMouseEnter: () => onMouseEnter(menu_item_code) }, isString(menu_item_path) ? (isPushDifferentDomain(menu_item_domain, menu_item_path) ? (React.createElement("div", { onClick: () => navigatePath(menu_item_domain, menu_item_path) }, renderLabel())) : (React.createElement(Link, { to: getPath(menu_item_path), className: "menu-link" }, renderLabel()))) : (renderLabel())));
57
43
  }, [activeAppCode, getPath, isPushDifferentDomain, navigatePath, onMouseEnter, state.hoverItem]);
58
44
  const renderCustomizedMenuItems = useCallback((items) => items === null || items === void 0 ? void 0 : items.map(item => {
59
45
  const { key, icon, label } = item;
@@ -89,7 +75,7 @@ export const LeftMenu = memo(props => {
89
75
  React.createElement("div", { className: "menu-content scroll-content" }, renderAppMenuItems()),
90
76
  React.createElement("div", { className: "nav-blank", onMouseEnter: onHoverMenuBar }),
91
77
  React.createElement(PopoverWrapper, { className: "antsomi-scroll-box antsomi-child-menu-popover", onMouseLeave: onMouseLeave },
92
- React.createElement("div", { className: "scroll-content" }, childMenu))),
78
+ React.createElement("div", { className: "scroll-content", style: { width: '200px', maxHeight: '100%' } }, childMenu))),
93
79
  React.createElement("div", { style: { flexShrink: 0 } }, renderSettings())),
94
80
  isExpandable && (React.createElement(ExpandWrapper, { onMouseEnter: onMouseLeave },
95
81
  React.createElement(Icon, { type: "icon-ants-expand-more", style: {
@@ -98,5 +84,5 @@ export const LeftMenu = memo(props => {
98
84
  transform: `rotate(${state.isExpandMenu ? '90deg' : '270deg'})`,
99
85
  }, onClick: onToggleChildMenu })))),
100
86
  React.createElement(ChildMenuWrapper, { isExpand: state.isExpandMenu && isExpandable, className: "antsomi-scroll-box" },
101
- React.createElement("div", { className: "scroll-content" }, childMenu))));
87
+ React.createElement("div", { className: "scroll-content", style: { width: '200px', maxHeight: '100%' } }, childMenu))));
102
88
  });
@@ -26,12 +26,11 @@ export const PopoverWrapper = styled.div `
26
26
  left: 65px;
27
27
  border-radius: ${(_a = THEME === null || THEME === void 0 ? void 0 : THEME.token) === null || _a === void 0 ? void 0 : _a.borderRadiusXL}px;
28
28
  bottom: 15px;
29
- width: 230px;
30
29
  box-shadow: 0px 3px 20px 0px #002e5933;
31
30
  height: calc(100% - ${HEADER_HEIGHT + 15}px);
32
31
  transition: visibility 0s, opacity 0.2s ease-out;
33
32
  z-index: 10;
34
- padding: 10px;
33
+ padding: 20px;
35
34
  box-sizing: border-box;
36
35
  `;
37
36
  export const FeatureMenuWrapper = styled(Flex) `
@@ -84,7 +84,7 @@ export declare const findLastMatchedItemByUrl: (args: {
84
84
  auth?: Partial<PayloadInfo>;
85
85
  }) => TFeatureMenu | undefined;
86
86
  export declare const findPathOfActiveItem: (args: {
87
- activeMenuItem: string;
87
+ activeMenuItem: TFeatureMenu;
88
88
  menuItems: TFeatureMenu[];
89
89
  }) => TFeatureMenu[];
90
90
  /**
@@ -129,6 +129,7 @@ export const getMappingAppChildren = (args) => {
129
129
  menu_item_code: item.channelCode,
130
130
  menu_item_name: item.translateLabel,
131
131
  logo_url: item.logoUrl,
132
+ menu_item_parent: menuItem.menu_item,
132
133
  menu_item_path: getGeneratePath(path, Object.assign(Object.assign({}, auth), { channelId: item.channelId })),
133
134
  }))))) || [];
134
135
  break;
@@ -156,10 +157,12 @@ export const getMappingAppChildren = (args) => {
156
157
  menu_item: childMenuItem.menu_item_code,
157
158
  menu_item_code: childMenuItem.menu_item_code,
158
159
  menu_item_name: childMenuItem.menu_item_name,
160
+ menu_item_parent: appItem.menu_item,
159
161
  })), { children: (_a = (((dashboardObject === null || dashboardObject === void 0 ? void 0 : dashboardObject[childMenuItem.menu_item_code]) || []))) === null || _a === void 0 ? void 0 : _a.map(item => (Object.assign({}, getInitialFeatureMenuItem({
160
162
  menu_item: String(item.dashboardId),
161
163
  menu_item_code: String(item.dashboardId),
162
164
  menu_item_name: item.dashboardName,
165
+ menu_item_parent: childMenuItem.menu_item_code,
163
166
  menu_item_path: getGeneratePath(HOME_REPORT_ROUTES.DETAIL, Object.assign(Object.assign({}, auth), { dashboardId: String(item.dashboardId) })),
164
167
  })))) }));
165
168
  });
@@ -243,14 +246,15 @@ export const findLastMatchedItemByUrl = (args) => {
243
246
  try {
244
247
  const { url, menuItems, auth } = args;
245
248
  const matchedItems = [];
246
- const recursiveFindActiveItem = (items) => {
249
+ const recursiveFindActiveItem = (items, parentId) => {
247
250
  for (const item of items) {
248
- if (!!(item === null || item === void 0 ? void 0 : item.menu_item_path) &&
249
- url.includes(getComparePath(getGeneratePath(item.menu_item_path, auth)))) {
251
+ if ((item === null || item === void 0 ? void 0 : item.menu_item_path) &&
252
+ url.includes(getComparePath(getGeneratePath(item.menu_item_path, auth))) &&
253
+ (!parentId || item.menu_item_parent === parentId)) {
250
254
  matchedItems.push(item);
251
255
  }
252
256
  if ((item === null || item === void 0 ? void 0 : item.children) && item.children.length) {
253
- recursiveFindActiveItem(item.children);
257
+ recursiveFindActiveItem(item.children, String(item.menu_item));
254
258
  }
255
259
  }
256
260
  };
@@ -268,14 +272,15 @@ export const findLastMatchedItemByUrl = (args) => {
268
272
  export const findPathOfActiveItem = (args) => {
269
273
  try {
270
274
  const { activeMenuItem, menuItems } = args;
271
- const recursiveFindPathOfActiveItem = (menuItems) => {
275
+ const recursiveFindPathOfActiveItem = (menuItems, parentId) => {
272
276
  let path = [];
273
277
  for (const item of menuItems) {
274
- if (item.menu_item_code === activeMenuItem) {
278
+ if (item.menu_item_code === (activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.menu_item_code) &&
279
+ (!parentId || (activeMenuItem === null || activeMenuItem === void 0 ? void 0 : activeMenuItem.menu_item_parent) === parentId)) {
275
280
  path.push(item);
276
281
  break;
277
282
  }
278
- const childPath = recursiveFindPathOfActiveItem((item === null || item === void 0 ? void 0 : item.children) || []);
283
+ const childPath = recursiveFindPathOfActiveItem((item === null || item === void 0 ? void 0 : item.children) || [], String(item.menu_item));
279
284
  if (childPath.length) {
280
285
  path = [item, ...childPath];
281
286
  break;
@@ -23,7 +23,7 @@ import { HeaderV2 } from '../../molecules';
23
23
  // Contexts
24
24
  import { AppConfigContext } from '../../..';
25
25
  // Constants
26
- import { MENU_PERMISSIONS } from './constants';
26
+ import { APP_ROLE_SCOPE, MENU_PERMISSIONS } from './constants';
27
27
  import { APP_CODES, APP_IAM_DOMAIN, APP_PERMISSION_DOMAIN, IAM_API, PERMISSION_API, PORTALS_IDS, SOCKET_API, } from '../../../constants';
28
28
  // Css
29
29
  import '@antscorp/processing-notification/dist/index.css';
@@ -35,7 +35,6 @@ export const Layout = memo(props => {
35
35
  const { leftMenuProps, headerProps = {}, workspaceProps, processingNotificationProps, children, onActiveMenuChange, } = props;
36
36
  const _a = leftMenuProps || {}, { className = '' } = _a, restOfLeftMenuProps = __rest(_a, ["className"]);
37
37
  const _b = workspaceProps || {}, { workspaceContentProps } = _b, restOfWorkspaceProps = __rest(_b, ["workspaceContentProps"]);
38
- // Selectors
39
38
  const appConfig = useContextSelector(AppConfigContext, state => state);
40
39
  const { auth, languageCode, appCode, env } = appConfig;
41
40
  const { token, userId, portalId } = auth || {};
@@ -114,14 +113,21 @@ export const Layout = memo(props => {
114
113
  const menuPermission = flattenPermissionList === null || flattenPermissionList === void 0 ? void 0 : flattenPermissionList.find(item => permissionCode === item.menu_code);
115
114
  if (menuPermission) {
116
115
  const checkRoleScope = menuPermission
117
- ? checkingRoleScope({ menuCode: activeItem.menu_item_code, menuPermission })
116
+ ? checkingRoleScope({
117
+ menuCode: menuPermission.menu_code || '',
118
+ menuPermission,
119
+ scope: APP_ROLE_SCOPE.EVERYTHING,
120
+ })
118
121
  : false;
119
122
  if (checkRoleScope) {
120
123
  roleScope = true;
121
124
  break;
122
125
  }
123
126
  }
124
- /** Nếu trong Api Permission không có những có trong @constant MENU_PERMISSIONS thì vẫn trả về True vì có những MENU_CODE mà BA chưa define permission */
127
+ /**
128
+ * Nếu trong Api Permission không có những có trong @constant MENU_PERMISSIONS
129
+ * thì vẫn trả về True vì có những MENU_CODE mà BA chưa define permission
130
+ * */
125
131
  if (isExternalPermissionCode) {
126
132
  roleScope = true;
127
133
  break;
@@ -14,9 +14,6 @@ export declare const MARKETING_CHANNEL_CODE: {
14
14
  * Nếu PERMISSION_CODE không được tìm thấy trong api get permissions và trong @constant MENU_PERMISSIONS thì sẽ ẩn account selection
15
15
  */
16
16
  export declare const MENU_PERMISSIONS: {
17
- ALL_CHANNEL: string;
18
- ORCHESTRATION: string;
19
- CAMPAIGN: string;
20
17
  BATCH_STREAM: string;
21
18
  REALTIME_STREAM: string;
22
19
  DF_DATA_SOURCE: string;
@@ -14,9 +14,6 @@ export const MARKETING_CHANNEL_CODE = {
14
14
  * Nếu PERMISSION_CODE không được tìm thấy trong api get permissions và trong @constant MENU_PERMISSIONS thì sẽ ẩn account selection
15
15
  */
16
16
  export const MENU_PERMISSIONS = {
17
- [MARKETING_CHANNEL_CODE.ALL_CHANNEL]: 'JOURNEY',
18
- [MARKETING_CHANNEL_CODE.ORCHESTRATION]: 'JOURNEY',
19
- [MARKETING_CHANNEL_CODE.CAMPAIGN]: 'JOURNEY',
20
17
  BATCH_STREAM: 'BATCH_STREAM',
21
18
  REALTIME_STREAM: 'REALTIME_STREAM',
22
19
  DF_DATA_SOURCE: 'DF_DATA_SOURCE',
@@ -1,8 +1,10 @@
1
+ /// <reference types="react" />
1
2
  import { HeaderV2Props } from '../../../molecules';
2
3
  import { DeepPartial } from '@antscorp/antsomi-ui/es/types';
3
4
  export interface HeaderStore extends Partial<HeaderV2Props> {
4
5
  }
5
6
  export interface LeftMenuStore {
7
+ onClickCreateDashboard?: React.MouseEventHandler<HTMLElement>;
6
8
  }
7
9
  export interface WorkspaceStore {
8
10
  }
@@ -17,6 +19,10 @@ interface LayoutStore {
17
19
  setLeftMenuState: (state: DeepPartial<LeftMenuStore>) => void;
18
20
  setWorkspaceState: (state: Partial<WorkspaceStore>) => void;
19
21
  setLayoutState: (state: DeepPartial<LayoutStoreState>) => void;
22
+ resetHeaderState: () => void;
23
+ resetLeftMenuState: () => void;
24
+ resetWorkspaceState: () => void;
25
+ resetLayoutState: () => void;
20
26
  }
21
27
  export declare const useLayoutStore: import("zustand").UseBoundStore<import("zustand").StoreApi<LayoutStore>>;
22
28
  export {};
@@ -18,4 +18,16 @@ export const useLayoutStore = create(set => ({
18
18
  setWorkspaceState: newState => set(store => ({
19
19
  state: Object.assign(Object.assign({}, store.state), { workspace: Object.assign(Object.assign({}, store.state.workspace), newState) }),
20
20
  })),
21
+ resetHeaderState: () => set(store => ({
22
+ state: Object.assign(Object.assign({}, store.state), { header: initialState.header }),
23
+ })),
24
+ resetLeftMenuState: () => set(store => ({
25
+ state: Object.assign(Object.assign({}, store.state), { leftMenu: initialState.leftMenu }),
26
+ })),
27
+ resetWorkspaceState: () => set(store => ({
28
+ state: Object.assign(Object.assign({}, store.state), { workspace: initialState.workspace }),
29
+ })),
30
+ resetLayoutState: () => set(store => ({
31
+ state: Object.assign(Object.assign({}, store.state), initialState),
32
+ })),
21
33
  }));
@@ -11,6 +11,6 @@ export declare const checkingRoleScope: (args: {
11
11
  menuCode: string;
12
12
  menuPermission: FeatureMenuPermission;
13
13
  action?: string;
14
- scope?: string;
14
+ scope?: number;
15
15
  isExactly?: boolean;
16
16
  }) => boolean;
@@ -29,15 +29,11 @@ const PATH = 'src/components/template/TemplateListing/components/CategoryListing
29
29
  export const CategoryListing = memo(props => {
30
30
  var _a;
31
31
  const { width = CATEGORY_LISTING_WITH, items = [], loading = false, show = true, checkedCategories = {}, emptyProps, debounceChangeMenu = CATEGORY_DEBOUNCE, header, footer, onMenuChange } = props, restOfProps = __rest(props, ["width", "items", "loading", "show", "checkedCategories", "emptyProps", "debounceChangeMenu", "header", "footer", "onMenuChange"]);
32
- // States
33
32
  const [checkedState, setCheckedState] = useState({});
34
- // Side Effects
35
33
  useEffect(() => {
36
34
  setCheckedState(prev => (isEqual(prev, checkedCategories) ? prev : checkedCategories));
37
35
  }, [checkedCategories]);
38
- // Ref
39
36
  const timeoutAfterChange = useRef(null);
40
- // Handlers
41
37
  const handleClickMenu = e => {
42
38
  var _a;
43
39
  try {
@@ -63,7 +59,6 @@ export const CategoryListing = memo(props => {
63
59
  });
64
60
  }
65
61
  };
66
- // Render components
67
62
  const renderCustomLabel = useCallback((args) => {
68
63
  var _a;
69
64
  try {
@@ -108,10 +103,9 @@ export const CategoryListing = memo(props => {
108
103
  return undefined;
109
104
  }
110
105
  }, [renderCustomLabel]);
111
- // Memo
112
106
  const menuItems = useMemo(() => {
113
107
  const menuItems = [];
114
- items === null || items === void 0 ? void 0 : items.forEach((item, index) => {
108
+ items === null || items === void 0 ? void 0 : items.forEach((item, _) => {
115
109
  // if (index > 0) menuItems.push({ type: 'divider' });
116
110
  const menuItem = getItem(Object.assign(Object.assign({}, item), { parentId: null }), true);
117
111
  if (menuItem)
@@ -25,11 +25,8 @@ import { LoadMoreBlock, TemplateListingWrapper, TemplateWrapper } from './styled
25
25
  // Hooks
26
26
  import { useIntersectionObserver, useListingItemResize } from '@antscorp/antsomi-ui/es/hooks';
27
27
  export const TemplateListing = memo(props => {
28
- // Props
29
28
  const { templatesProps = TEMPLATES_DEFAULT, templateItemProps = TEMPLATE_ITEM_DEFAULT, blankTemplateProps = BLANK_TEMPLATE_DEFAULT, categoryListingProps = CATEGORY_LISTING_DEFAULT, emptyProps = EMPTY_DEFAULT, previewModalProps, } = props;
30
- // States
31
29
  const [openPreviewModal, setOpenPreviewModal] = useState(false);
32
- // Variables
33
30
  const { header, footer, items = [], gap = LISTING_GAP_DEFAULT, loading = false, wrapperClassName, wrapperStyle, onLoadMoreTemplates = () => { }, } = templatesProps || {};
34
31
  const _a = previewModalProps || {}, { onOk, onCancel } = _a, restOfPreviewModalProps = __rest(_a, ["onOk", "onCancel"]);
35
32
  const _b = templateItemProps || {}, { width = THUMBNAIL_CARD_DEFAULT_WIDTH, height = THUMBNAIL_CARD_DEFAULT_HEIGHT, previewBtnProps } = _b, restOfTemplateItemProps = __rest(_b, ["width", "height", "previewBtnProps"]);
@@ -51,7 +48,6 @@ export const TemplateListing = memo(props => {
51
48
  }
52
49
  },
53
50
  });
54
- // Handlers
55
51
  const handleClickThumbnailPreview = (id) => {
56
52
  onClickPreview === null || onClickPreview === void 0 ? void 0 : onClickPreview(id);
57
53
  setOpenPreviewModal(true);
@@ -19,3 +19,6 @@ export * from './useMutationObserver';
19
19
  export * from './useKeyEventCanvas';
20
20
  export * from './useDragEvent';
21
21
  export * from './useDropFile';
22
+ export * from './useEventListener';
23
+ export * from './useDebounceCallback';
24
+ export * from './useWindowSize';
package/es/hooks/index.js CHANGED
@@ -38,3 +38,6 @@ export * from './useMutationObserver';
38
38
  export * from './useKeyEventCanvas';
39
39
  export * from './useDragEvent';
40
40
  export * from './useDropFile';
41
+ export * from './useEventListener';
42
+ export * from './useDebounceCallback';
43
+ export * from './useWindowSize';
@@ -0,0 +1,6 @@
1
+ import type { RefObject } from 'react';
2
+ declare function useEventListener<K extends keyof MediaQueryListEventMap>(eventName: K, handler: (event: MediaQueryListEventMap[K]) => void, element: RefObject<MediaQueryList>, options?: boolean | AddEventListenerOptions): void;
3
+ declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
4
+ declare function useEventListener<K extends keyof HTMLElementEventMap & keyof SVGElementEventMap, T extends Element = K extends keyof HTMLElementEventMap ? HTMLDivElement : SVGElement>(eventName: K, handler: ((event: HTMLElementEventMap[K]) => void) | ((event: SVGElementEventMap[K]) => void), element: RefObject<T>, options?: boolean | AddEventListenerOptions): void;
5
+ declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document>, options?: boolean | AddEventListenerOptions): void;
6
+ export { useEventListener };
@@ -0,0 +1,28 @@
1
+ // Libraries
2
+ import { useEffect, useRef } from 'react';
3
+ // Hooks
4
+ import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
5
+ function useEventListener(eventName, handler, element, options) {
6
+ // Create a ref that stores handler
7
+ const savedHandler = useRef(handler);
8
+ useIsomorphicLayoutEffect(() => {
9
+ savedHandler.current = handler;
10
+ }, [handler]);
11
+ useEffect(() => {
12
+ var _a;
13
+ // Define the listening target
14
+ const targetElement = (_a = element === null || element === void 0 ? void 0 : element.current) !== null && _a !== void 0 ? _a : window;
15
+ if (!(targetElement && targetElement.addEventListener))
16
+ return;
17
+ // Create event listener that calls handler function stored in ref
18
+ const listener = event => {
19
+ savedHandler.current(event);
20
+ };
21
+ targetElement.addEventListener(eventName, listener, options);
22
+ // Remove event listener on cleanup
23
+ return () => {
24
+ targetElement.removeEventListener(eventName, listener, options);
25
+ };
26
+ }, [eventName, element, options]);
27
+ }
28
+ export { useEventListener };
@@ -1,19 +1,14 @@
1
1
  // Libraries
2
- import { useMemo, useRef } from 'react';
2
+ import { useEffect, useMemo, useRef } from 'react';
3
3
  import { useForceUpdate } from '@antscorp/antsomi-ui/es/hooks';
4
4
  import { isNumber } from 'lodash';
5
5
  const DEFAULT_RATIO = 1;
6
6
  export const useListingItemResize = (props) => {
7
7
  var _a;
8
8
  const { initialWidth, gap } = props;
9
- // Ref
10
9
  const ref = useRef(null);
11
- const timeoutAfterChange = useRef(null);
12
- // Hooks
13
10
  const forceUpdate = useForceUpdate();
14
- /* Variables */
15
11
  const containerWidth = (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.offsetWidth;
16
- /* Memo */
17
12
  /**
18
13
  * The number of items per row to display in the container
19
14
  */
@@ -45,39 +40,23 @@ export const useListingItemResize = (props) => {
45
40
  }
46
41
  return DEFAULT_RATIO;
47
42
  }, [containerWidth, gap, initialWidth, itemPerRow]);
48
- // template-listing-wrapper
49
- // Hooks
50
- // useMutationObserver(
51
- // mutationsList => {
52
- // const templateListingElements = mutationsList?.filter(item =>
53
- // (item.target as Element)?.classList?.contains('template-listing-wrapper'),
54
- // );
55
- // // console.log({ templateListingElements, mutationsList });
56
- // // if (timeoutAfterChange) {
57
- // // clearTimeout(timeoutAfterChange.current);
58
- // // }
59
- // // timeoutAfterChange.current = setTimeout(() => {
60
- // // forceUpdate();
61
- // // }, 500);
62
- // },
63
- // ref,
64
- // {
65
- // attributes: true,
66
- // childList: true,
67
- // subtree: true,
68
- // characterData: true,
69
- // attributeOldValue: true,
70
- // characterDataOldValue: true,
71
- // },
72
- // );
73
- /* Events */
74
- window.addEventListener('resize', () => {
75
- if (timeoutAfterChange) {
76
- clearTimeout(timeoutAfterChange.current);
77
- }
78
- timeoutAfterChange.current = setTimeout(() => {
79
- forceUpdate();
80
- }, 200);
81
- });
43
+ useEffect(() => {
44
+ let timeoutAfterChange = null;
45
+ const handleResize = () => {
46
+ if (timeoutAfterChange) {
47
+ clearTimeout(timeoutAfterChange);
48
+ }
49
+ timeoutAfterChange = setTimeout(() => {
50
+ forceUpdate();
51
+ }, 500);
52
+ };
53
+ window.addEventListener('resize', handleResize);
54
+ return () => {
55
+ window.removeEventListener('resize', handleResize);
56
+ if (timeoutAfterChange) {
57
+ clearTimeout(timeoutAfterChange);
58
+ }
59
+ };
60
+ }, [forceUpdate]);
82
61
  return { ref, itemPerRow, ratio, gap };
83
62
  };
@@ -0,0 +1,11 @@
1
+ type WindowSize<T extends number | undefined = number | undefined> = {
2
+ width: T;
3
+ height: T;
4
+ };
5
+ type UseWindowSizeOptions<InitializeWithValue extends boolean | undefined> = {
6
+ initializeWithValue: InitializeWithValue;
7
+ debounceDelay?: number;
8
+ };
9
+ export declare function useWindowSize(options: UseWindowSizeOptions<false>): WindowSize;
10
+ export declare function useWindowSize(options?: Partial<UseWindowSizeOptions<true>>): WindowSize<number>;
11
+ export {};
@@ -0,0 +1,35 @@
1
+ import { useState } from 'react';
2
+ import { useDebounceCallback, useEventListener, useIsomorphicLayoutEffect } from '.';
3
+ const IS_SERVER = typeof window === 'undefined';
4
+ export function useWindowSize(options = {}) {
5
+ let { initializeWithValue = true } = options;
6
+ if (IS_SERVER) {
7
+ initializeWithValue = false;
8
+ }
9
+ const [windowSize, setWindowSize] = useState(() => {
10
+ if (initializeWithValue) {
11
+ return {
12
+ width: window.innerWidth,
13
+ height: window.innerHeight,
14
+ };
15
+ }
16
+ return {
17
+ width: undefined,
18
+ height: undefined,
19
+ };
20
+ });
21
+ const debouncedSetWindowSize = useDebounceCallback(setWindowSize, options.debounceDelay);
22
+ function handleSize() {
23
+ const setSize = options.debounceDelay ? debouncedSetWindowSize : setWindowSize;
24
+ setSize({
25
+ width: window.innerWidth,
26
+ height: window.innerHeight,
27
+ });
28
+ }
29
+ useEventListener('resize', handleSize);
30
+ // Set size at the first client-side load
31
+ useIsomorphicLayoutEffect(() => {
32
+ handleSize();
33
+ }, []);
34
+ return windowSize;
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.291",
3
+ "version": "1.3.5-beta.293",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",