@antscorp/antsomi-ui 1.6.6 → 1.6.7

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.
@@ -29,6 +29,7 @@ export const useHomeMenu = () => {
29
29
  const auth = useLeftMenuContext(store => { var _a; return (_a = store.appConfig) === null || _a === void 0 ? void 0 : _a.auth; });
30
30
  const env = useLeftMenuContext(store => { var _a; return (_a = store.appConfig) === null || _a === void 0 ? void 0 : _a.env; });
31
31
  const dashboardParams = useLeftMenuContext(store => store.dashboardParams);
32
+ const dashboardList = useLeftMenuContext(store => (store === null || store === void 0 ? void 0 : store.dashboardList) || []);
32
33
  const onClickCreateDashboard = useLayoutStore(store => store.state.leftMenu.onClickCreateDashboard);
33
34
  const [removedDashboardId, setRemovedDashboardId] = useState('');
34
35
  const urlParams = useMemo(() => new URLSearchParams(search), [search]);
@@ -73,6 +74,7 @@ export const useHomeMenu = () => {
73
74
  }
74
75
  }, [isRecommendation, auth, pathname, navigate]);
75
76
  const onRemoveDashboard = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
77
+ var _a, _b;
76
78
  if (removedDashboardId && auth && env) {
77
79
  const params = {
78
80
  params: Object.assign(Object.assign({}, dashboardParams), { dashboardId: +removedDashboardId }),
@@ -80,10 +82,33 @@ export const useHomeMenu = () => {
80
82
  };
81
83
  const response = yield removeDashboard(params);
82
84
  if ((response === null || response === void 0 ? void 0 : response.code) === API_RESPONSE_CODE.SUCCESS) {
85
+ let nextDashboardId;
86
+ for (const [index, item] of dashboardList.entries()) {
87
+ if (item.dashboardId === +removedDashboardId) {
88
+ nextDashboardId =
89
+ ((_a = dashboardList === null || dashboardList === void 0 ? void 0 : dashboardList[index + 1]) === null || _a === void 0 ? void 0 : _a.dashboardId) || ((_b = dashboardList === null || dashboardList === void 0 ? void 0 : dashboardList[0]) === null || _b === void 0 ? void 0 : _b.dashboardId);
90
+ break;
91
+ }
92
+ }
93
+ const newPathName = nextDashboardId
94
+ ? getGeneratePath(HOME_REPORT_ROUTES.DETAIL, Object.assign(Object.assign({}, auth), { dashboardId: String(nextDashboardId) }))
95
+ : getGeneratePath(HOME_ROUTE, Object.assign({}, auth));
96
+ if (newPathName !== pathname) {
97
+ navigate(newPathName);
98
+ }
83
99
  setRemovedDashboardId('');
84
100
  }
85
101
  }
86
- }), [auth, dashboardParams, env, removedDashboardId, removeDashboard]);
102
+ }), [
103
+ removedDashboardId,
104
+ auth,
105
+ env,
106
+ dashboardParams,
107
+ removeDashboard,
108
+ dashboardList,
109
+ pathname,
110
+ navigate,
111
+ ]);
87
112
  return {
88
113
  children: customChildren,
89
114
  removedDashboardId,
@@ -1,7 +1,7 @@
1
1
  // Libraries
2
2
  import React, { memo, useLayoutEffect, useState } from 'react';
3
3
  import Icon from '@antscorp/icons';
4
- import { isNil, uniq } from 'lodash';
4
+ import { isEmpty, isNil, uniq } from 'lodash';
5
5
  import classNames from 'classnames';
6
6
  import { Link } from 'react-router-dom';
7
7
  // Components
@@ -12,7 +12,7 @@ import { Flex } from '../../../../../atoms';
12
12
  import { LabelCustom, LabelWrapper, MenuWrapper, OptionDropdownWrapper } from './styled';
13
13
  import { IconWrapper } from '../../../styled';
14
14
  // Constants
15
- import { ICON_SIZE } from '../../../constants';
15
+ import { HOME_MENU_ITEMS, ICON_SIZE } from '../../../constants';
16
16
  // Utils
17
17
  import { findActiveAppCodeByUrl, findLastMatchedItemByUrl, getMenuItem } from '../../../utils';
18
18
  import { findItemByPermissionCode, recursiveFindItemByKey, recursiveFindParentOfActiveItem, } from './utils';
@@ -20,6 +20,12 @@ import { findItemByPermissionCode, recursiveFindItemByKey, recursiveFindParentOf
20
20
  import { useNavigatePath } from '../../../hooks';
21
21
  // Contexts
22
22
  import { useLeftMenuContext } from '../../../contexts';
23
+ const noDashboardItem = {
24
+ key: 'no_dashboard',
25
+ label: 'No dashboard available',
26
+ disabled: true,
27
+ icon: null,
28
+ };
23
29
  const styles = {
24
30
  dropdownMenu: { width: '130px', padding: '8px 0' },
25
31
  dotIcon: { marginTop: '2px', zIndex: 1000, flexShrink: 0, fontSize: 16 },
@@ -146,7 +152,8 @@ export const ChildMenu = memo(props => {
146
152
  const customMenuItems = (args) => {
147
153
  var _a;
148
154
  return (_a = args === null || args === void 0 ? void 0 : args.items) === null || _a === void 0 ? void 0 : _a.map(item => {
149
- const { key, label, children, icon, logo_url, menu_item_path = null, menu_item_domain = null, options, optionCallback, } = item;
155
+ const { key, label, children, icon, logo_url, menu_item_path = null, menu_item_domain = null, options, disabled, optionCallback, } = item;
156
+ const isOwnerDashboardKey = key === HOME_MENU_ITEMS.DASHBOARD.menu_item_code;
150
157
  const renderLabel = () => (React.createElement(LabelWrapper, null,
151
158
  React.createElement(LabelCustom, { ellipsis: { tooltip: label } }, label),
152
159
  (options === null || options === void 0 ? void 0 : options.length) && !isRecommendation && (React.createElement(OptionDropdownWrapper, null,
@@ -173,7 +180,11 @@ export const ChildMenu = memo(props => {
173
180
  label: (React.createElement(Flex, { gap: 10, align: "center", justify: "space-between", style: { height: '100%' } },
174
181
  renderIcon(),
175
182
  React.createElement(Flex, { style: styles.menuItemTitle, align: "center" }, renderTitle()))),
176
- children: customMenuItems({ parent: item, items: children }),
183
+ disabled,
184
+ children: customMenuItems({
185
+ parent: item,
186
+ items: isOwnerDashboardKey && isEmpty(children) ? [noDashboardItem] : children,
187
+ }),
177
188
  };
178
189
  });
179
190
  };
@@ -1,6 +1,6 @@
1
1
  export declare const usePermission: () => {
2
- mappingChildrenMenu: import("../../../../models/LeftMenu").TFeatureMenu[];
3
- permissionMenu: import("../../../../models/LeftMenu").TFeatureMenu[];
4
- activeItemPath: import("../../../../models/LeftMenu").TFeatureMenu[];
5
- flattenMenuPermission: import("../../../../models/LeftMenu").FeatureMenuPermission[];
2
+ mappingChildrenMenu: import("@antscorp/antsomi-ui/es/models/LeftMenu").TFeatureMenu[];
3
+ permissionMenu: import("@antscorp/antsomi-ui/es/models/LeftMenu").TFeatureMenu[];
4
+ activeItemPath: import("@antscorp/antsomi-ui/es/models/LeftMenu").TFeatureMenu[];
5
+ flattenMenuPermission: import("@antscorp/antsomi-ui/es/models/LeftMenu").FeatureMenuPermission[];
6
6
  };
@@ -1,6 +1,6 @@
1
1
  // Libraries
2
2
  import { useEffect, useMemo } from 'react';
3
- import { sortBy } from 'lodash';
3
+ import { sortBy, uniqBy } from 'lodash';
4
4
  // Queries
5
5
  import { useGetDashboard, useGetDestinationChannel, useGetListMenu, useGetListMenuPermission, } from '@antscorp/antsomi-ui/es/queries/LeftMenu';
6
6
  // Stores
@@ -13,19 +13,21 @@ export const usePermission = () => {
13
13
  const appConfig = useLeftMenuContext(store => store.appConfig);
14
14
  const isCustomized = useLeftMenuContext(store => store.isCustomized);
15
15
  const isRecommendation = useLeftMenuContext(store => store.isRecommendation);
16
+ const setLeftMenuState = useLeftMenuContext(store => store.setState);
16
17
  const { isGrouped, objectId, objectType } = useLeftMenuContext(store => store.dashboardParams);
17
18
  const { auth, languageCode = 'en', env = 'development', permissionDomain } = appConfig || {};
18
19
  const { pathname, hash } = window.location;
19
20
  const { data: menuList } = useGetListMenu({
20
21
  args: {
21
22
  auth: {
23
+ // token: '5474r2x214r2b4b4v2d4y444u2v5q2p5o4d4c4f424e4' || auth?.token,
22
24
  token: ['development', 'sandbox'].includes(env)
23
25
  ? '5474r2x214r2b4b4v2d4y444u2v5q2p5o4d4c4f424e4'
24
26
  : auth === null || auth === void 0 ? void 0 : auth.token,
25
27
  // url: 'https://sandbox-permission.ants.vn',
26
28
  url: ['development', 'sandbox'].includes(env)
27
29
  ? 'https://sandbox-permission.ants.vn'
28
- : permissionDomain, // NOTE: Hard for sandbox, development
30
+ : permissionDomain || PERMISSION_API, // NOTE: Hard for sandbox, development
29
31
  portalId: auth === null || auth === void 0 ? void 0 : auth.portalId,
30
32
  userId: auth === null || auth === void 0 ? void 0 : auth.userId,
31
33
  accountId: auth === null || auth === void 0 ? void 0 : auth.accountId,
@@ -35,7 +37,7 @@ export const usePermission = () => {
35
37
  },
36
38
  },
37
39
  options: {
38
- enabled: !!(auth === null || auth === void 0 ? void 0 : auth.userId) && !!auth.portalId && !!permissionDomain,
40
+ enabled: !!(auth === null || auth === void 0 ? void 0 : auth.userId) && !!auth.portalId,
39
41
  },
40
42
  });
41
43
  const { data: dashboardData, refetch: refetchDashboard } = useGetDashboard({
@@ -54,6 +56,8 @@ export const usePermission = () => {
54
56
  },
55
57
  },
56
58
  });
59
+ const { ownedDashboard = [], sharedDashboard = [] } = (dashboardData === null || dashboardData === void 0 ? void 0 : dashboardData.entries) || {};
60
+ const dashboardList = useMemo(() => uniqBy([...ownedDashboard, ...sharedDashboard], 'dashboardId'), [ownedDashboard, sharedDashboard]);
57
61
  const { data: destinationChannel } = useGetDestinationChannel({
58
62
  args: {
59
63
  auth: {
@@ -89,10 +93,10 @@ export const usePermission = () => {
89
93
  const mappingChildrenMenu = useMemo(() => getMappingAppChildren({
90
94
  menuList: permissionMenu,
91
95
  auth,
92
- dashboardData,
96
+ dashboardList,
93
97
  destinationChannelEntries: destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries,
94
98
  isRecommendation,
95
- }), [auth, dashboardData, destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries, isRecommendation, permissionMenu]);
99
+ }), [auth, dashboardList, destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries, isRecommendation, permissionMenu]);
96
100
  const activeItemPath = useMemo(() => {
97
101
  const url = `${pathname}${hash}`;
98
102
  const matchedCode = findLastMatchedItemByUrl({
@@ -107,6 +111,7 @@ export const usePermission = () => {
107
111
  })
108
112
  : [];
109
113
  }, [auth, hash, mappingChildrenMenu, pathname]);
114
+ useEffect(() => setLeftMenuState({ dashboardList: [] }), [dashboardList, setLeftMenuState]);
110
115
  useEffect(() => {
111
116
  if (!isCustomized) {
112
117
  const receivePostMessage = (event) => {
@@ -1,4 +1,4 @@
1
- import { TFeatureMenu } from '@antscorp/antsomi-ui/es/models/LeftMenu';
1
+ import { TDashboard, TFeatureMenu } from '@antscorp/antsomi-ui/es/models/LeftMenu';
2
2
  import { TMenuItem } from '../types';
3
3
  import { AppConfigProviderProps } from '@antscorp/antsomi-ui/es/providers';
4
4
  export interface LeftMenuStoreProps {
@@ -17,6 +17,7 @@ export interface LeftMenuStoreProps {
17
17
  objectType: string;
18
18
  isGrouped: boolean;
19
19
  };
20
+ dashboardList?: TDashboard[];
20
21
  onMenuClick?: (key: string, keyPath: string[]) => void;
21
22
  }
22
23
  export interface LeftMenuState extends LeftMenuStoreProps {
@@ -3,6 +3,7 @@ export type TMenuItem = Omit<Partial<TFeatureMenu>, 'children' | keyof TRequireM
3
3
  key: string;
4
4
  label: string;
5
5
  icon: string | null;
6
+ disabled?: boolean;
6
7
  children?: TMenuItem[];
7
8
  } & TOption;
8
9
  export type TMenuFeatureItem = Omit<Partial<TFeatureMenu>, 'children'> & TRequireMenuItemKey & TOption & {
@@ -1,4 +1,4 @@
1
- import { FeatureMenuPermission, TDashboardResponse, TDestinationChannel, TFeatureMenu } from '@antscorp/antsomi-ui/es/models/LeftMenu';
1
+ import { FeatureMenuPermission, TDashboard, TDestinationChannel, TFeatureMenu } from '@antscorp/antsomi-ui/es/models/LeftMenu';
2
2
  import { PayloadInfo } from '@antscorp/antsomi-ui/es/types';
3
3
  import { TMenuFeatureItem, TMenuItem } from '../types';
4
4
  /**
@@ -63,7 +63,7 @@ export declare const recursiveGetMenuItemByPermission: (featureMenuItem: TFeatur
63
63
  export declare const getMappingAppChildren: (args: {
64
64
  menuList: TFeatureMenu[];
65
65
  auth?: Partial<PayloadInfo>;
66
- dashboardData?: TDashboardResponse;
66
+ dashboardList?: TDashboard[];
67
67
  destinationChannelEntries?: TDestinationChannel[];
68
68
  isRecommendation?: boolean;
69
69
  }) => TFeatureMenu[];
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  // Libraries
13
- import { cloneDeep, isArray, isEmpty, sortBy, uniqBy } from 'lodash';
13
+ import { cloneDeep, isArray, isEmpty, sortBy } from 'lodash';
14
14
  // Constants
15
15
  import { APP_KEYS, MARKETING_CHANNEL_KEY, HOME_MENU_ITEMS, MARKETING_ROUTES, MENU_ITEM_TYPE, RENDER_OPTION, HOME_REPORT_ROUTES, SETTING_APP, } from '../constants';
16
16
  import { MARKETING_CHANNEL_CODE } from '../../../template/Layout/constants';
@@ -132,7 +132,7 @@ export const recursiveGetMenuItemByPermission = (featureMenuItem) => {
132
132
  };
133
133
  /** Map children to each App Item */
134
134
  export const getMappingAppChildren = (args) => {
135
- const { menuList, dashboardData, auth, destinationChannelEntries, isRecommendation } = args;
135
+ const { menuList, dashboardList, auth, destinationChannelEntries, isRecommendation } = args;
136
136
  const recursiveAddRenderOption = (menuItem) => {
137
137
  var _a;
138
138
  const cloneMenuItem = cloneDeep(menuItem);
@@ -170,11 +170,9 @@ export const getMappingAppChildren = (args) => {
170
170
  var _a, _b;
171
171
  switch (appItem.menu_item_code) {
172
172
  case APP_KEYS.HOME: {
173
- const { ownedDashboard = [], sharedDashboard = [] } = (dashboardData === null || dashboardData === void 0 ? void 0 : dashboardData.entries) || {};
174
- uniqBy([...ownedDashboard, ...sharedDashboard], 'dashboardId');
175
173
  const dashboardObject = {
176
174
  sharedDashboard: [],
177
- ownedDashboard: uniqBy([...ownedDashboard, ...sharedDashboard], 'dashboardId'),
175
+ ownedDashboard: dashboardList,
178
176
  recentDashboard: [],
179
177
  };
180
178
  appItem.children = (_a = Object.values(HOME_MENU_ITEMS)) === null || _a === void 0 ? void 0 : _a.map(childMenuItem => {
@@ -63,7 +63,7 @@ export const Layout = memo(props => {
63
63
  characterDataOldValue: true,
64
64
  });
65
65
  // Memo
66
- const permissionDomain = useMemo(() => {
66
+ const permissionDomain = useDeepCompareMemo(() => {
67
67
  var _a;
68
68
  /**
69
69
  * Priority for permission domain
@@ -117,7 +117,8 @@ export const Layout = memo(props => {
117
117
  const mergeHeaderProps = useDeepCompareMemo(() => merge(cloneDeep(initialHeaderProps), header), [initialHeaderProps, header]);
118
118
  const _b = useDeepCompareMemo(() => merge(cloneDeep(contentWrapperProps), cloneDeep(contentWrapper)), [contentWrapperProps, contentWrapper]), { noPadding } = _b, mergeContentWrapperProps = __rest(_b, ["noPadding"]);
119
119
  const mergeWorkSpaceProps = useDeepCompareMemo(() => merge(cloneDeep(restOfWorkspaceProps), omit(workspace, 'workspaceContentProps')), [restOfWorkspaceProps, workspace]);
120
- const _c = useDeepCompareMemo(() => merge(cloneDeep(leftMenuProps), cloneDeep(leftMenu)), [leftMenuProps, leftMenu]), { className: leftMenuClassName, show: showLeftMenu = true } = _c, mergeLeftMenuProps = __rest(_c, ["className", "show"]);
120
+ const _c = useDeepCompareMemo(() => merge(cloneDeep(leftMenuProps), cloneDeep(leftMenu)), [leftMenuProps, leftMenu, appConfig]), { className: leftMenuClassName, show: showLeftMenu = true } = _c, mergeLeftMenuProps = __rest(_c, ["className", "show"]);
121
+ const leftMenuAppConfig = useDeepCompareMemo(() => omit(Object.assign(Object.assign({}, appConfig), { permissionDomain }), ['setAppConfig']), [appConfig]);
121
122
  const antsProcessingNotificationConfig = useMemo(() => (Object.assign({ permissionDomain, socketDomain: SOCKET_API, token, accountId: userId, userId, lang: languageCode, networkId: portalId }, processingNotificationProps)), [permissionDomain, token, userId, languageCode, portalId, processingNotificationProps]);
122
123
  const onActiveMenuCodeChange = useCallback((activeItemPath, flattenPermissionList) => {
123
124
  var _a;
@@ -130,7 +131,7 @@ export const Layout = memo(props => {
130
131
  return (React.createElement(LayoutWrapper, { showLeftMenu: !!showLeftMenu },
131
132
  React.createElement(HeaderV2, Object.assign({}, mergeHeaderProps, { showLogo: !showLeftMenu })),
132
133
  React.createElement(Flex, { className: "layout-body" },
133
- showLeftMenu && (React.createElement(LeftMenu, Object.assign({ className: `layout-body__menu ${leftMenuClassName}` }, mergeLeftMenuProps, { appConfig: Object.assign(Object.assign({}, appConfig), { permissionDomain }), onActiveMenuCodeChange: onActiveMenuCodeChange }))),
134
+ showLeftMenu && (React.createElement(LeftMenu, Object.assign({ className: `layout-body__menu ${leftMenuClassName}` }, mergeLeftMenuProps, { appConfig: leftMenuAppConfig, onActiveMenuCodeChange: onActiveMenuCodeChange }))),
134
135
  React.createElement(ContentWrapper, Object.assign({ "$noPadding": noPadding, "$noSpaceTopContent": noSpaceTopContent }, mergeContentWrapperProps), activeMenuCode === HOME_MENU_ITEMS.RECOMMENDATION.menu_item_code ? (React.createElement("div", { className: "layout-body__content" },
135
136
  React.createElement(RecommendationWorkspace, null))) : (React.createElement("div", Object.assign({ className: `layout-body__content ${(workspaceProps === null || workspaceProps === void 0 ? void 0 : workspaceProps.className) || ''}` }, mergeWorkSpaceProps),
136
137
  React.createElement(NotificationWrapper, { ref: notificationWrapperRef },
@@ -1,13 +1,15 @@
1
1
  // Libraries
2
- import React, { useMemo, useState } from 'react';
3
- import { createContext } from 'use-context-selector';
4
2
  import { merge } from 'lodash';
3
+ import React, { useState } from 'react';
4
+ import { createContext } from 'use-context-selector';
5
+ // Hooks
6
+ import { useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
5
7
  const initialContext = { setAppConfig: () => { } };
6
8
  const AppConfigContext = createContext(initialContext);
7
9
  const AppConfigProvider = props => {
8
10
  const { value = initialContext, children } = props;
9
11
  const [appConfig, setAppConfig] = useState(value);
10
- const mergedValue = useMemo(() => (Object.assign(Object.assign({}, merge(value, appConfig)), { setAppConfig })), [appConfig, value]);
12
+ const mergedValue = useDeepCompareMemo(() => (Object.assign(Object.assign({}, merge(value, appConfig)), { setAppConfig })), [appConfig, value]);
11
13
  return React.createElement(AppConfigContext.Provider, { value: mergedValue }, children);
12
14
  };
13
15
  export { AppConfigContext, AppConfigProvider };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",