@antscorp/antsomi-ui 1.3.5-beta.544 → 1.3.5-beta.545

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.
@@ -0,0 +1,11 @@
1
+ import React, { ReactNode } from 'react';
2
+ interface AccessDeniedProps {
3
+ image?: ReactNode;
4
+ title?: ReactNode;
5
+ subTitle?: ReactNode;
6
+ description?: ReactNode;
7
+ onClickRequestAccess?: () => void;
8
+ onClickSwitchAccount?: () => void;
9
+ }
10
+ export declare const AccessDenied: React.FC<AccessDeniedProps>;
11
+ export {};
@@ -0,0 +1,25 @@
1
+ // Libraries
2
+ import React from 'react';
3
+ // Components
4
+ import { Button, Flex, Typography } from '@antscorp/antsomi-ui/es/components/atoms';
5
+ // Styled
6
+ import { AccessDeniedWrapper } from './styled';
7
+ // Translations
8
+ import { translations } from '@antscorp/antsomi-ui/es/locales/translations';
9
+ // Assets
10
+ import i18nInstance from '@antscorp/antsomi-ui/es/locales/i18n';
11
+ const { Text } = Typography;
12
+ const { t } = i18nInstance;
13
+ const AccessDeniedLockImage = 'https://st-media-template.antsomi.com/icons/antsomi/access_denied.png';
14
+ export const AccessDenied = props => {
15
+ const { image = AccessDeniedLockImage, title = t(translations.accessDenied.title).toString(), subTitle = t(translations.accessDenied.subTitle).toString(), description = t(translations.accessDenied.description).toString(), onClickRequestAccess, onClickSwitchAccount, } = props;
16
+ return (React.createElement(AccessDeniedWrapper, { vertical: true, align: "center", justify: "center" },
17
+ typeof image === 'string' ? (React.createElement("img", { src: image, alt: "Access Denied", className: "access-denied__lock", width: 100, height: "auto" })) : (image),
18
+ React.createElement(Flex, { vertical: true, gap: 5, align: "center" },
19
+ React.createElement(Text, { className: "access-denied__title", strong: true }, title),
20
+ React.createElement(Text, { className: "access-denied__subtitle" }, subTitle),
21
+ React.createElement(Text, { className: "access-denied__description" }, description)),
22
+ React.createElement(Flex, { className: "access-denied__actions", gap: 10 },
23
+ React.createElement(Button, { type: "primary", onClick: onClickRequestAccess }, t(translations.accessDenied.requestAccess).toString()),
24
+ React.createElement(Button, { type: "default", onClick: onClickSwitchAccount }, t(translations.accessDenied.switchAccount).toString()))));
25
+ };
@@ -0,0 +1 @@
1
+ export { AccessDenied } from './AccessDenied';
@@ -0,0 +1 @@
1
+ export { AccessDenied } from './AccessDenied';
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export declare const AccessDeniedWrapper: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("antd/es/flex/interface").FlexProps<import("antd/es/_util/type").AnyObject> & import("react").RefAttributes<HTMLElement>>, any, {}, never>;
@@ -0,0 +1,35 @@
1
+ // Libraries
2
+ import { Flex } from '@antscorp/antsomi-ui/es/components/atoms';
3
+ import styled from 'styled-components';
4
+ // Constants
5
+ import { globalToken } from '@antscorp/antsomi-ui/es/constants';
6
+ const { bw8, orange6 } = globalToken || {};
7
+ export const AccessDeniedWrapper = styled(Flex) `
8
+ width: 100%;
9
+ height: 100%;
10
+
11
+ .access-denied {
12
+ &__lock {
13
+ width: 100px;
14
+ margin-bottom: 15px;
15
+ }
16
+
17
+ &__title {
18
+ color: ${orange6};
19
+ font-size: 20px;
20
+ line-height: 23.44px;
21
+ }
22
+
23
+ &__subtitle {
24
+ font-weight: 600;
25
+ }
26
+
27
+ &__description {
28
+ color: ${bw8};
29
+ }
30
+
31
+ &__actions {
32
+ margin-top: 20px;
33
+ }
34
+ }
35
+ `;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { CheckboxChangeEvent } from 'antd/es/checkbox';
3
+ type AccountItemProps = {
4
+ checked: boolean;
5
+ label: string;
6
+ disabled?: boolean;
7
+ name?: string;
8
+ onChange?: (e: CheckboxChangeEvent) => void;
9
+ };
10
+ declare const _default: React.NamedExoticComponent<AccountItemProps>;
11
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import React, { memo } from 'react';
2
+ import { CheckboxStyled } from './styled';
3
+ import { Typography } from '../../atoms';
4
+ const AccountItem = props => {
5
+ const { checked, label, disabled, name, onChange } = props;
6
+ const TextLabel = ({ children }) => (React.createElement(Typography.Text, { ellipsis: { tooltip: { title: children } }, style: { maxWidth: '220px' } }, children));
7
+ return (React.createElement(CheckboxStyled, { name: name, disabled: disabled, checked: checked, onChange: onChange },
8
+ React.createElement(TextLabel, null, label)));
9
+ };
10
+ export default memo(AccountItem);
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  type AccountListProps = {};
3
- declare const AccountList: React.FC<AccountListProps>;
4
- export default AccountList;
3
+ declare const _default: React.NamedExoticComponent<AccountListProps>;
4
+ export default _default;
@@ -1,56 +1,93 @@
1
- import React, { useContext, useState } from 'react';
2
- import { AccountListBody, AccountListContent, AccountListFooter, AccountListTitleGroup, AccountListWrapper, CheckboxStyled, } from './styled';
3
- import { Button, Icon, Input, Scrollbars, Typography } from '../../atoms';
4
- import { Dropdown } from '../Dropdown';
1
+ // Libraries
2
+ import React, { memo, useContext, useEffect, useState } from 'react';
3
+ import { slice } from 'lodash';
4
+ // Context
5
5
  import { SelectAccountContext } from './context/SelectAccountContext';
6
+ // Components
7
+ import { AccountListBody, AccountListContent, AccountListFooter, AccountListTitleGroup, AccountListWrapper, } from './styled';
8
+ import { Button, Icon, Input, Scrollbars } from '../../atoms';
9
+ import { Dropdown } from '../Dropdown';
10
+ import AccountItem from './AccountItem';
6
11
  const AccountList = () => {
12
+ var _a;
7
13
  const { formListRef, state, dispatch } = useContext(SelectAccountContext);
8
- const { usersSelected, usersDisplay, disabledAccount, nameKey, userIdKey, searchText, listAccountGroupDisplay, } = state;
14
+ const { usersSelected, usersDisplay, disabledAccount, nameKey, userIdKey, searchText, listAccountGroupDisplay, limit = 10, } = state;
15
+ const POSITION_TOP = 0.9;
16
+ // States
9
17
  const [openGroup, setOpenGroup] = useState(true);
10
18
  const [openAccount, setOpenAccount] = useState(true);
19
+ const [page, setPage] = useState(1);
20
+ const [pageGroup, setPageGroup] = useState(1);
21
+ const [tempSelected, setTempSelected] = useState([]);
22
+ useEffect(() => {
23
+ setTempSelected([...usersSelected]);
24
+ }, [usersSelected]);
11
25
  const handleCancel = () => {
12
26
  dispatch({ type: 'CLOSE_ACCOUNT_LIST' });
13
27
  };
14
28
  const handleApply = () => {
15
- dispatch({ type: 'APPLY', payload: { formRef: formListRef } });
29
+ dispatch({ type: 'APPLY_SELECTED', payload: tempSelected });
16
30
  };
17
31
  const handleSearch = text => {
18
32
  dispatch({ type: 'UPDATE_SEARCH_TEXT', payload: text });
19
33
  };
20
- const TextLabel = ({ children }) => (React.createElement(Typography.Text, { ellipsis: { tooltip: { title: children } }, style: { maxWidth: '220px' } }, children));
34
+ const handleTempSelected = (isChecked, key) => {
35
+ if (isChecked) {
36
+ setTempSelected([...tempSelected, key]);
37
+ }
38
+ else {
39
+ setTempSelected(tempSelected.filter(id => id !== key));
40
+ }
41
+ };
21
42
  return (React.createElement(AccountListWrapper, null,
22
43
  React.createElement(AccountListBody, null,
23
44
  React.createElement("form", { ref: formListRef, id: "form-account-list" },
24
45
  React.createElement(Input, { value: searchText, placeholder: "Search", suffix: React.createElement(Icon, { type: "icon-ants-search-2" }), onAfterChange: value => handleSearch(value), debounce: 500 }),
25
46
  (state === null || state === void 0 ? void 0 : state.type) === 'group' ? (React.createElement(React.Fragment, null,
26
- React.createElement(Dropdown, { open: openGroup, getPopupContainer: () => document.getElementById('account-group-list') || document.body, overlayStyle: { position: 'initial' }, trigger: ['click'], dropdownRender: () => (
27
- // <AccountListContent>
28
- React.createElement(Scrollbars, { style: {
29
- width: '100%',
30
- height: 160,
31
- } }, listAccountGroupDisplay === null || listAccountGroupDisplay === void 0 ? void 0 : listAccountGroupDisplay.map((item, idx) => (React.createElement(CheckboxStyled, { key: item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey], name: item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey], value: typeof (item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey]), disabled: disabledAccount === null || disabledAccount === void 0 ? void 0 : disabledAccount.includes(item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey]), defaultChecked: usersSelected === null || usersSelected === void 0 ? void 0 : usersSelected.includes(item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey]) },
32
- React.createElement(TextLabel, null, item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupNameKey])))))
33
- // </AccountListContent>
34
- ) },
47
+ React.createElement(Dropdown, { open: openGroup, getPopupContainer: () => document.getElementById('account-group-list') || document.body, overlayStyle: { position: 'initial' }, trigger: ['click'], dropdownRender: () => {
48
+ var _a;
49
+ return (
50
+ // <AccountListContent>
51
+ React.createElement(Scrollbars, { width: "100%", autoHeight: true, autoHeightMax: 160, onScrollFrame: values => {
52
+ if (values.top > POSITION_TOP &&
53
+ limit * pageGroup < (listAccountGroupDisplay === null || listAccountGroupDisplay === void 0 ? void 0 : listAccountGroupDisplay.length)) {
54
+ setPageGroup(pageGroup + 1);
55
+ }
56
+ } },
57
+ React.createElement(AccountListContent, null, (_a = slice(listAccountGroupDisplay, 0, limit * pageGroup)) === null || _a === void 0 ? void 0 : _a.map(item => (React.createElement(AccountItem, { key: item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey], name: item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey], checked: tempSelected.includes(item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey]), label: item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupNameKey], disabled: disabledAccount === null || disabledAccount === void 0 ? void 0 : disabledAccount.includes(item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey]), onChange: e => handleTempSelected(e.target.checked, item === null || item === void 0 ? void 0 : item[state === null || state === void 0 ? void 0 : state.groupIdKey]) })))))
58
+ // </AccountListContent>
59
+ );
60
+ } },
35
61
  React.createElement(AccountListTitleGroup, { onClick: () => setOpenGroup(!openGroup) },
36
- React.createElement("div", null, "Account Group"),
37
- React.createElement(Icon, { type: "icon-ants-expand-more", size: 20, style: {
62
+ React.createElement("div", null, state.groupText || 'Account group'),
63
+ React.createElement(Icon, { type: "icon-ants-expand-more", size: 20, color: "#595959", style: {
38
64
  transform: openGroup ? 'rotate(180deg)' : 'rotate(0deg)',
39
65
  transition: '0.3s',
40
66
  } }))),
41
67
  React.createElement("div", { id: "account-group-list" }),
42
- React.createElement(Dropdown, { open: openAccount, getPopupContainer: () => document.getElementById('account-list') || document.body, overlayStyle: { position: 'initial' }, trigger: ['click'], dropdownRender: () => (React.createElement(AccountListContent, null, usersDisplay === null || usersDisplay === void 0 ? void 0 : usersDisplay.map(item => (React.createElement(CheckboxStyled, { key: item === null || item === void 0 ? void 0 : item[userIdKey], name: item === null || item === void 0 ? void 0 : item[userIdKey], value: typeof (item === null || item === void 0 ? void 0 : item[userIdKey]), disabled: disabledAccount === null || disabledAccount === void 0 ? void 0 : disabledAccount.includes(item === null || item === void 0 ? void 0 : item[userIdKey]), defaultChecked: usersSelected.includes(item === null || item === void 0 ? void 0 : item[userIdKey]) },
43
- React.createElement(TextLabel, null, item === null || item === void 0 ? void 0 : item[nameKey])))))) },
68
+ React.createElement(Dropdown, { open: openAccount, getPopupContainer: () => document.getElementById('account-list') || document.body, overlayStyle: { position: 'initial' }, trigger: ['click'], dropdownRender: () => {
69
+ var _a;
70
+ return (React.createElement(Scrollbars, { autoHeight: true, autoHeightMax: 160, width: "100%", onScrollFrame: values => {
71
+ if (values.top > POSITION_TOP && limit * page < (usersDisplay === null || usersDisplay === void 0 ? void 0 : usersDisplay.length)) {
72
+ setPage(page + 1);
73
+ }
74
+ } },
75
+ React.createElement(AccountListContent, null, (_a = slice(usersDisplay, 0, limit * page)) === null || _a === void 0 ? void 0 : _a.map(item => (React.createElement(AccountItem, { key: item === null || item === void 0 ? void 0 : item[userIdKey], name: item === null || item === void 0 ? void 0 : item[userIdKey], checked: tempSelected.includes(item === null || item === void 0 ? void 0 : item[userIdKey]), label: item === null || item === void 0 ? void 0 : item[nameKey], disabled: disabledAccount === null || disabledAccount === void 0 ? void 0 : disabledAccount.includes(item === null || item === void 0 ? void 0 : item[userIdKey]), onChange: e => handleTempSelected(e.target.checked, item === null || item === void 0 ? void 0 : item[userIdKey]) }))))));
76
+ } },
44
77
  React.createElement(AccountListTitleGroup, { onClick: () => setOpenAccount(!openAccount) },
45
- React.createElement("div", null, "Account"),
46
- React.createElement(Icon, { type: "icon-ants-expand-more", size: 20, style: {
78
+ React.createElement("div", null, state.accountText || 'Account'),
79
+ React.createElement(Icon, { type: "icon-ants-expand-more", size: 20, color: "#595959", style: {
47
80
  transform: openAccount ? 'rotate(180deg)' : 'rotate(0deg)',
48
81
  transition: '0.3s',
49
82
  } }))),
50
- React.createElement("div", { id: "account-list" }))) : (React.createElement(AccountListContent, { style: { marginTop: 15 } }, usersDisplay === null || usersDisplay === void 0 ? void 0 : usersDisplay.map(item => (React.createElement(CheckboxStyled, { key: item === null || item === void 0 ? void 0 : item[userIdKey], name: item === null || item === void 0 ? void 0 : item[userIdKey], value: typeof (item === null || item === void 0 ? void 0 : item[userIdKey]), disabled: disabledAccount === null || disabledAccount === void 0 ? void 0 : disabledAccount.includes(item === null || item === void 0 ? void 0 : item[userIdKey]), defaultChecked: usersSelected.includes(item === null || item === void 0 ? void 0 : item[userIdKey]) },
51
- React.createElement(TextLabel, null, item === null || item === void 0 ? void 0 : item[nameKey])))))))),
83
+ React.createElement("div", { id: "account-list" }))) : (React.createElement(Scrollbars, { autoHeight: true, autoHeightMax: 160, width: "100%", style: { marginTop: 15 }, onScrollFrame: values => {
84
+ if (values.top > POSITION_TOP && limit * page < (usersDisplay === null || usersDisplay === void 0 ? void 0 : usersDisplay.length)) {
85
+ setPage(page + 1);
86
+ }
87
+ } },
88
+ React.createElement(AccountListContent, null, (_a = slice(usersDisplay, 0, limit * page)) === null || _a === void 0 ? void 0 : _a.map(item => (React.createElement(AccountItem, { key: item === null || item === void 0 ? void 0 : item[userIdKey], checked: tempSelected.includes(item === null || item === void 0 ? void 0 : item[userIdKey]), label: item === null || item === void 0 ? void 0 : item[nameKey], disabled: disabledAccount === null || disabledAccount === void 0 ? void 0 : disabledAccount.includes(item === null || item === void 0 ? void 0 : item[userIdKey]), onChange: e => handleTempSelected(e.target.checked, item === null || item === void 0 ? void 0 : item[userIdKey]) })))))))),
52
89
  React.createElement(AccountListFooter, null,
53
90
  React.createElement(Button, { onClick: () => handleCancel() }, state.cancelText || 'Cancel'),
54
91
  React.createElement(Button, { type: "primary", onClick: () => handleApply() }, state.applyText || 'Apply'))));
55
92
  };
56
- export default AccountList;
93
+ export default memo(AccountList);
@@ -90,6 +90,21 @@ export const reducer = (state, action) => produce(state, draft => {
90
90
  }
91
91
  break;
92
92
  }
93
+ case 'APPLY_SELECTED':
94
+ draft.usersSelected = action.payload;
95
+ draft.openAccountList = false;
96
+ // handle change
97
+ if (typeof draft.onChange === 'function') {
98
+ const optionUsersSelected = [...state.users].filter(user => draft.usersSelected.includes(user[state.userIdKey]));
99
+ const optionGroupSelected = state.type === 'group'
100
+ ? [...state.listAccountGroup].filter(group => draft.usersSelected.includes(group[state.groupIdKey]))
101
+ : [];
102
+ draft.onChange(draft.usersSelected, [
103
+ ...(optionUsersSelected || []),
104
+ ...(optionGroupSelected || []),
105
+ ]);
106
+ }
107
+ break;
93
108
  case 'UPDATE_USERS':
94
109
  if (Array.isArray(action.payload)) {
95
110
  draft.users = action.payload;
@@ -13,6 +13,7 @@ export const SelectAccount = props => (React.createElement(QueryClientProviderAn
13
13
  React.createElement(Content, null)))));
14
14
  SelectAccount.defaultProps = {
15
15
  initData: [],
16
+ limit: 10,
16
17
  limitShow: 10,
17
18
  type: 'default',
18
19
  searchType: 'client',
@@ -108,10 +108,12 @@ export const AccountListTitleGroup = styled.div `
108
108
  justify-content: space-between;
109
109
  align-items: center;
110
110
  margin-top: 10px;
111
+ margin-bottom: 10px;
111
112
 
112
- font-size: 14px;
113
- line-height: 16px;
114
- font-weight: 700;
113
+ font-size: 12px;
114
+ line-height: 14px;
115
+ font-weight: 400;
116
+ height: 30px;
115
117
  cursor: pointer;
116
118
  `;
117
119
  export const AccountListContent = styled.div `
@@ -119,41 +121,12 @@ export const AccountListContent = styled.div `
119
121
  flex-direction: column;
120
122
  gap: 5px;
121
123
 
122
- max-height: 160px;
123
- overflow: auto;
124
-
125
124
  & label:hover {
126
125
  background-color: #f2f9ff;
127
126
  }
128
-
129
- &:hover::-webkit-scrollbar-thumb {
130
- display: initial !important;
131
- -ms-overflow-style: initial; /* IE and Edge */
132
- scrollbar-width: initial; /* Firefox */
133
- }
134
-
135
- ::-webkit-scrollbar {
136
- border-radius: 15px !important;
137
- width: 4px !important;
138
- height: 4px !important;
139
- background-color: transparent !important;
140
- }
141
- ::-webkit-scrollbar-track {
142
- border-radius: 15px !important;
143
- background-color: transparent !important;
144
- }
145
-
146
- ::-webkit-scrollbar-thumb {
147
- display: none !important;
148
- -ms-overflow-style: none; /* IE and Edge */
149
- scrollbar-width: none; /* Firefox */
150
-
151
- border-radius: 15px !important;
152
- background-color: #babac0 !important;
153
- }
154
127
  `;
155
128
  export const CheckboxStyled = styled(Checkbox) `
156
- padding: 5px !important;
129
+ padding: 3px !important;
157
130
  border-radius: 10px !important;
158
131
  `;
159
132
  export const ViewAllWrapper = styled.div `
@@ -7,6 +7,8 @@ type GroupAccountProps = {
7
7
  listAccountGroup: any[];
8
8
  groupNameKey: string;
9
9
  groupIdKey: string;
10
+ groupText?: string;
11
+ accountText?: string;
10
12
  };
11
13
  export type SelectAccountWithUsers = {
12
14
  users?: Record<any, string>[];
@@ -27,6 +29,7 @@ export type SelectAccountProps = {
27
29
  onlyOne?: boolean;
28
30
  disabled?: boolean;
29
31
  disabledAccount?: any[];
32
+ limit?: number;
30
33
  limitShow?: number;
31
34
  className?: string;
32
35
  styles?: {
@@ -64,6 +67,9 @@ export type TAction = {
64
67
  payload: {
65
68
  formRef: React.RefObject<HTMLFormElement>;
66
69
  };
70
+ } | {
71
+ type: 'APPLY_SELECTED';
72
+ payload: any[];
67
73
  } | {
68
74
  type: 'UPDATE';
69
75
  payload: SelectAccountProps;
@@ -58,6 +58,7 @@ export * from './ProcessLoading';
58
58
  export * from './Tree';
59
59
  export * from './MatchAnySelect';
60
60
  export * from './ApplyPopupContent';
61
+ export * from './AccessDenied';
61
62
  export { EditorScript } from './EditorScript';
62
63
  export { EditorTab } from './EditorTab';
63
64
  export { SelectAccount } from './SelectAccount';
@@ -58,6 +58,7 @@ export * from './ProcessLoading';
58
58
  export * from './Tree';
59
59
  export * from './MatchAnySelect';
60
60
  export * from './ApplyPopupContent';
61
+ export * from './AccessDenied';
61
62
  export { EditorScript } from './EditorScript';
62
63
  export { EditorTab } from './EditorTab';
63
64
  export { SelectAccount } from './SelectAccount';
@@ -24,8 +24,9 @@ import { translate } from './utils';
24
24
  import Icon from '@antscorp/icons';
25
25
  import { useDebounce } from '@antscorp/antsomi-ui/es/hooks/useDebounceV2';
26
26
  import { DEFAULT_TRANSLATE_DATA } from './constant';
27
- import { THEME } from '@antscorp/antsomi-ui/es/constants';
27
+ import { THEME, UOGS_PREFIX } from '@antscorp/antsomi-ui/es/constants';
28
28
  import { useAppConfigContext } from '../../..';
29
+ // Constants
29
30
  import { ENV } from '@antscorp/antsomi-ui/es/config';
30
31
  // const STEP = {
31
32
  // SWITCH_ACCOUNT: 'SWITCH_ACCOUNT',
@@ -228,7 +229,7 @@ export const AccountSharing = props => {
228
229
  });
229
230
  // const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
230
231
  const onClickButtonLogout = () => {
231
- removeCookie(`uogs_${networkId}`, Object.assign(Object.assign({}, (env !== ENV.DEV && {
232
+ removeCookie(`${UOGS_PREFIX}${networkId}`, Object.assign(Object.assign({}, (env !== ENV.DEV && {
232
233
  domain: `.${origin.split('.').splice(-2).join('.')}`,
233
234
  })), { path: '/', sameSite: 'none', secure: true }));
234
235
  if (callbackLogout)
@@ -17,22 +17,24 @@ import { cloneDeep, isString, merge, omit } from 'lodash';
17
17
  import isEqual from 'react-fast-compare';
18
18
  import { translations } from '@antscorp/antsomi-ui/es/locales/translations';
19
19
  import { Helmet } from 'react-helmet';
20
+ import { useCookies } from 'react-cookie';
20
21
  // Styled
21
22
  import { ChildrenWrapper, ContentWrapper, LayoutWrapper, NotificationWrapper } from './styled';
22
23
  // Components
23
24
  import { LeftMenu } from '../../organism';
24
25
  import { Flex } from '../../atoms';
25
- import { HeaderV2 } from '../../molecules';
26
+ import { HeaderV2, AccessDenied } from '../../molecules';
26
27
  // Contexts
27
28
  import { AppConfigContext } from '../../..';
28
29
  // Constants
29
- import { APP_CODES, APP_IAM_DOMAIN, APP_PERMISSION_DOMAIN, IAM_API, PERMISSION_API, PORTALS_IDS, SOCKET_API, } from '../../../constants';
30
+ import { APP_CODES, APP_IAM_DOMAIN, APP_PERMISSION_DOMAIN, IAM_API, PERMISSION_API, PORTALS_IDS, SOCKET_API, UOGS_PREFIX, } from '../../../constants';
31
+ import { ENV } from '@antscorp/antsomi-ui/es/config';
30
32
  // Css
31
33
  import '@antscorp/processing-notification/dist/index.css';
32
34
  import { useLayoutStore } from './stores';
33
35
  // Utils
34
36
  import { hasSelectAccountPermission } from './utils';
35
- import { useDeepCompareMemo, useMutationObserver } from '@antscorp/antsomi-ui/es/hooks';
37
+ import { useCustomRouter, useDeepCompareMemo, useMutationObserver, } from '@antscorp/antsomi-ui/es/hooks';
36
38
  import { HOME_MENU_ITEMS } from '../../organism/LeftMenu/constants';
37
39
  import { RecommendationWorkspace } from './components';
38
40
  import i18nInstance from '@antscorp/antsomi-ui/es/locales/i18n';
@@ -40,6 +42,7 @@ const { DATAFLOWS, APP_ANTALYSER } = APP_CODES;
40
42
  export const Layout = memo(props => {
41
43
  const { leftMenuProps, headerProps = {}, workspaceProps, contentWrapperProps, processingNotificationProps, children, onActiveMenuChange, } = props;
42
44
  const _a = workspaceProps || {}, { workspaceContentProps } = _a, restOfWorkspaceProps = __rest(_a, ["workspaceContentProps"]);
45
+ // Hooks
43
46
  const appConfig = useContextSelector(AppConfigContext, state => state);
44
47
  const { auth, languageCode, appCode, permissionDomain: configPermissionDomain, iamDomain: configIamDomain, env, } = appConfig;
45
48
  const { token, userId, portalId } = auth || {};
@@ -47,10 +50,13 @@ export const Layout = memo(props => {
47
50
  const header = useLayoutStore(store => store.state.header);
48
51
  const contentWrapper = useLayoutStore(store => store.state.contentWrapper);
49
52
  const workspace = useLayoutStore(store => store.state.workspace);
53
+ const [, , removeCookie] = useCookies();
54
+ const { navigate } = useCustomRouter();
50
55
  const [showAccountSelection, setShowAccountSelection] = useState(false);
51
56
  const [noSpaceTopContent, setNoSpaceTopContent] = useState(false);
52
57
  const [activeMenuCode, setActiveMenuCode] = useState('');
53
58
  const [activePageTitle, setActivePageTitle] = useState('');
59
+ const [isAccessDenied, setIsAccessDenied] = useState(false);
54
60
  const notificationWrapperRef = useRef(null);
55
61
  useMutationObserver(() => {
56
62
  if (notificationWrapperRef.current) {
@@ -125,7 +131,7 @@ export const Layout = memo(props => {
125
131
  const onActiveMenuCodeChange = useCallback((activeItemPath, flattenPermissionList, menuListPermission) => {
126
132
  var _a;
127
133
  const activeMenuItem = activeItemPath === null || activeItemPath === void 0 ? void 0 : activeItemPath[(activeItemPath === null || activeItemPath === void 0 ? void 0 : activeItemPath.length) - 1];
128
- const { menu_item_code, page_title, menu_item_name } = activeMenuItem || {};
134
+ const { menu_item_code, page_title, menu_item_name, permission_code } = activeMenuItem || {};
129
135
  setActivePageTitle(page_title
130
136
  ? i18nInstance.t((_a = translations.leftMenu.pageTitle) === null || _a === void 0 ? void 0 : _a[`${page_title}`]).toString()
131
137
  : menu_item_name);
@@ -138,7 +144,20 @@ export const Layout = memo(props => {
138
144
  appItem: activeItemPath[0],
139
145
  });
140
146
  setShowAccountSelection(hasRole);
147
+ // Check if the user has permission or not (access denied)
148
+ if (!!permission_code && !!activeMenuItem && !!flattenPermissionList) {
149
+ const isAccessDenied = !flattenPermissionList.some(item => item.menu_code === activeMenuItem.permission_code);
150
+ setIsAccessDenied(isAccessDenied);
151
+ }
141
152
  }, [onActiveMenuChange]);
153
+ const onClickSwitchAccount = useCallback(() => {
154
+ // Remove cookie when switch account
155
+ removeCookie(`${UOGS_PREFIX}${portalId}`, Object.assign(Object.assign({}, (env !== ENV.DEV && {
156
+ domain: `.${origin.split('.').splice(-2).join('.')}`,
157
+ })), { path: '/', sameSite: 'none', secure: true }));
158
+ // Redirect to login page
159
+ navigate('/login');
160
+ }, [env, portalId, navigate, removeCookie]);
142
161
  return (React.createElement(LayoutWrapper, { showLeftMenu: !!showLeftMenu },
143
162
  React.createElement(Helmet, null,
144
163
  React.createElement("meta", { charSet: "utf-8" }),
@@ -154,6 +173,5 @@ export const Layout = memo(props => {
154
173
  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" },
155
174
  React.createElement(RecommendationWorkspace, null))) : (React.createElement("div", Object.assign({ className: `layout-body__content ${(workspaceProps === null || workspaceProps === void 0 ? void 0 : workspaceProps.className) || ''}` }, mergeWorkSpaceProps),
156
175
  React.createElement(NotificationWrapper, { className: "process-notification", ref: notificationWrapperRef }, showNotification && (React.createElement(AntsProcessingNotification, Object.assign({}, antsProcessingNotificationConfig)))),
157
- React.createElement(ChildrenWrapper, Object.assign({}, workspaceContentProps),
158
- React.createElement("div", null, children))))))));
176
+ React.createElement(ChildrenWrapper, Object.assign({}, workspaceContentProps), isAccessDenied ? (React.createElement(AccessDenied, { onClickSwitchAccount: onClickSwitchAccount })) : (React.createElement("div", null, children)))))))));
159
177
  }, (prevProps, nextProps) => isEqual(prevProps, nextProps));
@@ -102,6 +102,9 @@ THEME.components = {
102
102
  colorBgTextHover: (_f = THEME.token) === null || _f === void 0 ? void 0 : _f.blue,
103
103
  colorBgTextActive: (_g = THEME.token) === null || _g === void 0 ? void 0 : _g.blue1_1,
104
104
  },
105
+ Typography: {
106
+ lineHeight: 1.2,
107
+ },
105
108
  Input: {
106
109
  controlHeight: 31,
107
110
  colorBgContainerDisabled: (_h = THEME.token) === null || _h === void 0 ? void 0 : _h.bw2,
@@ -50,3 +50,4 @@ export declare const METRIC_TYPE: {
50
50
  export declare const ENDPOINT: {
51
51
  toolkitV2: string;
52
52
  };
53
+ export declare const UOGS_PREFIX = "uogs_";
@@ -53,3 +53,4 @@ const TOOLKIT_API_VERSION = '2.0';
53
53
  export const ENDPOINT = {
54
54
  toolkitV2: `toolkit/v${TOOLKIT_API_VERSION}`,
55
55
  };
56
+ export const UOGS_PREFIX = 'uogs_';
@@ -658,5 +658,12 @@
658
658
  "_builtIn": "Built in",
659
659
  "_standard": "Standard"
660
660
  }
661
+ },
662
+ "accessDenied": {
663
+ "title": "Access Denied",
664
+ "subTitle": "You don’t have permission to access this feature",
665
+ "description": "Ask for permission or switch to an account with access",
666
+ "requestAccess": "Request access",
667
+ "switchAccount": "Switch account"
661
668
  }
662
669
  }
@@ -661,6 +661,13 @@ export declare const translationsJson: {
661
661
  _standard: string;
662
662
  };
663
663
  };
664
+ accessDenied: {
665
+ title: string;
666
+ subTitle: string;
667
+ description: string;
668
+ requestAccess: string;
669
+ switchAccount: string;
670
+ };
664
671
  };
665
672
  };
666
673
  vi: {
@@ -875,6 +882,13 @@ export declare const translationsJson: {
875
882
  _standard: string;
876
883
  };
877
884
  };
885
+ accessDenied: {
886
+ title: string;
887
+ subTitle: string;
888
+ description: string;
889
+ requestAccess: string;
890
+ switchAccount: string;
891
+ };
878
892
  };
879
893
  };
880
894
  };
@@ -661,6 +661,13 @@ export declare const convertLanguageJsonToObject: (json: any, objToConvertTo?: C
661
661
  _standard: string;
662
662
  };
663
663
  };
664
+ accessDenied: {
665
+ title: string;
666
+ subTitle: string;
667
+ description: string;
668
+ requestAccess: string;
669
+ switchAccount: string;
670
+ };
664
671
  }>, current?: string) => void;
665
672
  export declare const t: (id: string, ...rest: any[]) => [string, ...any[]];
666
673
  export declare const getTranslateMessage: (id: string, defaultMessage?: string, value?: Record<string, unknown>) => string;
@@ -208,5 +208,12 @@
208
208
  "_builtIn": "Mẫu",
209
209
  "_standard": "Tiêu chuẩn"
210
210
  }
211
+ },
212
+ "accessDenied": {
213
+ "title": "Truy cập bị từ chối",
214
+ "subTitle": "Bạn không có quyền truy cập tính năng này",
215
+ "description": "Hãy yêu cầu quyền truy cập hoặc chuyển sang tài khoản có quyền",
216
+ "requestAccess": "Yêu cầu truy cập",
217
+ "switchAccount": "Đổi tài khoản"
211
218
  }
212
219
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.544",
3
+ "version": "1.3.5-beta.545",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",