@antscorp/antsomi-ui 1.3.5-beta.382 → 1.3.5-beta.384

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.
@@ -11,6 +11,7 @@ interface EditableNameProps {
11
11
  value?: string;
12
12
  style?: React.CSSProperties;
13
13
  readonly?: boolean;
14
+ maxLength?: number;
14
15
  onBlur?: React.FocusEventHandler<HTMLInputElement>;
15
16
  onChange?: (value: string) => void;
16
17
  }
@@ -3,12 +3,15 @@ import { InputWrapperStyled } from './styled';
3
3
  import { Input, Tooltip } from 'antd';
4
4
  import { THEME } from '@antscorp/antsomi-ui/es/constants';
5
5
  import Icon from '@antscorp/icons';
6
+ import { useInView } from 'react-intersection-observer';
6
7
  import { Spin } from '../../atoms';
7
8
  export const EditableName = React.forwardRef((props, ref) => {
8
9
  var _a;
9
- const { className, isLoading, defaultValue, required, error, value, style, readonly, onBlur, onChange, } = props;
10
+ const { className, isLoading, required, error, value, style, readonly, maxLength, onBlur, onChange, } = props;
11
+ const defaultValue = useRef(props.defaultValue);
10
12
  const [inputWidth, setInputWidth] = useState(1);
11
- const [internalValue, setInternalValue] = useState(value || defaultValue || '');
13
+ const [internalValue, setInternalValue] = useState(value || defaultValue.current || '');
14
+ const { ref: componentInViewRef, inView: componentInView } = useInView();
12
15
  const requiredError = useMemo(() => {
13
16
  const newValue = value ? value.trim() : internalValue.trim();
14
17
  return required && newValue.length === 0 ? 'This field is required' : '';
@@ -29,16 +32,14 @@ export const EditableName = React.forwardRef((props, ref) => {
29
32
  };
30
33
  useEffect(() => {
31
34
  var _a;
32
- if (spanRef.current) {
33
- spanRef.current.innerText = value || defaultValue || '';
34
- setInputWidth(((_a = spanRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 1);
35
- }
36
- // NOTE: the defaultValue props should need use only one time and don't change in component life circle
37
- // eslint-disable-next-line react-hooks/exhaustive-deps
38
- }, [value]);
39
- return (React.createElement(InputWrapperStyled, { className: className || '', style: style },
35
+ if (!spanRef.current || !componentInView)
36
+ return;
37
+ spanRef.current.innerText = value || defaultValue.current || '';
38
+ setInputWidth(((_a = spanRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 1);
39
+ }, [value, componentInView]);
40
+ return (React.createElement(InputWrapperStyled, { className: className || '', style: style, ref: componentInViewRef },
40
41
  React.createElement(Tooltip, { title: value || internalValue },
41
- React.createElement(Input, { readOnly: readonly, ref: inputRef, style: { width: inputWidth + 2 }, defaultValue: defaultValue, value: value, onChange: event => {
42
+ React.createElement(Input, { readOnly: readonly, ref: inputRef, style: { width: inputWidth + 2 }, defaultValue: defaultValue.current, value: value, onChange: event => {
42
43
  var _a;
43
44
  const newValue = event.target.value;
44
45
  if (spanRef.current)
@@ -46,7 +47,7 @@ export const EditableName = React.forwardRef((props, ref) => {
46
47
  setInputWidth(((_a = spanRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 1);
47
48
  setInternalValue(newValue);
48
49
  onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
49
- }, onBlur: onBlur, onKeyDown: onKeyDown })),
50
+ }, onBlur: onBlur, onKeyDown: onKeyDown, maxLength: maxLength })),
50
51
  isLoading ? (React.createElement(Spin, { indicatorSize: 20, style: { paddingLeft: '5px', marginLeft: '10px', alignSelf: 'center' } })) : null,
51
52
  (error || requiredError) && !isLoading ? (React.createElement("div", { className: "suffix-icon-error" },
52
53
  React.createElement(Tooltip, { title: error || requiredError },
@@ -84,7 +84,9 @@ export const HeaderV2 = memo(props => {
84
84
  iamDomain,
85
85
  accountId: userId,
86
86
  networkId: portalId,
87
- urlEditProfile: `${permissionDomain}/${portalId}#/account/profile/`,
87
+ // NOTE: old edit link
88
+ // urlEditProfile: `${permissionDomain}/${portalId}#/account/profile/`,
89
+ urlEditProfile: `${permissionDomain}/${portalId}#/${userId}/permission/account?ui=drawer-detail&accountId=${userId}&tab=settings`,
88
90
  // 6006 is storybook port so direct to sandbox page
89
91
  urlLogout: urlLogoutProvider || window.location.origin,
90
92
  // urlLogout: window.location.origin,
@@ -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
  // 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,6 +13,7 @@ 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;
@@ -49,6 +50,8 @@ export const usePermission = () => {
49
50
  },
50
51
  },
51
52
  });
53
+ const { ownedDashboard = [], sharedDashboard = [] } = (dashboardData === null || dashboardData === void 0 ? void 0 : dashboardData.entries) || {};
54
+ const dashboardList = useMemo(() => uniqBy([...ownedDashboard, ...sharedDashboard], 'dashboardId'), [ownedDashboard, sharedDashboard]);
52
55
  const { data: destinationChannel } = useGetDestinationChannel({
53
56
  args: {
54
57
  auth: {
@@ -84,10 +87,10 @@ export const usePermission = () => {
84
87
  const mappingChildrenMenu = useMemo(() => getMappingAppChildren({
85
88
  menuList: permissionMenu,
86
89
  auth,
87
- dashboardData,
90
+ dashboardList,
88
91
  destinationChannelEntries: destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries,
89
92
  isRecommendation,
90
- }), [auth, dashboardData, destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries, isRecommendation, permissionMenu]);
93
+ }), [auth, dashboardList, destinationChannel === null || destinationChannel === void 0 ? void 0 : destinationChannel.entries, isRecommendation, permissionMenu]);
91
94
  const activeItemPath = useMemo(() => {
92
95
  const url = `${pathname}${hash}`;
93
96
  const matchedCode = findLastMatchedItemByUrl({
@@ -102,6 +105,7 @@ export const usePermission = () => {
102
105
  })
103
106
  : [];
104
107
  }, [auth, hash, mappingChildrenMenu, pathname]);
108
+ useEffect(() => setLeftMenuState({ dashboardList: [] }), [dashboardList, setLeftMenuState]);
105
109
  useEffect(() => {
106
110
  if (!isCustomized) {
107
111
  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 => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.382",
3
+ "version": "1.3.5-beta.384",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",
@@ -59,7 +59,7 @@
59
59
  "not op_mini all"
60
60
  ],
61
61
  "dependencies": {
62
- "@antscorp/icons": "0.27.36",
62
+ "@antscorp/icons": "0.27.37",
63
63
  "@antscorp/image-editor": "1.0.2",
64
64
  "@antscorp/processing-notification": "^1.0.3",
65
65
  "@dnd-kit/core": "^6.1.0",
@@ -111,6 +111,7 @@
111
111
  "react-draggable": "^4.4.5",
112
112
  "react-frame-component": "^5.2.6",
113
113
  "react-konva": "^18.2.10",
114
+ "react-intersection-observer": "^9.10.3",
114
115
  "react-markdown": "^8.0.7",
115
116
  "react-resizable": "^3.0.5",
116
117
  "react-syntax-highlighter": "^15.5.0",