@antscorp/antsomi-ui 1.3.5-beta.235 → 1.3.5-beta.237
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.
- package/es/components/molecules/AccountSelection/AccountListing.d.ts +0 -1
- package/es/components/molecules/AccountSelection/AccountListing.js +1 -13
- package/es/components/molecules/AccountSelection/AccountSelection.js +3 -3
- package/es/components/molecules/HeaderV2/HeaderV2.js +11 -25
- package/es/components/molecules/TemplateSaveAs/TemplateSaveAs.js +1 -0
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/BigImage.d.ts +1 -0
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/BigImage.js +2 -2
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/ImageSlider.d.ts +1 -0
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/ImageSlider.js +3 -3
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/SmallImage.d.ts +1 -0
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/SmallImage.js +2 -2
- package/es/components/molecules/ThumbnailCard/ThumbnailCard.js +2 -2
- package/es/components/molecules/ThumbnailCard/types.d.ts +2 -1
- package/es/components/organism/LeftMenu/components/CustomMenu/index.d.ts +6 -0
- package/es/components/organism/LeftMenu/components/CustomMenu/index.js +14 -0
- package/es/components/organism/LeftMenu/components/common/ChildMenu/index.js +35 -16
- package/es/components/organism/LeftMenu/components/common/ChildMenu/utils.d.ts +3 -2
- package/es/components/organism/LeftMenu/components/common/ChildMenu/utils.js +3 -3
- package/es/components/organism/LeftMenu/components/index.d.ts +1 -0
- package/es/components/organism/LeftMenu/components/index.js +1 -0
- package/es/components/organism/LeftMenu/constants/sampleData.d.ts +1 -0
- package/es/components/organism/LeftMenu/constants/sampleData.js +90 -0
- package/es/components/organism/LeftMenu/hooks/index.d.ts +1 -0
- package/es/components/organism/LeftMenu/hooks/index.js +1 -0
- package/es/components/organism/LeftMenu/hooks/useLeftMenu.d.ts +3 -0
- package/es/components/organism/LeftMenu/hooks/useLeftMenu.js +86 -35
- package/es/components/organism/LeftMenu/hooks/useNavigatePath.js +2 -4
- package/es/components/organism/LeftMenu/index.d.ts +7 -3
- package/es/components/organism/LeftMenu/index.js +43 -24
- package/es/components/organism/LeftMenu/stores/index.d.ts +6 -0
- package/es/components/organism/LeftMenu/stores/index.js +10 -1
- package/es/components/organism/LeftMenu/styled.js +1 -9
- package/es/components/organism/LeftMenu/utils/index.d.ts +31 -0
- package/es/components/organism/LeftMenu/utils/index.js +50 -0
- package/es/providers/AppConfigProvider/contexts/index.d.ts +5 -2
- package/es/providers/AppConfigProvider/contexts/index.js +6 -3
- package/es/providers/AppConfigProvider/selector.d.ts +1 -1
- package/package.json +1 -1
|
@@ -11,7 +11,6 @@ export interface AccountListingProps {
|
|
|
11
11
|
};
|
|
12
12
|
showAllAccount?: boolean;
|
|
13
13
|
currentAccount?: string | 'ALL_ACCOUNT';
|
|
14
|
-
onLabelChange?: (label: string) => void;
|
|
15
14
|
onChange?: (userId: number | 'ALL_ACCOUNT') => void;
|
|
16
15
|
}
|
|
17
16
|
export declare const AccountListing: React.FC<AccountListingProps>;
|
|
@@ -7,7 +7,7 @@ import { PORTALS_IDS } from '@antscorp/antsomi-ui/es/constants';
|
|
|
7
7
|
import { searchStringQuery } from '@antscorp/antsomi-ui/es/utils';
|
|
8
8
|
import { useGetAccountList, useGetPermissionAccountList, useGetRecentAccount } from '../../..';
|
|
9
9
|
export const AccountListing = props => {
|
|
10
|
-
const { className, apiConfig, showAllAccount = true, currentAccount,
|
|
10
|
+
const { className, apiConfig, showAllAccount = true, currentAccount, onChange } = props;
|
|
11
11
|
const { domain, token, userId, appCode, portalId } = apiConfig;
|
|
12
12
|
const { data } = useGetAccountList({
|
|
13
13
|
apiConfig,
|
|
@@ -48,21 +48,9 @@ export const AccountListing = props => {
|
|
|
48
48
|
return (data === null || data === void 0 ? void 0 : data.entries) || [];
|
|
49
49
|
}, [data === null || data === void 0 ? void 0 : data.entries, permissionAccountList, portalId]);
|
|
50
50
|
const [searchValue, setSearchValue] = useState('');
|
|
51
|
-
// const currentAccountInfo = useMemo(
|
|
52
|
-
// () => accountData?.find(account => String(account.userId) === currentAccount),
|
|
53
|
-
// [accountData, currentAccount],
|
|
54
|
-
// );
|
|
55
51
|
const isAllAccount = !currentAccount || currentAccount === 'ALL_ACCOUNT';
|
|
56
|
-
// useEffect(() => {
|
|
57
|
-
// // HACK: this use for popover input label
|
|
58
|
-
// const inputLabel = isAllAccount ? 'All account' : currentAccountInfo?.userName;
|
|
59
|
-
// onLabelChange?.(inputLabel);
|
|
60
|
-
// }, [currentAccountInfo?.userName, isAllAccount, onLabelChange]);
|
|
61
52
|
const handleSelectAccount = useCallback((userId) => {
|
|
62
53
|
onChange === null || onChange === void 0 ? void 0 : onChange(userId);
|
|
63
|
-
// const userInfo = accountData?.find(account => String(account.userId) === userId);
|
|
64
|
-
// const inputLabel = userId === 'ALL_ACCOUNT' ? 'All account' : userInfo?.userName;
|
|
65
|
-
// onLabelChange?.(inputLabel);
|
|
66
54
|
}, [onChange]);
|
|
67
55
|
return (React.createElement(AccountSelectionStyled, { className: className },
|
|
68
56
|
React.createElement(Input, { placeholder: "Search", suffix: React.createElement(Icon, { type: "icon-ants-search-2", style: { fontSize: '24px' } }), value: searchValue, onChange: event => setSearchValue(event.target.value) }),
|
|
@@ -24,6 +24,7 @@ export const AccountSelection = props => {
|
|
|
24
24
|
// const [searchValue, setSearchValue] = useState<string>('');
|
|
25
25
|
const { apiConfig, currentAccount } = props;
|
|
26
26
|
const { domain, token, userId, appCode, portalId } = apiConfig;
|
|
27
|
+
// Queries
|
|
27
28
|
const { data } = useGetAccountList({
|
|
28
29
|
apiConfig,
|
|
29
30
|
options: {
|
|
@@ -57,6 +58,7 @@ export const AccountSelection = props => {
|
|
|
57
58
|
return (data === null || data === void 0 ? void 0 : data.entries) || [];
|
|
58
59
|
}, [data === null || data === void 0 ? void 0 : data.entries, permissionAccountList, portalId]);
|
|
59
60
|
const currentAccountInfo = useMemo(() => accountData === null || accountData === void 0 ? void 0 : accountData.find(account => String(account.userId) === currentAccount), [accountData, currentAccount]);
|
|
61
|
+
/** If oid is null, default is 'ALL_ACCOUNT' */
|
|
60
62
|
const isAllAccount = !currentAccount || currentAccount === 'ALL_ACCOUNT';
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
const newLabel = isAllAccount ? 'All account' : currentAccountInfo === null || currentAccountInfo === void 0 ? void 0 : currentAccountInfo.userName;
|
|
@@ -66,9 +68,7 @@ export const AccountSelection = props => {
|
|
|
66
68
|
setOpen(false);
|
|
67
69
|
onChange === null || onChange === void 0 ? void 0 : onChange(userId);
|
|
68
70
|
}, [onChange]);
|
|
69
|
-
return (show && (React.createElement(Popover, { content: React.createElement(AccountListing, Object.assign({}, accountListingProps, { onChange: handleSelectAccount
|
|
70
|
-
// getPopupContainer={triggerNode => triggerNode}
|
|
71
|
-
getPopupContainer: getPopupContainer, placement: "bottomLeft", arrow: false, open: open, onOpenChange: setOpen, zIndex: zIndex || 1300 },
|
|
71
|
+
return (show && (React.createElement(Popover, { content: React.createElement(AccountListing, Object.assign({}, accountListingProps, { onChange: handleSelectAccount })), trigger: "click", overlayInnerStyle: { padding: 0 }, getPopupContainer: getPopupContainer, placement: "bottomLeft", arrow: false, open: open, onOpenChange: setOpen, zIndex: zIndex || 1300 },
|
|
72
72
|
React.createElement(PopoverFieldStyled, { className: `${inputStyle || ''} ${inputClassName || ''}` },
|
|
73
73
|
React.createElement(Tooltip, { title: inputLabel },
|
|
74
74
|
React.createElement("span", { className: !inputLabel ? 'is-placeholder' : '' }, inputLabel || 'Select an account')),
|
|
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import React, { memo,
|
|
12
|
+
import React, { memo, useMemo, useState } from 'react';
|
|
13
13
|
// Styled
|
|
14
14
|
import { HeaderV2Styled } from './styled';
|
|
15
15
|
// Components
|
|
@@ -34,22 +34,6 @@ export const HeaderV2 = memo(props => {
|
|
|
34
34
|
const oidParam = urlParams.get('oid');
|
|
35
35
|
// States
|
|
36
36
|
const [selectedAccount, setSelectedAccount] = useState(`${useURLParam ? oidParam !== null && oidParam !== void 0 ? oidParam : '' : (_a = currentAccount !== null && currentAccount !== void 0 ? currentAccount : userId) !== null && _a !== void 0 ? _a : ''}`);
|
|
37
|
-
// Side effects
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (!useURLParam)
|
|
40
|
-
return;
|
|
41
|
-
if (!oidParam) {
|
|
42
|
-
// urlParams.append('oid', 'ALL_ACCOUNT');
|
|
43
|
-
// urlParams.append('oid', `${currentAccount ?? userId ?? 'ALL_ACCOUNT'}`);
|
|
44
|
-
// const newUrl = `${window.location.pathname}?${urlParams.toString()}${window.location.hash}`;
|
|
45
|
-
// window.history.replaceState(null, '', newUrl);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
// const newUrl = `${window.location.pathname}?${urlParams.toString()}${window.location.hash}`;
|
|
49
|
-
// window.history.replaceState(null, '', newUrl);
|
|
50
|
-
}
|
|
51
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
|
-
}, [oidParam, useURLParam, userId]);
|
|
53
37
|
// Memo
|
|
54
38
|
const accountSelectionDomain = useMemo(() => {
|
|
55
39
|
var _a;
|
|
@@ -96,16 +80,18 @@ export const HeaderV2 = memo(props => {
|
|
|
96
80
|
token,
|
|
97
81
|
lang: language,
|
|
98
82
|
};
|
|
83
|
+
// Handlers
|
|
84
|
+
const handleChangeAccount = (userId) => {
|
|
85
|
+
setSelectedAccount(String(userId));
|
|
86
|
+
if (useURLParam) {
|
|
87
|
+
urlParams.set('oid', `${userId}`);
|
|
88
|
+
history.replace({ search: urlParams.toString() });
|
|
89
|
+
}
|
|
90
|
+
onSelectAccount === null || onSelectAccount === void 0 ? void 0 : onSelectAccount(String(userId));
|
|
91
|
+
};
|
|
99
92
|
return (React.createElement(HeaderV2Styled, { className: className || '', style: style },
|
|
100
93
|
React.createElement("div", { className: "left-side" },
|
|
101
|
-
React.createElement(AccountSelection, Object.assign({}, accountSelectionProps, { currentAccount: selectedAccount, apiConfig: accountSelectionApiConfig, onChange:
|
|
102
|
-
setSelectedAccount(String(userId));
|
|
103
|
-
if (useURLParam) {
|
|
104
|
-
urlParams.set('oid', `${userId}`);
|
|
105
|
-
history.replace({ search: urlParams.toString() });
|
|
106
|
-
}
|
|
107
|
-
onSelectAccount === null || onSelectAccount === void 0 ? void 0 : onSelectAccount(String(userId));
|
|
108
|
-
}, inputStyle: inputStyle })),
|
|
94
|
+
React.createElement(AccountSelection, Object.assign({}, accountSelectionProps, { currentAccount: selectedAccount, apiConfig: accountSelectionApiConfig, onChange: handleChangeAccount, inputStyle: inputStyle })),
|
|
109
95
|
typeof pageTitle === 'string' ? React.createElement("div", { className: "page-title" }, pageTitle) : pageTitle),
|
|
110
96
|
React.createElement("div", { className: "right-side" },
|
|
111
97
|
showHelp ? React.createElement(Help, Object.assign({ configs: helpConfigProps }, helpProps)) : null,
|
|
@@ -32,6 +32,7 @@ export const TemplateSaveAs = props => {
|
|
|
32
32
|
const form = formProps || internalForm;
|
|
33
33
|
const { show: isShowShareAccess } = shareAccess, shareAccessProps = __rest(shareAccess, ["show"]);
|
|
34
34
|
const { label: imageReviewLabel } = imageReview, restImageReviewProps = __rest(imageReview, ["label"]);
|
|
35
|
+
console.log('🚀 ~ restImageReviewProps:', restImageReviewProps);
|
|
35
36
|
const { isLoading, label: templateLabel, defaultNewTemplateName = `Untitled Media Template#${dayjs().format('YYYY-MM-DD HH:mm:ss')}`, selectPlaceholder = 'Please select an item', placeholder = 'Enter your media template name', validateName, onSearch, onNamePopupScroll, onScrollToBottom, } = templateNamesOptions || {};
|
|
36
37
|
const { label: descriptionLabel, placeholder: descriptionPlaceholder } = descriptionOptions || {};
|
|
37
38
|
const { saveNewText = 'Save as a new media template', saveExistText = 'Save as an existing media template', saveNewValue = 'save-new', saveExistValue = 'save-exist', } = saveOptions || {};
|
|
@@ -4,13 +4,13 @@ import { Button } from '@antscorp/antsomi-ui/es/components';
|
|
|
4
4
|
import Icon from '@antscorp/icons';
|
|
5
5
|
import { checkShowSkeletonBaseUrl, getUrlNoCache } from '@antscorp/antsomi-ui/es/utils';
|
|
6
6
|
export const BigImage = React.memo(props => {
|
|
7
|
-
const { url, isDefaultThumbnail, isHideDefaultButton, index, showSkeleton, onClickDefaultButton, } = props;
|
|
7
|
+
const { url, isDefaultThumbnail, isHideDefaultButton, index, showSkeleton, imageFit, onClickDefaultButton, } = props;
|
|
8
8
|
const currentTime = useMemo(() => new Date(), []);
|
|
9
9
|
const timeGenerated = Math.floor(currentTime.getTime() / 1000 - (currentTime.getTime() % 3)) * 1000;
|
|
10
10
|
const urlNoCache = getUrlNoCache(url, timeGenerated);
|
|
11
11
|
const showSkeletonMemo = showSkeleton !== undefined ? showSkeleton : checkShowSkeletonBaseUrl(urlNoCache);
|
|
12
12
|
return (React.createElement("div", { className: `image-container--big ${!showSkeletonMemo ? 'hide-skeleton' : ''}` },
|
|
13
|
-
url ? (React.createElement(Image, { preview: false, width: "100%", height: "100%", src: urlNoCache })) : null,
|
|
13
|
+
url ? (React.createElement(Image, { preview: false, width: "100%", height: "100%", src: urlNoCache, style: { objectFit: imageFit } })) : null,
|
|
14
14
|
isHideDefaultButton ? null : (React.createElement(Button, { className: "set-default-button", onClick: () => onClickDefaultButton && onClickDefaultButton(index) },
|
|
15
15
|
isDefaultThumbnail ? React.createElement(Icon, { type: "icon-ants-check", style: { fontSize: '12px' } }) : null,
|
|
16
16
|
isDefaultThumbnail ? 'Default thumbnail' : 'Set as default'))));
|
|
@@ -12,7 +12,7 @@ const ButtonSlider = React.memo(({ direction, type, onClick }) => (React.createE
|
|
|
12
12
|
: `change-preview-button change-preview-button--${direction}`, onClick: onClick },
|
|
13
13
|
React.createElement(Icon, { type: `icon-ants-angle-${direction}` }))));
|
|
14
14
|
export const ImageSlider = props => {
|
|
15
|
-
const { thumbnails, isLoading, className, skeleton, previewNavigation, slidesPerView = 3, hideThumbnailsList, hideDefaultButton, imageWidth = 330, imageHeight = 230, infinity = true, defaultThumbnail, onSelectDefault, } = props;
|
|
15
|
+
const { thumbnails, isLoading, className, skeleton, previewNavigation, slidesPerView = 3, hideThumbnailsList, hideDefaultButton, imageWidth = 330, imageHeight = 230, infinity = true, defaultThumbnail, thumbnailFit, onSelectDefault, } = props;
|
|
16
16
|
const sliderContainerRef = useRef(null);
|
|
17
17
|
const thumbnailSelectedRef = useRef(null);
|
|
18
18
|
const smallImageWidth = useMemo(() => imageWidth / slidesPerView - (10 * (slidesPerView - 1)) / slidesPerView, [imageWidth, slidesPerView]);
|
|
@@ -55,8 +55,8 @@ export const ImageSlider = props => {
|
|
|
55
55
|
}
|
|
56
56
|
}, [onSelectDefault]);
|
|
57
57
|
return (React.createElement(ImageSliderStyled, { className: className || '', "$skeleton": skeleton, "$imageWidth": imageWidth, "$smallImageWidth": smallImageWidth, "$imageHeight": imageHeight, vertical: true, gap: 10 },
|
|
58
|
-
React.createElement(Flex, { className: "thumbnail-preview-container", ref: thumbnailSelectedRef }, isLoading ? (React.createElement(Spin, { spinning: true })) : (thumbnails.map((url, index) => (React.createElement(BigImage, { key: `image-big_${url}_${index * 2}`, url: url, index: index, showSkeleton: skeleton, isDefaultThumbnail: defaultThumbnailInternal === index, isHideDefaultButton: hideDefaultButton || hideThumbnailsList || thumbnails.length <= 1, onClickDefaultButton: handleClickDefault }))))),
|
|
59
|
-
hideThumbnailsList || thumbnails.length <= 1 ? null : (React.createElement(Flex, { gap: 10, className: "thumbnail-slider-container", ref: sliderContainerRef, style: { justifyContent: thumbnails.length < slidesPerView ? 'center' : 'flex-start' } }, isLoading ? (React.createElement(Spin, { spinning: true })) : (thumbnails.map((url, index) => (React.createElement(SmallImage, { key: `${url}_${index * 2}`, showSkeleton: skeleton, isSelected: index === selectedThumbnail, url: url, index: index, onClick: handleSelectThumbnail })))))),
|
|
58
|
+
React.createElement(Flex, { className: "thumbnail-preview-container", ref: thumbnailSelectedRef }, isLoading ? (React.createElement(Spin, { spinning: true })) : (thumbnails.map((url, index) => (React.createElement(BigImage, { key: `image-big_${url}_${index * 2}`, url: url, index: index, showSkeleton: skeleton, isDefaultThumbnail: defaultThumbnailInternal === index, isHideDefaultButton: hideDefaultButton || hideThumbnailsList || thumbnails.length <= 1, imageFit: thumbnailFit, onClickDefaultButton: handleClickDefault }))))),
|
|
59
|
+
hideThumbnailsList || thumbnails.length <= 1 ? null : (React.createElement(Flex, { gap: 10, className: "thumbnail-slider-container", ref: sliderContainerRef, style: { justifyContent: thumbnails.length < slidesPerView ? 'center' : 'flex-start' } }, isLoading ? (React.createElement(Spin, { spinning: true })) : (thumbnails.map((url, index) => (React.createElement(SmallImage, { imageFit: thumbnailFit, key: `${url}_${index * 2}`, showSkeleton: skeleton, isSelected: index === selectedThumbnail, url: url, index: index, onClick: handleSelectThumbnail })))))),
|
|
60
60
|
previewNavigation && !isLoading ? (React.createElement(React.Fragment, null,
|
|
61
61
|
React.createElement(ButtonSlider, { direction: "left", type: "preview", onClick: handlePrevThumbnail }),
|
|
62
62
|
React.createElement(ButtonSlider, { direction: "right", type: "preview", onClick: handleNextThumbnail }))) : null,
|
|
@@ -2,12 +2,12 @@ import React, { useMemo } from 'react';
|
|
|
2
2
|
import { Image } from 'antd';
|
|
3
3
|
import { checkShowSkeletonBaseUrl, getUrlNoCache } from '@antscorp/antsomi-ui/es/utils';
|
|
4
4
|
export const SmallImage = React.memo(props => {
|
|
5
|
-
const { url, isSelected, index,
|
|
5
|
+
const { url, isSelected, index, imageFit, showSkeleton, onClick } = props;
|
|
6
6
|
const currentTime = useMemo(() => new Date(), []);
|
|
7
7
|
const timeGenerated = Math.floor(currentTime.getTime() / 1000 - (currentTime.getTime() % 3)) * 1000;
|
|
8
8
|
const urlNoCache = getUrlNoCache(url, timeGenerated);
|
|
9
9
|
const showSkeletonMemo = showSkeleton !== undefined ? showSkeleton : checkShowSkeletonBaseUrl(urlNoCache);
|
|
10
|
-
return (React.createElement("div", { className: `image-container--small ${isSelected ? 'image-container--selected' : ''} ${!showSkeletonMemo ? 'hide-skeleton' : ''}`, onClick: () => onClick && onClick(index) }, url ? (React.createElement(Image, { preview: false, width: "100%", height: "100%",
|
|
10
|
+
return (React.createElement("div", { className: `image-container--small ${isSelected ? 'image-container--selected' : ''} ${!showSkeletonMemo ? 'hide-skeleton' : ''}`, onClick: () => onClick && onClick(index) }, url ? (React.createElement(Image, { preview: false, width: "100%", height: "100%", style: { objectFit: imageFit },
|
|
11
11
|
// src={imageUrl}
|
|
12
12
|
// src={url}
|
|
13
13
|
src: urlNoCache })) : null));
|
|
@@ -32,7 +32,7 @@ import { getUrlNoCache, checkShowSkeletonBaseUrl } from '@antscorp/antsomi-ui/es
|
|
|
32
32
|
const cacheValue = new Date().getTime();
|
|
33
33
|
export const ThumbnailCard = memo(props => {
|
|
34
34
|
const [modal, contextHolder] = Modal.useModal();
|
|
35
|
-
const { id, name, width = THUMBNAIL_CARD_DEFAULT_WIDTH, height = THUMBNAIL_CARD_DEFAULT_HEIGHT, thumbnail, removable = true, actionAvailable = true, showSkeleton, loading = false, removeModalProps, editBtnProps, previewBtnProps, onClickWrapper } = props, restOfProps = __rest(props, ["id", "name", "width", "height", "thumbnail", "removable", "actionAvailable", "showSkeleton", "loading", "removeModalProps", "editBtnProps", "previewBtnProps", "onClickWrapper"]);
|
|
35
|
+
const { id, name, width = THUMBNAIL_CARD_DEFAULT_WIDTH, height = THUMBNAIL_CARD_DEFAULT_HEIGHT, thumbnail, thumbnailFit, removable = true, actionAvailable = true, showSkeleton, loading = false, removeModalProps, editBtnProps, previewBtnProps, onClickWrapper } = props, restOfProps = __rest(props, ["id", "name", "width", "height", "thumbnail", "thumbnailFit", "removable", "actionAvailable", "showSkeleton", "loading", "removeModalProps", "editBtnProps", "previewBtnProps", "onClickWrapper"]);
|
|
36
36
|
const _a = removeModalProps || {}, { onOk } = _a, restOfRemoveTemplateModalProps = __rest(_a, ["onOk"]);
|
|
37
37
|
const _b = editBtnProps || {}, { text: editText = 'Use template', onClick: onClickEdit } = _b, restOfEditBtnProps = __rest(_b, ["text", "onClick"]);
|
|
38
38
|
const _c = previewBtnProps || {}, { text: previewText = 'Preview', onClick: onClickPreview } = _c, restOfPreviewBtnProps = __rest(_c, ["text", "onClick"]);
|
|
@@ -60,7 +60,7 @@ export const ThumbnailCard = memo(props => {
|
|
|
60
60
|
};
|
|
61
61
|
return (React.createElement(Flex, Object.assign({ gap: 10, vertical: true }, restOfProps, { style: Object.assign({ width }, restOfProps.style) }),
|
|
62
62
|
React.createElement(ThumbnailCardWrapper, { "$showSkeleton": showSkeletonMemo, style: { height, cursor: actionAvailable ? 'default' : 'pointer' }, onClick: handleWrapperClick },
|
|
63
|
-
React.createElement("div", { className: "screen" }, thumbnail && React.createElement("img", { src: getUrlNoCache(thumbnail, cacheValue), alt: "" })),
|
|
63
|
+
React.createElement("div", { className: "screen" }, thumbnail && (React.createElement("img", { src: getUrlNoCache(thumbnail, cacheValue), alt: "", style: { objectFit: thumbnailFit } }))),
|
|
64
64
|
actionAvailable && !loading && (React.createElement(React.Fragment, null,
|
|
65
65
|
React.createElement(Flex, { className: "center-action", align: "center", gap: 10, vertical: true },
|
|
66
66
|
React.createElement(Button, Object.assign({ type: "primary", className: "animate__animated animate__fadeIn" }, restOfEditBtnProps, { onClick: e => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ModalFuncProps, ButtonProps } from 'antd';
|
|
2
|
-
import { HTMLAttributes } from 'react';
|
|
2
|
+
import React, { HTMLAttributes } from 'react';
|
|
3
3
|
export type TThumbnailCardId = string | number;
|
|
4
4
|
export type TRemoveModalProps = Omit<ModalFuncProps, 'onOk'> & {
|
|
5
5
|
onOk?: (id: TThumbnailCardId) => void;
|
|
@@ -21,5 +21,6 @@ export interface ThumbnailCardProps extends Omit<HTMLAttributes<HTMLDivElement>,
|
|
|
21
21
|
previewBtnProps?: TThumbnailButton;
|
|
22
22
|
actionAvailable?: boolean;
|
|
23
23
|
removeModalProps?: TRemoveModalProps;
|
|
24
|
+
thumbnailFit?: React.CSSProperties['objectFit'];
|
|
24
25
|
onClickWrapper?: (id: TThumbnailCardId) => void;
|
|
25
26
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Libraries
|
|
2
|
+
import React, { memo } from 'react';
|
|
3
|
+
// Components
|
|
4
|
+
import { ChildMenu } from '../common';
|
|
5
|
+
// Hooks
|
|
6
|
+
import { useLeftMenuStore } from '../../stores';
|
|
7
|
+
export const CustomMenu = memo(({ onMenuItemClick }) => {
|
|
8
|
+
const appCustomMenuChildren = useLeftMenuStore(store => store.state.customMenuChildren);
|
|
9
|
+
const customActiveAppKey = useLeftMenuStore(store => store.state.customActiveAppKey);
|
|
10
|
+
const handleMenuItemClick = (key, keyPath) => {
|
|
11
|
+
onMenuItemClick === null || onMenuItemClick === void 0 ? void 0 : onMenuItemClick(key, [...keyPath, customActiveAppKey]);
|
|
12
|
+
};
|
|
13
|
+
return React.createElement(ChildMenu, { items: appCustomMenuChildren, onMenuClick: handleMenuItemClick });
|
|
14
|
+
});
|
|
@@ -14,44 +14,60 @@ import { IconWrapper } from '../../../styled';
|
|
|
14
14
|
// Constants
|
|
15
15
|
import { ICON_SIZE } from '../../../constants';
|
|
16
16
|
// Utils
|
|
17
|
-
import { findActiveAppCodeByUrl, findLastMatchedItemByUrl } from '../../../utils';
|
|
17
|
+
import { findActiveAppCodeByUrl, findLastMatchedItemByUrl, getMenuItem } from '../../../utils';
|
|
18
18
|
import { recursiveFindParentOfActiveItem } from './utils';
|
|
19
|
-
import { random } from '@antscorp/antsomi-ui/es/utils';
|
|
20
19
|
// Hooks
|
|
21
20
|
import { useLeftMenuStore } from '../../../stores';
|
|
22
|
-
import { useNavigatePath } from '../../../hooks
|
|
21
|
+
import { useNavigatePath } from '../../../hooks';
|
|
23
22
|
export const ChildMenu = memo(props => {
|
|
24
23
|
const { items = [], parentKey, onMenuClick } = props;
|
|
25
24
|
// Stores
|
|
26
25
|
const auth = useLeftMenuStore(store => { var _a; return (_a = store.state.appConfig) === null || _a === void 0 ? void 0 : _a.auth; });
|
|
27
26
|
const activeAppCode = useLeftMenuStore(store => store.state.activeAppCode);
|
|
28
27
|
const menuItems = useLeftMenuStore(store => store.state.menuItems);
|
|
28
|
+
const customItems = useLeftMenuStore(store => store.state.customItems);
|
|
29
|
+
const isCustomized = useLeftMenuStore(store => store.state.isCustomized);
|
|
30
|
+
const customActiveCurrentKey = useLeftMenuStore(store => store.state.customActiveCurrentKey);
|
|
29
31
|
const setLeftMenuState = useLeftMenuStore(store => store.setState);
|
|
30
32
|
// States
|
|
31
33
|
const [currentActiveItem, setCurrentActiveItem] = useState('');
|
|
32
34
|
const [openKeys, setOpenKeys] = useState([]);
|
|
33
|
-
// Variables
|
|
34
|
-
const randomMenuWrapperId = random(10);
|
|
35
35
|
// Hooks
|
|
36
36
|
const { pathname, hash } = window.location;
|
|
37
37
|
const { isPushDifferentDomain, getPath, navigatePath } = useNavigatePath();
|
|
38
38
|
// Side Effects
|
|
39
39
|
useEffect(() => {
|
|
40
40
|
var _a;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const activeMenuItem = (_a = findLastMatchedItemByUrl({ url, menuItems, auth })) === null || _a === void 0 ? void 0 : _a.menu_item_code;
|
|
44
|
-
if (activeMenuItem && activeMenuItem !== currentActiveItem) {
|
|
45
|
-
setCurrentActiveItem(activeMenuItem);
|
|
41
|
+
if (isCustomized) {
|
|
42
|
+
setCurrentActiveItem(customActiveCurrentKey);
|
|
46
43
|
/** Find parent key of active menu item to open it */
|
|
47
|
-
const parentKey = recursiveFindParentOfActiveItem({
|
|
44
|
+
const parentKey = recursiveFindParentOfActiveItem({
|
|
45
|
+
activeMenuItem: customActiveCurrentKey,
|
|
46
|
+
menuItems: customItems,
|
|
47
|
+
});
|
|
48
48
|
if (parentKey) {
|
|
49
49
|
setOpenKeys(prev => [...prev, parentKey]);
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const url = `${pathname}${hash}`;
|
|
54
|
+
/** Active menu item by current url */
|
|
55
|
+
const activeMenuItem = (_a = findLastMatchedItemByUrl({ url, menuItems, auth })) === null || _a === void 0 ? void 0 : _a.menu_item_code;
|
|
56
|
+
if (activeMenuItem && activeMenuItem !== currentActiveItem) {
|
|
57
|
+
setCurrentActiveItem(activeMenuItem);
|
|
58
|
+
/** Find parent key of active menu item to open it */
|
|
59
|
+
const parentKey = recursiveFindParentOfActiveItem({
|
|
60
|
+
activeMenuItem,
|
|
61
|
+
menuItems: menuItems === null || menuItems === void 0 ? void 0 : menuItems.map(item => getMenuItem(item)),
|
|
62
|
+
});
|
|
63
|
+
if (parentKey) {
|
|
64
|
+
setOpenKeys(prev => [...prev, parentKey]);
|
|
65
|
+
}
|
|
66
|
+
/** Active App Item having code matching url */
|
|
67
|
+
const matchAppCode = findActiveAppCodeByUrl({ menuItems, url, auth });
|
|
68
|
+
if (matchAppCode && matchAppCode !== activeAppCode) {
|
|
69
|
+
setLeftMenuState({ activeAppCode: matchAppCode });
|
|
70
|
+
}
|
|
55
71
|
}
|
|
56
72
|
}
|
|
57
73
|
}, [
|
|
@@ -64,6 +80,9 @@ export const ChildMenu = memo(props => {
|
|
|
64
80
|
activeAppCode,
|
|
65
81
|
menuItems,
|
|
66
82
|
setLeftMenuState,
|
|
83
|
+
isCustomized,
|
|
84
|
+
customActiveCurrentKey,
|
|
85
|
+
customItems,
|
|
67
86
|
]);
|
|
68
87
|
// Handlers
|
|
69
88
|
const onClick = e => {
|
|
@@ -95,7 +114,7 @@ export const ChildMenu = memo(props => {
|
|
|
95
114
|
};
|
|
96
115
|
});
|
|
97
116
|
};
|
|
98
|
-
return (React.createElement(MenuWrapper,
|
|
117
|
+
return (React.createElement(MenuWrapper, null,
|
|
99
118
|
React.createElement(Menu, { selectedKeys: [currentActiveItem], defaultOpenKeys: [currentActiveItem], openKeys: uniq(openKeys), mode: "inline", items: customMenuItems({ items }), inlineIndent: 10, onOpenChange: openKeys => {
|
|
100
119
|
setOpenKeys(openKeys);
|
|
101
120
|
}, expandIcon: ({ isOpen }) => (React.createElement(Icon, { type: "icon-ants-expand-more", style: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TFeatureMenu } from '@antscorp/antsomi-ui/es/models/LeftMenu';
|
|
2
2
|
import { PayloadInfo } from '@antscorp/antsomi-ui/es/types';
|
|
3
|
+
import { TMenuItem } from '../../../types';
|
|
3
4
|
/**
|
|
4
5
|
* Finds the active menu item code based on the provided URL within the given menu items.
|
|
5
6
|
* ATTENTION: Start finding from level 2 because level 1 contains apps
|
|
@@ -21,10 +22,10 @@ export declare const findActiveMenuItemByUrl: (args: {
|
|
|
21
22
|
* Recursively finds the parent key of the active menu item within the given menu items.
|
|
22
23
|
* @param {object} args - The arguments object.
|
|
23
24
|
* @param {string} args.activeMenuItem - The key of the active menu item.
|
|
24
|
-
* @param {
|
|
25
|
+
* @param {TMenuItem[]} args.menuItems - The array of menu items to search within.
|
|
25
26
|
* @returns {string | undefined} The key of the parent menu item or undefined if not found.
|
|
26
27
|
*/
|
|
27
28
|
export declare const recursiveFindParentOfActiveItem: (args: {
|
|
28
29
|
activeMenuItem: string;
|
|
29
|
-
menuItems:
|
|
30
|
+
menuItems: TMenuItem[];
|
|
30
31
|
}) => string | undefined;
|
|
@@ -55,7 +55,7 @@ export const findActiveMenuItemByUrl = (args) => {
|
|
|
55
55
|
* Recursively finds the parent key of the active menu item within the given menu items.
|
|
56
56
|
* @param {object} args - The arguments object.
|
|
57
57
|
* @param {string} args.activeMenuItem - The key of the active menu item.
|
|
58
|
-
* @param {
|
|
58
|
+
* @param {TMenuItem[]} args.menuItems - The array of menu items to search within.
|
|
59
59
|
* @returns {string | undefined} The key of the parent menu item or undefined if not found.
|
|
60
60
|
*/
|
|
61
61
|
export const recursiveFindParentOfActiveItem = (args) => {
|
|
@@ -64,9 +64,9 @@ export const recursiveFindParentOfActiveItem = (args) => {
|
|
|
64
64
|
const { activeMenuItem, menuItems } = args;
|
|
65
65
|
let parentKey;
|
|
66
66
|
for (const item of menuItems) {
|
|
67
|
-
const isHasActiveMenuItem = !!((_a = item === null || item === void 0 ? void 0 : item.children) === null || _a === void 0 ? void 0 : _a.find(child => child.
|
|
67
|
+
const isHasActiveMenuItem = !!((_a = item === null || item === void 0 ? void 0 : item.children) === null || _a === void 0 ? void 0 : _a.find(child => child.key === activeMenuItem));
|
|
68
68
|
if (isHasActiveMenuItem) {
|
|
69
|
-
parentKey = item.
|
|
69
|
+
parentKey = item.key;
|
|
70
70
|
break;
|
|
71
71
|
}
|
|
72
72
|
const findNestedParentKey = recursiveFindParentOfActiveItem({
|
|
@@ -983,3 +983,93 @@ export const MENU_SAMPLE = [
|
|
|
983
983
|
],
|
|
984
984
|
},
|
|
985
985
|
];
|
|
986
|
+
export const CUSTOM_MENU_ITEMS = [
|
|
987
|
+
{
|
|
988
|
+
key: 'survey',
|
|
989
|
+
label: 'Survey',
|
|
990
|
+
icon: 'icon-ants-survey-v2',
|
|
991
|
+
children: [
|
|
992
|
+
{
|
|
993
|
+
key: 'ANALYSIS',
|
|
994
|
+
label: 'Analysis',
|
|
995
|
+
icon: null,
|
|
996
|
+
children: [
|
|
997
|
+
{
|
|
998
|
+
key: 'SQL_WORKSPACE',
|
|
999
|
+
label: 'SQL Workspace',
|
|
1000
|
+
icon: null,
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
key: 'EXPLORE',
|
|
1004
|
+
label: 'Explore',
|
|
1005
|
+
icon: null,
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
key: 'SCHEDULE_QUERY',
|
|
1009
|
+
label: 'Schedule Query',
|
|
1010
|
+
icon: null,
|
|
1011
|
+
},
|
|
1012
|
+
],
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
label: 'Reports',
|
|
1016
|
+
icon: null,
|
|
1017
|
+
key: 'REPORT',
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
key: 'DATA_SOURCE',
|
|
1021
|
+
label: 'Data Sources',
|
|
1022
|
+
icon: null,
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
key: 'GALLERY',
|
|
1026
|
+
label: 'Gallery',
|
|
1027
|
+
icon: null,
|
|
1028
|
+
},
|
|
1029
|
+
],
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
key: 'data',
|
|
1033
|
+
label: 'Data',
|
|
1034
|
+
icon: 'icon-ants-survey-data',
|
|
1035
|
+
children: [
|
|
1036
|
+
{
|
|
1037
|
+
key: 'COUPON',
|
|
1038
|
+
label: 'Coupons',
|
|
1039
|
+
icon: 'icon-ants-coupons',
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
label: 'Short Links',
|
|
1043
|
+
icon: 'icon-ants-short-link',
|
|
1044
|
+
key: 'SHORT_LINK',
|
|
1045
|
+
},
|
|
1046
|
+
],
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
key: 'report',
|
|
1050
|
+
label: 'Report',
|
|
1051
|
+
icon: 'icon-ants-overview',
|
|
1052
|
+
children: [
|
|
1053
|
+
{
|
|
1054
|
+
label: 'Overview',
|
|
1055
|
+
icon: 'icon-ants-overview',
|
|
1056
|
+
key: 'JOURNEY_OVERVIEW',
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
key: 'ALL_CHANNEL',
|
|
1060
|
+
label: 'All Channels',
|
|
1061
|
+
icon: 'icon-ants-window',
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
key: 'CAMPAIGN',
|
|
1065
|
+
label: 'Campaigns',
|
|
1066
|
+
icon: 'icon-ants-campaign',
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
key: 'ORCHESTRATION',
|
|
1070
|
+
label: 'Orchestration',
|
|
1071
|
+
icon: 'icon-ants-orchestration',
|
|
1072
|
+
},
|
|
1073
|
+
],
|
|
1074
|
+
},
|
|
1075
|
+
];
|
|
@@ -7,8 +7,11 @@ 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
|
+
customActiveAppKey: string;
|
|
10
12
|
onToggleChildMenu: () => void;
|
|
11
13
|
onMouseEnter: (key: string) => void;
|
|
12
14
|
onMouseLeave: () => void;
|
|
15
|
+
onHoverMenuBar: () => void;
|
|
13
16
|
};
|
|
14
17
|
export {};
|
|
@@ -4,7 +4,7 @@ import { isArray, sortBy } from 'lodash';
|
|
|
4
4
|
// Queries
|
|
5
5
|
import { useGetDashboard, useGetDestinationChannel, useGetListMenu, useGetListMenuPermission, } from '@antscorp/antsomi-ui/es/queries/LeftMenu';
|
|
6
6
|
// Utils
|
|
7
|
-
import { findActiveAppCodeByUrl, findLastMatchedItemByUrl, findPathOfActiveItem, flattenMenuArray, getMappingAppChildren, recursivePermissionMenu, } from '../utils';
|
|
7
|
+
import { findActiveAppCodeByChild, findActiveAppCodeByUrl, findLastMatchedItemByUrl, findPathOfActiveItem, flattenMenuArray, getMappingAppChildren, recursivePermissionMenu, } from '../utils';
|
|
8
8
|
// Store
|
|
9
9
|
import { useLeftMenuStore } from '../stores';
|
|
10
10
|
import { POST_MESSAGE_TYPES } from '@antscorp/antsomi-ui/es/constants/postMessage';
|
|
@@ -14,12 +14,13 @@ const initialState = {
|
|
|
14
14
|
};
|
|
15
15
|
export const useLeftMenu = (props) => {
|
|
16
16
|
// Props
|
|
17
|
-
const { objectType = 'OVERVIEW', objectId = 1, isGrouped = true, appConfig, onActiveMenuCodeChange, } = props;
|
|
17
|
+
const { objectType = 'OVERVIEW', objectId = 1, isGrouped = true, appConfig, customization, onActiveMenuCodeChange, } = props;
|
|
18
|
+
const { isExpandable = true, isCustomized = false, items, activeKey } = customization || {};
|
|
18
19
|
// Hooks
|
|
19
20
|
const { pathname, hash } = window.location;
|
|
20
|
-
console.log({ pathname, hash, locationWindow: window.location });
|
|
21
21
|
// Stores
|
|
22
22
|
const activeAppCode = useLeftMenuStore(store => store.state.activeAppCode);
|
|
23
|
+
const customActiveAppKey = useLeftMenuStore(store => store.state.customActiveAppKey);
|
|
23
24
|
const setLeftMenuState = useLeftMenuStore(store => store.setState);
|
|
24
25
|
// Destructuring variables
|
|
25
26
|
const { auth, languageCode } = appConfig || {};
|
|
@@ -112,37 +113,71 @@ export const useLeftMenu = (props) => {
|
|
|
112
113
|
// Side Effects
|
|
113
114
|
// Receive Post Message
|
|
114
115
|
useEffect(() => {
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
if (!isCustomized) {
|
|
117
|
+
window.addEventListener('message', receivePostMessage);
|
|
118
|
+
return () => window.removeEventListener('message', receivePostMessage);
|
|
119
|
+
}
|
|
117
120
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
118
121
|
}, []);
|
|
119
122
|
useEffect(() => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
setLeftMenuState({ appConfig, isCustomized });
|
|
124
|
+
}, [appConfig, isCustomized, setLeftMenuState]);
|
|
125
|
+
/**
|
|
126
|
+
* Active Custom App Key when active key is changed
|
|
127
|
+
*/
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (activeKey && items)
|
|
130
|
+
setLeftMenuState({
|
|
131
|
+
customActiveAppKey: findActiveAppCodeByChild({
|
|
132
|
+
activeCurrentKey: activeKey,
|
|
133
|
+
menuItems: items,
|
|
134
|
+
}) || '',
|
|
135
|
+
customActiveCurrentKey: activeKey,
|
|
136
|
+
});
|
|
137
|
+
}, [activeKey, appConfig, isCustomized, items, setLeftMenuState]);
|
|
123
138
|
/**
|
|
124
139
|
* Change list menu children when hovering or activating items, giving priority to hovering items
|
|
125
140
|
*/
|
|
126
141
|
useEffect(() => {
|
|
127
|
-
var _a;
|
|
128
|
-
|
|
129
|
-
|
|
142
|
+
var _a, _b;
|
|
143
|
+
if (isCustomized) {
|
|
144
|
+
const appActiveKey = state.hoverItem ? state.hoverItem : customActiveAppKey;
|
|
130
145
|
setLeftMenuState({
|
|
131
|
-
|
|
132
|
-
|
|
146
|
+
customItems: items,
|
|
147
|
+
customMenuChildren: ((_a = items === null || items === void 0 ? void 0 : items.find(item => item.key === appActiveKey)) === null || _a === void 0 ? void 0 : _a.children) || [],
|
|
133
148
|
});
|
|
134
149
|
}
|
|
135
|
-
|
|
150
|
+
else {
|
|
151
|
+
const appCode = state.hoverItem ? state.hoverItem : activeAppCode;
|
|
152
|
+
if (isArray(mappingChildrenMenu)) {
|
|
153
|
+
setLeftMenuState({
|
|
154
|
+
menuItems: mappingChildrenMenu,
|
|
155
|
+
appMenuChildren: ((_b = mappingChildrenMenu === null || mappingChildrenMenu === void 0 ? void 0 : mappingChildrenMenu.find(item => item.menu_item_code === appCode)) === null || _b === void 0 ? void 0 : _b.children) || [],
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}, [
|
|
160
|
+
isCustomized,
|
|
161
|
+
activeAppCode,
|
|
162
|
+
mappingChildrenMenu,
|
|
163
|
+
state.hoverItem,
|
|
164
|
+
setLeftMenuState,
|
|
165
|
+
items,
|
|
166
|
+
customActiveAppKey,
|
|
167
|
+
]);
|
|
136
168
|
/**
|
|
137
169
|
* Active App Item having code matching url
|
|
138
170
|
*/
|
|
139
171
|
useEffect(() => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
172
|
+
if (!isCustomized) {
|
|
173
|
+
const url = `${pathname}${hash}`;
|
|
174
|
+
const matchAppCode = findActiveAppCodeByUrl({ url, menuItems: mappingChildrenMenu, auth });
|
|
175
|
+
if (matchAppCode && matchAppCode !== activeAppCode) {
|
|
176
|
+
setLeftMenuState({ activeAppCode: matchAppCode });
|
|
177
|
+
}
|
|
144
178
|
}
|
|
145
179
|
}, [
|
|
180
|
+
isCustomized,
|
|
146
181
|
activeAppCode,
|
|
147
182
|
appConfig === null || appConfig === void 0 ? void 0 : appConfig.auth,
|
|
148
183
|
auth,
|
|
@@ -157,34 +192,47 @@ export const useLeftMenu = (props) => {
|
|
|
157
192
|
*/
|
|
158
193
|
useEffect(() => {
|
|
159
194
|
var _a;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
auth,
|
|
165
|
-
})) === null || _a === void 0 ? void 0 : _a.menu_item_code;
|
|
166
|
-
const activeItemPath = matchedCode
|
|
167
|
-
? findPathOfActiveItem({
|
|
168
|
-
activeMenuItem: matchedCode,
|
|
195
|
+
if (!isCustomized) {
|
|
196
|
+
const url = `${pathname}${hash}`;
|
|
197
|
+
const matchedCode = (_a = findLastMatchedItemByUrl({
|
|
198
|
+
url,
|
|
169
199
|
menuItems: mappingChildrenMenu,
|
|
170
|
-
|
|
171
|
-
:
|
|
172
|
-
|
|
173
|
-
|
|
200
|
+
auth,
|
|
201
|
+
})) === null || _a === void 0 ? void 0 : _a.menu_item_code;
|
|
202
|
+
const activeItemPath = matchedCode
|
|
203
|
+
? findPathOfActiveItem({
|
|
204
|
+
activeMenuItem: matchedCode,
|
|
205
|
+
menuItems: mappingChildrenMenu,
|
|
206
|
+
})
|
|
207
|
+
: [];
|
|
208
|
+
onActiveMenuCodeChange === null || onActiveMenuCodeChange === void 0 ? void 0 : onActiveMenuCodeChange(activeItemPath, flattenMenuPermission);
|
|
209
|
+
}
|
|
210
|
+
}, [
|
|
211
|
+
isCustomized,
|
|
212
|
+
auth,
|
|
213
|
+
flattenMenuPermission,
|
|
214
|
+
hash,
|
|
215
|
+
mappingChildrenMenu,
|
|
216
|
+
onActiveMenuCodeChange,
|
|
217
|
+
pathname,
|
|
218
|
+
]);
|
|
174
219
|
/* Callbacks */
|
|
175
220
|
const onToggleChildMenu = useCallback(() => {
|
|
176
221
|
setState(prev => (Object.assign(Object.assign({}, prev), { isExpandMenu: !prev.isExpandMenu })));
|
|
177
222
|
}, []);
|
|
178
223
|
const onMouseEnter = useCallback((key) => {
|
|
179
|
-
if (!state.isExpandMenu) {
|
|
224
|
+
if (!state.isExpandMenu || !isExpandable) {
|
|
180
225
|
setState(prev => (Object.assign(Object.assign({}, prev), { hoverItem: key })));
|
|
181
226
|
}
|
|
182
|
-
}, [state.isExpandMenu]);
|
|
227
|
+
}, [isExpandable, state.isExpandMenu]);
|
|
183
228
|
const onMouseLeave = useCallback(() => {
|
|
184
|
-
if (!state.isExpandMenu) {
|
|
229
|
+
if (!state.isExpandMenu || !isExpandable) {
|
|
185
230
|
setState(prev => (Object.assign(Object.assign({}, prev), { hoverItem: '' })));
|
|
186
231
|
}
|
|
187
|
-
}, [state.isExpandMenu]);
|
|
232
|
+
}, [isExpandable, state.isExpandMenu]);
|
|
233
|
+
const onHoverMenuBar = () => {
|
|
234
|
+
onMouseEnter(isCustomized ? customActiveAppKey : activeAppCode);
|
|
235
|
+
};
|
|
188
236
|
return {
|
|
189
237
|
/* State */
|
|
190
238
|
state,
|
|
@@ -192,9 +240,12 @@ export const useLeftMenu = (props) => {
|
|
|
192
240
|
activeAppCode,
|
|
193
241
|
/* Data Queries */
|
|
194
242
|
permissionMenu,
|
|
243
|
+
/** Variables */
|
|
244
|
+
customActiveAppKey,
|
|
195
245
|
/* Callbacks */
|
|
196
246
|
onToggleChildMenu,
|
|
197
247
|
onMouseEnter,
|
|
198
248
|
onMouseLeave,
|
|
249
|
+
onHoverMenuBar,
|
|
199
250
|
};
|
|
200
251
|
};
|
|
@@ -37,13 +37,11 @@ export const useNavigatePath = () => {
|
|
|
37
37
|
const customPath = ((_a = path === null || path === void 0 ? void 0 : path.split('#')) === null || _a === void 0 ? void 0 : _a[1]) || '';
|
|
38
38
|
return getGeneratePath(customPath, auth);
|
|
39
39
|
}
|
|
40
|
-
return `${
|
|
41
|
-
// return `${getGeneratePath(path ?? '', auth)}${searchParams}`;
|
|
40
|
+
return getGeneratePath(`${path !== null && path !== void 0 ? path : ''}${searchParams}`, auth);
|
|
42
41
|
}, [auth, searchParams]);
|
|
43
42
|
const navigatePath = useCallback((domain, path) => {
|
|
44
43
|
const newDomain = isNil(domain) || env === ENV.DEV ? '' : domain;
|
|
45
|
-
window.location.assign(
|
|
46
|
-
// window.location.assign(`${getGeneratePath(`${newDomain}${path}`, auth)}${searchParams}`);
|
|
44
|
+
window.location.assign(getGeneratePath(`${newDomain}${path}${searchParams}`, auth));
|
|
47
45
|
}, [auth, env, searchParams]);
|
|
48
46
|
return { isPushDifferentDomain, getPath, navigatePath };
|
|
49
47
|
};
|
|
@@ -10,9 +10,13 @@ export interface LeftMenuProps {
|
|
|
10
10
|
isGrouped?: boolean;
|
|
11
11
|
style?: React.CSSProperties;
|
|
12
12
|
className?: string;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
customization?: {
|
|
14
|
+
isCustomized?: boolean;
|
|
15
|
+
isExpandable?: boolean;
|
|
16
|
+
items?: TMenuItem[];
|
|
17
|
+
activeKey?: string;
|
|
18
|
+
onMenuItemClick?: (key: string, keyPath: string[]) => void;
|
|
19
|
+
};
|
|
16
20
|
onActiveMenuCodeChange?: (activeItemPath: TFeatureMenu[], flattenPermissionList?: FeatureMenuPermission[]) => void;
|
|
17
21
|
}
|
|
18
22
|
export declare const LeftMenu: React.FC<LeftMenuProps>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Libraries
|
|
2
|
-
import React, { memo, useMemo } from 'react';
|
|
2
|
+
import React, { memo, useCallback, useMemo } from 'react';
|
|
3
3
|
import Icon from '@antscorp/icons';
|
|
4
4
|
import { Typography } from 'antd';
|
|
5
5
|
import classNames from 'classnames';
|
|
@@ -8,17 +8,16 @@ import { Link } from 'react-router-dom';
|
|
|
8
8
|
// Assets
|
|
9
9
|
import SubLogoAntsomi from '@antscorp/antsomi-ui/es/assets/images/logo/sub-logo-antsomi.png';
|
|
10
10
|
// Styled
|
|
11
|
-
import { ChildMenuWrapper, ExpandWrapper, FeatureMenu, FeatureMenuItem, LeftMenuNav, LeftMenuNavWrapper, PopoverWrapper, NavLogoWrapper, FeatureMenuWrapper, } from './styled';
|
|
11
|
+
import { ChildMenuWrapper, ExpandWrapper, FeatureMenu, FeatureMenuItem, LeftMenuNav, LeftMenuNavWrapper, PopoverWrapper, NavLogoWrapper, FeatureMenuWrapper, IconWrapper, } from './styled';
|
|
12
12
|
// Constants
|
|
13
|
-
import { APP_KEYS
|
|
13
|
+
import { APP_KEYS } from './constants';
|
|
14
14
|
// Components
|
|
15
|
-
import { ProfilesMenu, ContentMenu, DataMenu, MarketingMenu, HomeMenu, InsightsMenu, SettingsMenu, TemplatesMenu, } from './components';
|
|
15
|
+
import { ProfilesMenu, ContentMenu, DataMenu, MarketingMenu, HomeMenu, InsightsMenu, SettingsMenu, TemplatesMenu, CustomMenu, } from './components';
|
|
16
16
|
// Hooks
|
|
17
|
-
import { useLeftMenu } from './hooks';
|
|
18
|
-
import { useNavigatePath } from './hooks/useNavigatePath';
|
|
17
|
+
import { useLeftMenu, useNavigatePath } from './hooks';
|
|
19
18
|
export const LeftMenu = memo(props => {
|
|
20
|
-
|
|
21
|
-
const {
|
|
19
|
+
const { style, className, customization } = props;
|
|
20
|
+
const { isExpandable = true, isCustomized = false, items = [], onMenuItemClick, } = customization || {};
|
|
22
21
|
// Hooks
|
|
23
22
|
const {
|
|
24
23
|
/* State */
|
|
@@ -27,12 +26,16 @@ export const LeftMenu = memo(props => {
|
|
|
27
26
|
activeAppCode,
|
|
28
27
|
/* Data Queries */
|
|
29
28
|
permissionMenu,
|
|
29
|
+
/** Variables */
|
|
30
|
+
customActiveAppKey,
|
|
30
31
|
/* Callbacks */
|
|
31
|
-
onToggleChildMenu, onMouseEnter, onMouseLeave, } = useLeftMenu(props);
|
|
32
|
+
onToggleChildMenu, onMouseEnter, onMouseLeave, onHoverMenuBar, } = useLeftMenu(props);
|
|
32
33
|
const { isPushDifferentDomain, getPath, navigatePath } = useNavigatePath();
|
|
33
34
|
// Memo
|
|
34
35
|
const childMenu = useMemo(() => {
|
|
35
36
|
const selectedFeatureKey = state.hoverItem ? state.hoverItem : activeAppCode;
|
|
37
|
+
if (isCustomized)
|
|
38
|
+
return React.createElement(CustomMenu, { onMenuItemClick: onMenuItemClick });
|
|
36
39
|
switch (selectedFeatureKey) {
|
|
37
40
|
case APP_KEYS.HOME: {
|
|
38
41
|
return React.createElement(HomeMenu, null);
|
|
@@ -61,38 +64,54 @@ export const LeftMenu = memo(props => {
|
|
|
61
64
|
default:
|
|
62
65
|
return null;
|
|
63
66
|
}
|
|
64
|
-
}, [activeAppCode, state.hoverItem]);
|
|
67
|
+
}, [activeAppCode, isCustomized, onMenuItemClick, state.hoverItem]);
|
|
65
68
|
// Render components
|
|
66
|
-
const renderFeatureMenuItems = (item) => {
|
|
69
|
+
const renderFeatureMenuItems = useCallback((item) => {
|
|
67
70
|
const { menu_item_name, menu_item, icon_name, menu_item_code, menu_item_path, menu_item_domain, } = item;
|
|
68
71
|
const isActive = activeAppCode === menu_item_code;
|
|
69
72
|
const isHover = state.hoverItem === menu_item_code;
|
|
70
73
|
const labelComponent = () => (React.createElement("li", { role: "menuitem", className: classNames({ isActive, isHover }) },
|
|
71
|
-
React.createElement(
|
|
74
|
+
React.createElement(IconWrapper, null, isNil(icon_name) ? null : React.createElement(Icon, { type: icon_name })),
|
|
72
75
|
React.createElement(Typography.Text, null, menu_item_name),
|
|
73
76
|
React.createElement("div", { className: "popup-triangle" })));
|
|
74
77
|
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())));
|
|
78
|
+
}, [activeAppCode, getPath, isPushDifferentDomain, navigatePath, onMouseEnter, state.hoverItem]);
|
|
79
|
+
const renderCustomizedMenuItems = useCallback((items) => items === null || items === void 0 ? void 0 : items.map(item => {
|
|
80
|
+
const { key, icon, label } = item;
|
|
81
|
+
const isActive = key === customActiveAppKey;
|
|
82
|
+
const isHover = key === state.hoverItem;
|
|
83
|
+
return (React.createElement(FeatureMenuItem, { key: key, onClick: () => onMenuItemClick === null || onMenuItemClick === void 0 ? void 0 : onMenuItemClick(key, [key]), onMouseEnter: () => onMouseEnter(key) },
|
|
84
|
+
React.createElement("li", { role: "menuitem", className: classNames({ isActive, isHover }) },
|
|
85
|
+
React.createElement(IconWrapper, null, isNil(icon) ? null : React.createElement(Icon, { type: icon })),
|
|
86
|
+
React.createElement(Typography.Text, null, label),
|
|
87
|
+
isExpandable && React.createElement("div", { className: "popup-triangle" }))));
|
|
88
|
+
}), [customActiveAppKey, state.hoverItem, isExpandable, onMenuItemClick, onMouseEnter]);
|
|
89
|
+
const renderAppMenuItems = useCallback(() => {
|
|
90
|
+
var _a;
|
|
91
|
+
return isCustomized
|
|
92
|
+
? renderCustomizedMenuItems(items)
|
|
93
|
+
: (_a = permissionMenu === null || permissionMenu === void 0 ? void 0 : permissionMenu.filter(item => item.menu_item_code !== APP_KEYS.SETTINGS)) === null || _a === void 0 ? void 0 : _a.map(item => renderFeatureMenuItems(item));
|
|
94
|
+
}, [isCustomized, items, permissionMenu, renderCustomizedMenuItems, renderFeatureMenuItems]);
|
|
95
|
+
const renderSettings = () => {
|
|
96
|
+
if (!isCustomized) {
|
|
97
|
+
const settingApp = permissionMenu === null || permissionMenu === void 0 ? void 0 : permissionMenu.find(item => item.menu_item_code === APP_KEYS.SETTINGS);
|
|
98
|
+
if (settingApp)
|
|
99
|
+
return renderFeatureMenuItems(settingApp);
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
75
102
|
};
|
|
76
|
-
// const renderCustomizedMenuItems = (items: TMenuItem) => {
|
|
77
|
-
// return items?.map(item => {
|
|
78
|
-
// return <FeatureMenuItem key={menu_item} onMouseEnter={() => onMouseEnter(menu_item_code)} />;
|
|
79
|
-
// });
|
|
80
|
-
// };
|
|
81
103
|
return (React.createElement(LeftMenuNavWrapper, { style: style, className: className },
|
|
82
104
|
React.createElement(LeftMenuNav, null,
|
|
83
105
|
React.createElement(FeatureMenuWrapper, { isExpandMenu: state.isExpandMenu, vertical: true },
|
|
84
|
-
React.createElement(NavLogoWrapper, { align: "center", justify: "center", onMouseEnter:
|
|
106
|
+
React.createElement(NavLogoWrapper, { align: "center", justify: "center", onMouseEnter: onHoverMenuBar },
|
|
85
107
|
React.createElement("div", { className: "image-wrapper" },
|
|
86
108
|
React.createElement("img", { src: SubLogoAntsomi, alt: "Antsomi sub logo" }))),
|
|
87
109
|
React.createElement(FeatureMenu, { role: "menu", className: "antsomi-scroll-box", onMouseLeave: onMouseLeave },
|
|
88
|
-
React.createElement("div", { className: "menu-content scroll-content" }, (
|
|
89
|
-
React.createElement("div", { className: "nav-blank", onMouseEnter:
|
|
110
|
+
React.createElement("div", { className: "menu-content scroll-content" }, renderAppMenuItems()),
|
|
111
|
+
React.createElement("div", { className: "nav-blank", onMouseEnter: onHoverMenuBar }),
|
|
90
112
|
React.createElement(PopoverWrapper, { className: "antsomi-scroll-box antsomi-child-menu-popover", onMouseLeave: onMouseLeave },
|
|
91
113
|
React.createElement("div", { className: "scroll-content" }, childMenu))),
|
|
92
|
-
React.createElement("div", { style: { flexShrink: 0 } }, (
|
|
93
|
-
const settingFeature = permissionMenu === null || permissionMenu === void 0 ? void 0 : permissionMenu.find(item => item.menu_item_code === APP_KEYS.SETTINGS);
|
|
94
|
-
return settingFeature ? renderFeatureMenuItems(settingFeature) : null;
|
|
95
|
-
})())),
|
|
114
|
+
React.createElement("div", { style: { flexShrink: 0 } }, renderSettings())),
|
|
96
115
|
isExpandable && (React.createElement(ExpandWrapper, { onMouseEnter: onMouseLeave },
|
|
97
116
|
React.createElement(Icon, { type: "icon-ants-expand-more", style: {
|
|
98
117
|
cursor: 'pointer',
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { TFeatureMenu } from '@antscorp/antsomi-ui/es/models/LeftMenu';
|
|
2
2
|
import { AppConfigProviderProps } from '@antscorp/antsomi-ui/es/providers';
|
|
3
|
+
import { TMenuItem } from '../types';
|
|
3
4
|
export interface LeftMenuState {
|
|
4
5
|
activeAppCode: string;
|
|
6
|
+
customActiveAppKey: string;
|
|
7
|
+
customActiveCurrentKey: string;
|
|
5
8
|
menuItems: TFeatureMenu[];
|
|
9
|
+
customItems: TMenuItem[];
|
|
10
|
+
customMenuChildren: TMenuItem[];
|
|
6
11
|
appMenuChildren: TFeatureMenu[];
|
|
7
12
|
appConfig?: AppConfigProviderProps;
|
|
13
|
+
isCustomized?: boolean;
|
|
8
14
|
}
|
|
9
15
|
interface LeftMenuStore {
|
|
10
16
|
state: LeftMenuState;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// Libraries
|
|
2
2
|
import { create } from 'zustand';
|
|
3
|
-
const initialState = {
|
|
3
|
+
const initialState = {
|
|
4
|
+
activeAppCode: '',
|
|
5
|
+
customActiveAppKey: '',
|
|
6
|
+
customActiveCurrentKey: '',
|
|
7
|
+
menuItems: [],
|
|
8
|
+
appMenuChildren: [],
|
|
9
|
+
customItems: [],
|
|
10
|
+
customMenuChildren: [],
|
|
11
|
+
isCustomized: false,
|
|
12
|
+
};
|
|
4
13
|
export const useLeftMenuStore = create(set => ({
|
|
5
14
|
state: initialState,
|
|
6
15
|
setState: newState => set(store => ({ state: Object.assign(Object.assign({}, store.state), newState) })),
|
|
@@ -129,14 +129,6 @@ export const FeatureMenuItem = styled.div `
|
|
|
129
129
|
display: none !important;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
.icon-wrapper {
|
|
133
|
-
height: 30px;
|
|
134
|
-
width: 30px;
|
|
135
|
-
display: flex;
|
|
136
|
-
align-items: center;
|
|
137
|
-
justify-content: center;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
132
|
span {
|
|
141
133
|
font-size: 11px !important;
|
|
142
134
|
font-weight: 500;
|
|
@@ -198,6 +190,6 @@ export const IconWrapper = styled.div `
|
|
|
198
190
|
align-items: center;
|
|
199
191
|
|
|
200
192
|
i {
|
|
201
|
-
font-size: ${ICON_SIZE};
|
|
193
|
+
font-size: ${ICON_SIZE}px;
|
|
202
194
|
}
|
|
203
195
|
`;
|
|
@@ -39,6 +39,25 @@ export declare const getComparePath: (path: string) => string;
|
|
|
39
39
|
* @returns {TFeatureMenu} The initial feature menu item object.
|
|
40
40
|
*/
|
|
41
41
|
export declare const getInitialFeatureMenuItem: (featureMenuItem: Partial<TFeatureMenu>) => TFeatureMenu;
|
|
42
|
+
export declare const recursiveGetInitialFeatureMenuItem: (featureMenuItem: Partial<TFeatureMenu>) => {
|
|
43
|
+
menu_item: string | number;
|
|
44
|
+
network_id: number;
|
|
45
|
+
menu_item_name: string;
|
|
46
|
+
level_position: string | number;
|
|
47
|
+
icon_name: string | null;
|
|
48
|
+
menu_item_path: string | null;
|
|
49
|
+
menu_item_code: string;
|
|
50
|
+
permission_code: string | null;
|
|
51
|
+
menu_item_type: string | number;
|
|
52
|
+
menu_item_parent: string | number;
|
|
53
|
+
render_option: string | null;
|
|
54
|
+
menu_item_domain: string | null;
|
|
55
|
+
total_row: number;
|
|
56
|
+
ctime: string | null;
|
|
57
|
+
utime: string | null;
|
|
58
|
+
logo_url?: string | undefined;
|
|
59
|
+
children?: TFeatureMenu[] | undefined;
|
|
60
|
+
};
|
|
42
61
|
/** Map children to each App Item */
|
|
43
62
|
export declare const getMappingAppChildren: (args: {
|
|
44
63
|
menuList: TFeatureMenu[];
|
|
@@ -68,3 +87,15 @@ export declare const findPathOfActiveItem: (args: {
|
|
|
68
87
|
activeMenuItem: string;
|
|
69
88
|
menuItems: TFeatureMenu[];
|
|
70
89
|
}) => TFeatureMenu[];
|
|
90
|
+
/**
|
|
91
|
+
* Finds the app code of the menu item or its parent based on the provided active key.
|
|
92
|
+
*
|
|
93
|
+
* @param {Object} args - The arguments object.
|
|
94
|
+
* @param {string} args.activeCurrentKey - The key of the currently active menu item.
|
|
95
|
+
* @param {TMenuItem[]} args.menuItems - The array of menu items to search through.
|
|
96
|
+
* @returns {string | undefined} - The app code of the matching menu item or its parent, or undefined if not found.
|
|
97
|
+
*/
|
|
98
|
+
export declare const findActiveAppCodeByChild: (args: {
|
|
99
|
+
activeCurrentKey: string;
|
|
100
|
+
menuItems: TMenuItem[];
|
|
101
|
+
}) => string | undefined;
|
|
@@ -105,6 +105,7 @@ export const getComparePath = (path) => {
|
|
|
105
105
|
* @returns {TFeatureMenu} The initial feature menu item object.
|
|
106
106
|
*/
|
|
107
107
|
export const getInitialFeatureMenuItem = (featureMenuItem) => (Object.assign({ menu_item: '', network_id: -1, menu_item_name: '', level_position: 0, icon_name: null, menu_item_path: null, menu_item_code: '', permission_code: null, menu_item_type: 3, menu_item_parent: 0, render_option: null, menu_item_domain: null, total_row: 0, ctime: null, utime: null }, featureMenuItem));
|
|
108
|
+
export const recursiveGetInitialFeatureMenuItem = (featureMenuItem) => (Object.assign({ menu_item: '', network_id: -1, menu_item_name: '', level_position: 0, icon_name: null, menu_item_path: null, menu_item_code: '', permission_code: null, menu_item_type: 3, menu_item_parent: 0, render_option: null, menu_item_domain: null, total_row: 0, ctime: null, utime: null }, featureMenuItem));
|
|
108
109
|
/** Map children to each App Item */
|
|
109
110
|
export const getMappingAppChildren = (args) => {
|
|
110
111
|
const { menuList, dashboardData, auth, destinationChannelEntries } = args;
|
|
@@ -270,3 +271,52 @@ export const findPathOfActiveItem = (args) => {
|
|
|
270
271
|
return [];
|
|
271
272
|
}
|
|
272
273
|
};
|
|
274
|
+
/**
|
|
275
|
+
* Finds the app code of the menu item or its parent based on the provided active key.
|
|
276
|
+
*
|
|
277
|
+
* @param {Object} args - The arguments object.
|
|
278
|
+
* @param {string} args.activeCurrentKey - The key of the currently active menu item.
|
|
279
|
+
* @param {TMenuItem[]} args.menuItems - The array of menu items to search through.
|
|
280
|
+
* @returns {string | undefined} - The app code of the matching menu item or its parent, or undefined if not found.
|
|
281
|
+
*/
|
|
282
|
+
export const findActiveAppCodeByChild = (args) => {
|
|
283
|
+
try {
|
|
284
|
+
const { activeCurrentKey, menuItems } = args;
|
|
285
|
+
let matchAppCode;
|
|
286
|
+
const recursiveCheckHasActiveChild = (items) => {
|
|
287
|
+
let matchAppCode = false;
|
|
288
|
+
for (const item of items) {
|
|
289
|
+
if (item.key === activeCurrentKey) {
|
|
290
|
+
matchAppCode = true;
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
if ((item === null || item === void 0 ? void 0 : item.children) && item.children.length) {
|
|
294
|
+
matchAppCode = recursiveCheckHasActiveChild(item.children);
|
|
295
|
+
if (matchAppCode) {
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return matchAppCode;
|
|
301
|
+
};
|
|
302
|
+
for (const menuItem of menuItems) {
|
|
303
|
+
if (menuItem.key === activeCurrentKey) {
|
|
304
|
+
matchAppCode = activeCurrentKey;
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
const hasActiveChild = recursiveCheckHasActiveChild((menuItem === null || menuItem === void 0 ? void 0 : menuItem.children) || []);
|
|
308
|
+
if (hasActiveChild) {
|
|
309
|
+
matchAppCode = menuItem.key;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return matchAppCode;
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
handleError(error, {
|
|
317
|
+
path: PATH,
|
|
318
|
+
name: findActiveAppCodeByChild.name,
|
|
319
|
+
args,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
};
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { PayloadInfo } from '../../..';
|
|
3
3
|
import { envType } from '@antscorp/antsomi-ui/es/types/config';
|
|
4
|
-
export interface
|
|
4
|
+
export interface AppConfigProps {
|
|
5
5
|
env?: envType;
|
|
6
6
|
auth?: Omit<PayloadInfo, 'url'>;
|
|
7
7
|
appCode?: string;
|
|
8
8
|
languageCode?: string;
|
|
9
9
|
urlLogout?: string;
|
|
10
|
+
setAppConfig: React.Dispatch<React.SetStateAction<AppConfigProviderProps>>;
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
+
export interface AppConfigProviderProps extends Omit<AppConfigProps, 'setAppConfig'> {
|
|
13
|
+
}
|
|
14
|
+
declare const AppConfigContext: import("use-context-selector").Context<AppConfigProps>;
|
|
12
15
|
declare const AppConfigProvider: React.FC<React.PropsWithChildren<{
|
|
13
16
|
value?: AppConfigProviderProps;
|
|
14
17
|
}>>;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// Libraries
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import React, { useMemo, useState } from 'react';
|
|
3
3
|
import { createContext } from 'use-context-selector';
|
|
4
|
-
|
|
4
|
+
import { merge } from 'lodash';
|
|
5
|
+
const initialContext = { setAppConfig: () => { } };
|
|
5
6
|
const AppConfigContext = createContext(initialContext);
|
|
6
7
|
const AppConfigProvider = props => {
|
|
7
8
|
const { value = initialContext, children } = props;
|
|
8
|
-
|
|
9
|
+
const [appConfig, setAppConfig] = useState(value);
|
|
10
|
+
const mergedValue = useMemo(() => (Object.assign(Object.assign({}, merge(value, appConfig)), { setAppConfig })), [appConfig, value]);
|
|
11
|
+
return React.createElement(AppConfigContext.Provider, { value: mergedValue }, children);
|
|
9
12
|
};
|
|
10
13
|
export { AppConfigContext, AppConfigProvider };
|