@blocklet/ui-react 3.4.15 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/lib/common/org-switch/use-org.d.ts +4 -4
  2. package/package.json +9 -6
  3. package/.aigne/doc-smith/.local/afs-storage.sqlite3 +0 -0
  4. package/.aigne/doc-smith/config.yaml +0 -78
  5. package/.aigne/doc-smith/history.yaml +0 -14
  6. package/.aigne/doc-smith/media-description.yaml +0 -11
  7. package/.aigne/doc-smith/output/structure-plan.json +0 -255
  8. package/.aigne/doc-smith/translation-cache.yaml +0 -11
  9. package/.aigne/doc-smith/upload-cache.yaml +0 -528
  10. package/build.config.ts +0 -24
  11. package/docs/_sidebar.md +0 -19
  12. package/docs/assets/diagram/component-installer-diagram-0.ja.jpg +0 -0
  13. package/docs/assets/diagram/component-installer-diagram-0.jpg +0 -0
  14. package/docs/assets/diagram/component-installer-diagram-0.zh-TW.jpg +0 -0
  15. package/docs/assets/diagram/component-installer-diagram-0.zh.jpg +0 -0
  16. package/docs/assets/diagram/component-management-diagram-0.ja.jpg +0 -0
  17. package/docs/assets/diagram/component-management-diagram-0.jpg +0 -0
  18. package/docs/assets/diagram/component-management-diagram-0.zh-TW.jpg +0 -0
  19. package/docs/assets/diagram/component-management-diagram-0.zh.jpg +0 -0
  20. package/docs/assets/diagram/core-concepts-diagram-0.ja.jpg +0 -0
  21. package/docs/assets/diagram/core-concepts-diagram-0.jpg +0 -0
  22. package/docs/assets/diagram/core-concepts-diagram-0.zh-TW.jpg +0 -0
  23. package/docs/assets/diagram/core-concepts-diagram-0.zh.jpg +0 -0
  24. package/docs/assets/diagram/dashboard-diagram-0.ja.jpg +0 -0
  25. package/docs/assets/diagram/dashboard-diagram-0.jpg +0 -0
  26. package/docs/assets/diagram/dashboard-diagram-0.zh-TW.jpg +0 -0
  27. package/docs/assets/diagram/dashboard-diagram-0.zh.jpg +0 -0
  28. package/docs/assets/diagram/header-diagram-0.ja.jpg +0 -0
  29. package/docs/assets/diagram/header-diagram-0.jpg +0 -0
  30. package/docs/assets/diagram/header-diagram-0.zh-TW.jpg +0 -0
  31. package/docs/assets/diagram/header-diagram-0.zh.jpg +0 -0
  32. package/docs/assets/diagram/layout-diagram-0.ja.jpg +0 -0
  33. package/docs/assets/diagram/layout-diagram-0.jpg +0 -0
  34. package/docs/assets/diagram/layout-diagram-0.zh-TW.jpg +0 -0
  35. package/docs/assets/diagram/layout-diagram-0.zh.jpg +0 -0
  36. package/docs/assets/diagram/notifications-diagram-0.ja.jpg +0 -0
  37. package/docs/assets/diagram/notifications-diagram-0.jpg +0 -0
  38. package/docs/assets/diagram/notifications-diagram-0.zh-TW.jpg +0 -0
  39. package/docs/assets/diagram/notifications-diagram-0.zh.jpg +0 -0
  40. package/docs/assets/diagram/overview-diagram-0.ja.jpg +0 -0
  41. package/docs/assets/diagram/overview-diagram-0.jpg +0 -0
  42. package/docs/assets/diagram/overview-diagram-0.zh-TW.jpg +0 -0
  43. package/docs/assets/diagram/overview-diagram-0.zh.jpg +0 -0
  44. package/docs/assets/diagram/user-center-diagram-0.ja.jpg +0 -0
  45. package/docs/assets/diagram/user-center-diagram-0.jpg +0 -0
  46. package/docs/assets/diagram/user-center-diagram-0.zh-TW.jpg +0 -0
  47. package/docs/assets/diagram/user-center-diagram-0.zh.jpg +0 -0
  48. package/docs/assets/diagram/user-management-diagram-0.ja.jpg +0 -0
  49. package/docs/assets/diagram/user-management-diagram-0.jpg +0 -0
  50. package/docs/assets/diagram/user-management-diagram-0.zh-TW.jpg +0 -0
  51. package/docs/assets/diagram/user-management-diagram-0.zh.jpg +0 -0
  52. package/docs/assets/diagram/user-sessions-diagram-0.ja.jpg +0 -0
  53. package/docs/assets/diagram/user-sessions-diagram-0.jpg +0 -0
  54. package/docs/assets/diagram/user-sessions-diagram-0.zh-TW.jpg +0 -0
  55. package/docs/assets/diagram/user-sessions-diagram-0.zh.jpg +0 -0
  56. package/docs/components-component-management-blocklet-studio.ja.md +0 -194
  57. package/docs/components-component-management-blocklet-studio.md +0 -194
  58. package/docs/components-component-management-blocklet-studio.zh-TW.md +0 -194
  59. package/docs/components-component-management-blocklet-studio.zh.md +0 -194
  60. package/docs/components-component-management-component-installer.ja.md +0 -182
  61. package/docs/components-component-management-component-installer.md +0 -182
  62. package/docs/components-component-management-component-installer.zh-TW.md +0 -182
  63. package/docs/components-component-management-component-installer.zh.md +0 -182
  64. package/docs/components-component-management.ja.md +0 -30
  65. package/docs/components-component-management.md +0 -30
  66. package/docs/components-component-management.zh-TW.md +0 -30
  67. package/docs/components-component-management.zh.md +0 -30
  68. package/docs/components-layout-dashboard.ja.md +0 -185
  69. package/docs/components-layout-dashboard.md +0 -187
  70. package/docs/components-layout-dashboard.zh-TW.md +0 -185
  71. package/docs/components-layout-dashboard.zh.md +0 -185
  72. package/docs/components-layout-footer.ja.md +0 -165
  73. package/docs/components-layout-footer.md +0 -165
  74. package/docs/components-layout-footer.zh-TW.md +0 -165
  75. package/docs/components-layout-footer.zh.md +0 -165
  76. package/docs/components-layout-header.ja.md +0 -183
  77. package/docs/components-layout-header.md +0 -183
  78. package/docs/components-layout-header.zh-TW.md +0 -183
  79. package/docs/components-layout-header.zh.md +0 -183
  80. package/docs/components-layout.ja.md +0 -31
  81. package/docs/components-layout.md +0 -31
  82. package/docs/components-layout.zh-TW.md +0 -31
  83. package/docs/components-layout.zh.md +0 -31
  84. package/docs/components-notifications.ja.md +0 -125
  85. package/docs/components-notifications.md +0 -125
  86. package/docs/components-notifications.zh-TW.md +0 -125
  87. package/docs/components-notifications.zh.md +0 -125
  88. package/docs/components-user-management-user-center.ja.md +0 -148
  89. package/docs/components-user-management-user-center.md +0 -147
  90. package/docs/components-user-management-user-center.zh-TW.md +0 -148
  91. package/docs/components-user-management-user-center.zh.md +0 -148
  92. package/docs/components-user-management-user-sessions.ja.md +0 -121
  93. package/docs/components-user-management-user-sessions.md +0 -123
  94. package/docs/components-user-management-user-sessions.zh-TW.md +0 -121
  95. package/docs/components-user-management-user-sessions.zh.md +0 -121
  96. package/docs/components-user-management.ja.md +0 -49
  97. package/docs/components-user-management.md +0 -51
  98. package/docs/components-user-management.zh-TW.md +0 -49
  99. package/docs/components-user-management.zh.md +0 -49
  100. package/docs/components-utilities-icon.ja.md +0 -106
  101. package/docs/components-utilities-icon.md +0 -106
  102. package/docs/components-utilities-icon.zh-TW.md +0 -106
  103. package/docs/components-utilities-icon.zh.md +0 -106
  104. package/docs/components-utilities.ja.md +0 -136
  105. package/docs/components-utilities.md +0 -136
  106. package/docs/components-utilities.zh-TW.md +0 -136
  107. package/docs/components-utilities.zh.md +0 -136
  108. package/docs/components.ja.md +0 -27
  109. package/docs/components.md +0 -27
  110. package/docs/components.zh-TW.md +0 -27
  111. package/docs/components.zh.md +0 -27
  112. package/docs/core-concepts.ja.md +0 -134
  113. package/docs/core-concepts.md +0 -135
  114. package/docs/core-concepts.zh-TW.md +0 -134
  115. package/docs/core-concepts.zh.md +0 -134
  116. package/docs/getting-started.ja.md +0 -132
  117. package/docs/getting-started.md +0 -132
  118. package/docs/getting-started.zh-TW.md +0 -132
  119. package/docs/getting-started.zh.md +0 -132
  120. package/docs/hooks-api.ja.md +0 -214
  121. package/docs/hooks-api.md +0 -214
  122. package/docs/hooks-api.zh-TW.md +0 -214
  123. package/docs/hooks-api.zh.md +0 -214
  124. package/docs/how-to-guides.ja.md +0 -413
  125. package/docs/how-to-guides.md +0 -413
  126. package/docs/how-to-guides.zh-TW.md +0 -413
  127. package/docs/how-to-guides.zh.md +0 -413
  128. package/docs/overview.ja.md +0 -51
  129. package/docs/overview.md +0 -51
  130. package/docs/overview.zh-TW.md +0 -51
  131. package/docs/overview.zh.md +0 -51
  132. package/glossary.md +0 -12
  133. package/src/@types/index.ts +0 -230
  134. package/src/@types/shims.d.ts +0 -18
  135. package/src/BlockletStudio/README.md +0 -116
  136. package/src/BlockletStudio/index.tsx +0 -145
  137. package/src/ComponentInstaller/ComponentInstaller.stories.jsx +0 -16
  138. package/src/ComponentInstaller/index.jsx +0 -207
  139. package/src/ComponentInstaller/installer-item.jsx +0 -129
  140. package/src/ComponentInstaller/locales.js +0 -22
  141. package/src/ComponentInstaller/use-component-installed.js +0 -88
  142. package/src/ComponentManager/components/add-component.tsx +0 -136
  143. package/src/ComponentManager/components/check-component.tsx +0 -3
  144. package/src/ComponentManager/components/publish-component.tsx +0 -90
  145. package/src/ComponentManager/components/resource-dialog.tsx +0 -91
  146. package/src/ComponentManager/index.tsx +0 -3
  147. package/src/ComponentManager/libs/locales.ts +0 -15
  148. package/src/Dashboard/Dashboard.stories.jsx +0 -20
  149. package/src/Dashboard/app-shell/app-badge.stories.tsx +0 -64
  150. package/src/Dashboard/app-shell/app-badge.tsx +0 -94
  151. package/src/Dashboard/app-shell/app-header.tsx +0 -104
  152. package/src/Dashboard/app-shell/app-info-context.tsx +0 -182
  153. package/src/Dashboard/app-shell/badges/app-badge-default.tsx +0 -130
  154. package/src/Dashboard/app-shell/badges/app-badge-did.tsx +0 -28
  155. package/src/Dashboard/app-shell/badges/app-badge-state.tsx +0 -40
  156. package/src/Dashboard/app-shell/badges/app-badge-switch.tsx +0 -72
  157. package/src/Dashboard/app-shell/badges/app-badge-version.tsx +0 -60
  158. package/src/Dashboard/app-shell/index.ts +0 -5
  159. package/src/Dashboard/index.jsx +0 -184
  160. package/src/Footer/Footer.stories.jsx +0 -33
  161. package/src/Footer/brand.jsx +0 -81
  162. package/src/Footer/copyright.jsx +0 -22
  163. package/src/Footer/index.jsx +0 -111
  164. package/src/Footer/internal-footer.jsx +0 -139
  165. package/src/Footer/layout/plain.jsx +0 -55
  166. package/src/Footer/layout/row.jsx +0 -43
  167. package/src/Footer/layout/standard.jsx +0 -114
  168. package/src/Footer/links.jsx +0 -321
  169. package/src/Footer/social-media.jsx +0 -55
  170. package/src/Header/Header.stories.jsx +0 -30
  171. package/src/Header/index.tsx +0 -259
  172. package/src/Icon/Icon.stories.jsx +0 -12
  173. package/src/Icon/index.tsx +0 -87
  174. package/src/Notifications/Snackbar.tsx +0 -261
  175. package/src/Notifications/hooks/use-title.tsx +0 -254
  176. package/src/Notifications/hooks/use-width.tsx +0 -16
  177. package/src/Notifications/utils.ts +0 -246
  178. package/src/UserCenter/assets/banner.png +0 -0
  179. package/src/UserCenter/components/config-inviter.tsx +0 -48
  180. package/src/UserCenter/components/config-profile.tsx +0 -99
  181. package/src/UserCenter/components/danger-zone.tsx +0 -82
  182. package/src/UserCenter/components/editable-field.tsx +0 -273
  183. package/src/UserCenter/components/fallback.tsx +0 -57
  184. package/src/UserCenter/components/nft-preview.tsx +0 -84
  185. package/src/UserCenter/components/nft.tsx +0 -279
  186. package/src/UserCenter/components/notification.tsx +0 -319
  187. package/src/UserCenter/components/passport.tsx +0 -107
  188. package/src/UserCenter/components/privacy.tsx +0 -120
  189. package/src/UserCenter/components/settings.tsx +0 -170
  190. package/src/UserCenter/components/status-dialog/date-picker.tsx +0 -77
  191. package/src/UserCenter/components/status-dialog/index.tsx +0 -293
  192. package/src/UserCenter/components/status-selector/duration-menu.tsx +0 -90
  193. package/src/UserCenter/components/status-selector/index.tsx +0 -58
  194. package/src/UserCenter/components/status-selector/menu-item.tsx +0 -56
  195. package/src/UserCenter/components/storage/action.tsx +0 -49
  196. package/src/UserCenter/components/storage/connected.tsx +0 -61
  197. package/src/UserCenter/components/storage/delete.tsx +0 -72
  198. package/src/UserCenter/components/storage/disconnect.tsx +0 -40
  199. package/src/UserCenter/components/storage/icons/empty-spaces-nft.svg +0 -1
  200. package/src/UserCenter/components/storage/icons/long-arrow.svg +0 -5
  201. package/src/UserCenter/components/storage/icons/space-connected.svg +0 -3
  202. package/src/UserCenter/components/storage/icons/space-disconnect.svg +0 -3
  203. package/src/UserCenter/components/storage/index.tsx +0 -41
  204. package/src/UserCenter/components/storage/preview-nft.tsx +0 -72
  205. package/src/UserCenter/components/third-party-login/index.tsx +0 -199
  206. package/src/UserCenter/components/third-party-login/third-party-item.tsx +0 -296
  207. package/src/UserCenter/components/user-center.tsx +0 -787
  208. package/src/UserCenter/components/user-info/address.tsx +0 -143
  209. package/src/UserCenter/components/user-info/index.tsx +0 -4
  210. package/src/UserCenter/components/user-info/link-preview-input.tsx +0 -274
  211. package/src/UserCenter/components/user-info/metadata.tsx +0 -658
  212. package/src/UserCenter/components/user-info/social-actions/chat.tsx +0 -43
  213. package/src/UserCenter/components/user-info/social-actions/follow.tsx +0 -23
  214. package/src/UserCenter/components/user-info/social-actions/index.tsx +0 -17
  215. package/src/UserCenter/components/user-info/switch-role.tsx +0 -42
  216. package/src/UserCenter/components/user-info/timezone-select.tsx +0 -119
  217. package/src/UserCenter/components/user-info/user-basic-info.tsx +0 -292
  218. package/src/UserCenter/components/user-info/user-info-item.tsx +0 -54
  219. package/src/UserCenter/components/user-info/user-info.tsx +0 -91
  220. package/src/UserCenter/components/user-info/user-status.tsx +0 -234
  221. package/src/UserCenter/components/user-info/utils.ts +0 -320
  222. package/src/UserCenter/components/webhook-item.tsx +0 -248
  223. package/src/UserCenter/index.tsx +0 -1
  224. package/src/UserCenter/libs/locales.ts +0 -378
  225. package/src/UserCenter/libs/utils.ts +0 -30
  226. package/src/UserSessions/components/user-session-info.tsx +0 -78
  227. package/src/UserSessions/components/user-sessions.tsx +0 -545
  228. package/src/UserSessions/index.tsx +0 -1
  229. package/src/UserSessions/libs/locales.ts +0 -60
  230. package/src/UserSessions/libs/utils.ts +0 -82
  231. package/src/blocklets.js +0 -195
  232. package/src/common/domain-warning.jsx +0 -178
  233. package/src/common/header-addons.jsx +0 -119
  234. package/src/common/link-blocker.jsx +0 -20
  235. package/src/common/notification-addon.jsx +0 -135
  236. package/src/common/org-switch/avatar-uploader.jsx +0 -271
  237. package/src/common/org-switch/create.jsx +0 -267
  238. package/src/common/org-switch/index.jsx +0 -407
  239. package/src/common/org-switch/locales.js +0 -52
  240. package/src/common/org-switch/use-org.jsx +0 -79
  241. package/src/common/overridable-theme-provider.jsx +0 -17
  242. package/src/common/wallet-hidden-topbar.js +0 -14
  243. package/src/common/wizard-modal.jsx +0 -200
  244. package/src/common/ws.js +0 -68
  245. package/src/contexts/config-user-space.tsx +0 -88
  246. package/src/contexts/user-followers.tsx +0 -54
  247. package/src/hooks/use-follow.tsx +0 -75
  248. package/src/hooks/use-mobile.tsx +0 -6
  249. package/src/index.ts +0 -16
  250. package/src/libs/constant.ts +0 -1
  251. package/src/libs/spaces.tsx +0 -18
  252. package/src/libs/with-hide-when-embed.tsx +0 -24
  253. package/src/types.js +0 -45
  254. package/src/utils.js +0 -161
  255. package/vite.config.mjs +0 -34
@@ -1,78 +0,0 @@
1
- import { Box, Chip, Tooltip, Typography } from '@mui/material';
2
- import Avatar from '@arcblock/ux/lib/Avatar';
3
- import { useCreation } from 'ahooks';
4
-
5
- import { User } from '../../@types';
6
-
7
- export default function UserSessionInfo({ user, sessionUser }: { readonly user: User; readonly sessionUser: any }) {
8
- const currentRole = useCreation(() => {
9
- return (user?.passports || [])?.find((item) => item.name === sessionUser.role);
10
- }, [user?.passports, sessionUser?.role]);
11
-
12
- return (
13
- <Box
14
- sx={{
15
- display: 'flex',
16
- alignItems: 'center',
17
- gap: 1,
18
- }}>
19
- <Avatar
20
- size={40}
21
- variant="circle"
22
- shape="circle"
23
- src={sessionUser.avatar}
24
- did={sessionUser.did}
25
- sx={{ flexShrink: 0 }}
26
- />
27
- <Box sx={{ flex: 1, overflow: 'hidden' }}>
28
- <Box
29
- sx={{
30
- display: 'flex',
31
- alignItems: 'center',
32
- gap: 1,
33
- }}>
34
- <Tooltip title={sessionUser.fullName}>
35
- <Typography
36
- sx={{
37
- whiteSpace: 'nowrap',
38
- overflow: 'hidden',
39
- textOverflow: 'ellipsis',
40
- flex: 1,
41
- }}>
42
- {sessionUser.fullName}
43
- </Typography>
44
- </Tooltip>
45
- <Chip
46
- label={currentRole?.title || currentRole?.name || 'Guest'}
47
- size="small"
48
- variant="outlined"
49
- sx={{
50
- flexShrink: 0,
51
- fontWeight: 'bold',
52
- fontSize: '12px',
53
- color: 'text.primary',
54
- borderColor: 'grey.300',
55
- backgroundColor: 'transparent',
56
- textTransform: 'capitalize',
57
- pr: 0.5,
58
- pl: 0,
59
- height: 'auto',
60
- }}
61
- />
62
- </Box>
63
- <Tooltip title={sessionUser.email}>
64
- <Typography
65
- variant="body2"
66
- color="grey"
67
- sx={{
68
- whiteSpace: 'nowrap',
69
- overflow: 'hidden',
70
- textOverflow: 'ellipsis',
71
- }}>
72
- {sessionUser.email}
73
- </Typography>
74
- </Tooltip>
75
- </Box>
76
- </Box>
77
- );
78
- }
@@ -1,545 +0,0 @@
1
- /* eslint-disable no-nested-ternary */
2
- /* eslint-disable react/no-unstable-nested-components */
3
- import Datatable from '@arcblock/ux/lib/Datatable';
4
- import { useCreation, useMemoizedFn, useMount, useReactive, useRequest } from 'ahooks';
5
- import { translate } from '@arcblock/ux/lib/Locale/util';
6
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
7
- import RelativeTime from '@arcblock/ux/lib/RelativeTime';
8
- import UAParser from 'ua-parser-js';
9
- import { getVisitorId } from '@arcblock/ux/lib/Util';
10
- import { useConfirm } from '@arcblock/ux/lib/Dialog';
11
- import DidAddress from '@arcblock/ux/lib/DID';
12
- import PQueue from 'p-queue';
13
- import {
14
- Box,
15
- Button,
16
- CircularProgress,
17
- FormControlLabel,
18
- Radio,
19
- RadioGroup,
20
- Tooltip,
21
- Typography,
22
- useMediaQuery,
23
- } from '@mui/material';
24
- import { memo, ReactElement, useEffect } from 'react';
25
- import { getBlockletSDK, UserSession } from '@blocklet/js-sdk';
26
- import { mergeSx } from '@arcblock/ux/lib/Util/style';
27
-
28
- import useMobile from '../../hooks/use-mobile';
29
- import UserSessionInfo from './user-session-info';
30
- import { User } from '../../@types';
31
- import { translations } from '../libs/locales';
32
- import { ip2Region } from '../libs/utils';
33
-
34
- const parseUa = (ua: string) => {
35
- const parser = new UAParser(ua, {
36
- // eslint-disable-next-line no-useless-escape
37
- browser: [[/(ArcWallet)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION]],
38
- });
39
- const result = parser.getResult();
40
- return result;
41
- };
42
-
43
- const textRightStyle = {
44
- display: 'flex',
45
- justifyContent: 'flex-end',
46
- textAlign: 'right',
47
- };
48
-
49
- const queue = new PQueue({ concurrency: 1 });
50
-
51
- const UserSessionIp = memo(({ userSession, isMobile = false }: { userSession: any; isMobile: boolean }) => {
52
- const currentState = useReactive({
53
- loading: true,
54
- ipRegion: '',
55
- });
56
-
57
- const { t } = useLocaleContext();
58
-
59
- useEffect(() => {
60
- queue.add(async () => {
61
- try {
62
- currentState.ipRegion = await ip2Region(userSession.lastLoginIp);
63
- } finally {
64
- currentState.loading = false;
65
- }
66
- });
67
- }, [currentState, userSession.lastLoginIp]);
68
-
69
- return (
70
- <Box
71
- {...(isMobile && {
72
- display: 'flex',
73
- alignItems: 'center',
74
- justifyContent: 'flex-end',
75
- gap: 1,
76
- flexWrap: 'wrap',
77
- })}>
78
- {currentState.ipRegion ? (
79
- <>
80
- <Typography variant="body2">{currentState.ipRegion}</Typography>
81
- <Typography variant="body2" color="grey">
82
- {userSession.lastLoginIp || t('unknown')}
83
- </Typography>
84
- </>
85
- ) : (
86
- <>
87
- <Typography>{userSession.lastLoginIp || t('unknown')}</Typography>
88
- {currentState.loading ? (
89
- <Typography variant="body2" color="grey" sx={{ textAlign: 'center' }}>
90
- <CircularProgress size={12} color="inherit" />
91
- </Typography>
92
- ) : null}
93
- </>
94
- )}
95
- </Box>
96
- );
97
- });
98
-
99
- export default function UserSessions({
100
- user,
101
- showAction = true,
102
- showUser = true,
103
- getUserSessions,
104
- showOffline = false,
105
- showAppPid = false,
106
- }: {
107
- readonly user: User & {
108
- userSessions?: any[];
109
- };
110
- readonly showAction?: boolean;
111
- readonly showUser?: boolean;
112
- readonly showOffline?: boolean;
113
- readonly showAppPid?: boolean;
114
- readonly getUserSessions: (params: {
115
- page: number;
116
- pageSize: number;
117
- status?: 'online' | 'expired' | 'offline';
118
- }) => Promise<{
119
- paging: {
120
- total: number;
121
- };
122
- list: UserSession[];
123
- }>;
124
- }) {
125
- const client = getBlockletSDK();
126
- const filterParams = useReactive({
127
- status: 'online',
128
- page: 1,
129
- pageSize: 10,
130
- });
131
- const userSessionsCountMap = useReactive({
132
- online: 0,
133
- expired: 0,
134
- offline: 0,
135
- });
136
- const currentVisitorId = getVisitorId();
137
- const { locale } = useLocaleContext();
138
- const isMobile = useMobile({ key: 'md' });
139
- const isLg = useMediaQuery((theme: any) => theme.breakpoints.down('lg'));
140
- const { confirmApi, confirmHolder } = useConfirm();
141
- const t = useMemoizedFn((key, data = {}) => {
142
- return translate(translations, key, locale, 'en', data);
143
- });
144
- const getData = useMemoizedFn(async () => {
145
- const result = await getUserSessions({
146
- page: filterParams.page,
147
- pageSize: filterParams.pageSize,
148
- status: filterParams.status as 'online' | 'expired' | 'offline',
149
- });
150
-
151
- const total = result?.paging?.total || 0;
152
- userSessionsCountMap[filterParams.status as keyof typeof userSessionsCountMap] = total;
153
-
154
- return {
155
- total,
156
- list: result?.list || [],
157
- };
158
- });
159
-
160
- useMount(async () => {
161
- const expiredResult = await getUserSessions({
162
- page: 1,
163
- pageSize: 1,
164
- status: 'expired',
165
- });
166
- userSessionsCountMap.expired = expiredResult?.paging?.total || 0;
167
-
168
- const offlineResult = await getUserSessions({
169
- page: 1,
170
- pageSize: 1,
171
- status: 'offline',
172
- });
173
- userSessionsCountMap.offline = offlineResult?.paging?.total || 0;
174
- });
175
-
176
- const pageState = useRequest(getData, {
177
- refreshDeps: [filterParams.status, filterParams.page, filterParams.pageSize],
178
- });
179
-
180
- const safeData = useCreation(() => {
181
- return pageState.data?.list || [];
182
- }, [pageState.data?.list]);
183
-
184
- const disableLogout = useCreation(() => {
185
- const status = filterParams.status as keyof typeof userSessionsCountMap;
186
- if (status === 'online') {
187
- // HACK: 这里只能假设会话列表包含了当前登录的会话,所以只有大于 1 的时候才能够去注销其他会话
188
- return userSessionsCountMap[status] <= 1;
189
- }
190
- return userSessionsCountMap[status] === 0;
191
- }, [safeData, currentVisitorId]);
192
-
193
- const mergeStyle = useCreation(() => {
194
- return mergeSx({}, isMobile ? textRightStyle : {});
195
- }, [isMobile]);
196
-
197
- const logout = useMemoizedFn(({ visitorId }) => {
198
- confirmApi.open({
199
- title: t('logoutThisSession'),
200
- content: t('logoutThisSessionConfirm'),
201
- confirmButtonText: t('confirm'),
202
- confirmButtonProps: {
203
- color: 'error',
204
- },
205
- cancelButtonText: t('cancel'),
206
- onConfirm: async () => {
207
- await client.user.logout({
208
- visitorId,
209
- includeFederated: true,
210
- });
211
- // 如果当前页没有数据需要向前翻页
212
- const { page = 0 } = filterParams;
213
- const { list = [] } = pageState.data || {};
214
- const currentPageLength = list.length || 0;
215
- if (page > 1 && currentPageLength === 1) {
216
- filterParams.page = Math.max(page - 1, 1);
217
- }
218
- pageState.refresh();
219
- confirmApi.close();
220
- },
221
- });
222
- });
223
- const logoutAll = useMemoizedFn(() => {
224
- confirmApi.open({
225
- title: t('logoutAllSession', {
226
- type: t(filterParams.status),
227
- }),
228
- content: t('logoutAllSessionConfirm', {
229
- type: t(filterParams.status),
230
- }),
231
- confirmButtonText: t('confirm'),
232
- confirmButtonProps: {
233
- color: 'error',
234
- },
235
- cancelButtonText: t('cancel'),
236
- onConfirm: async () => {
237
- await client.user.logout({
238
- status: filterParams.status,
239
- visitorId: currentVisitorId as string,
240
- includeFederated: true,
241
- });
242
- // 重置至第一页
243
- filterParams.page = 1;
244
- pageState.refresh();
245
- confirmApi.close();
246
- },
247
- });
248
- });
249
- const customButtons: ReactElement<any>[] = [];
250
- if (showAction) {
251
- customButtons.push(
252
- <Tooltip
253
- key="logoutAll"
254
- title={t('logoutAllTips', {
255
- type: t(filterParams.status),
256
- })}>
257
- <Button
258
- sx={{ ml: 0.5 }}
259
- size="small"
260
- variant="contained"
261
- color="error"
262
- onClick={logoutAll}
263
- disabled={disableLogout}>
264
- {t('logoutAll', {
265
- type: t(filterParams.status),
266
- })}
267
- </Button>
268
- </Tooltip>
269
- );
270
- }
271
- const tableOptions = useCreation(() => {
272
- return {
273
- // viewColumns: false,
274
- search: false,
275
- sort: false,
276
- download: false,
277
- filter: false,
278
- print: false,
279
- expandableRowsOnClick: false,
280
- searchDebounceTime: 600,
281
- page: filterParams.page - 1,
282
- rowsPerPage: filterParams.pageSize,
283
- count: pageState.data?.total || 0,
284
- };
285
- }, [pageState.data?.total, filterParams.page, filterParams.pageSize]);
286
- const columns = [
287
- {
288
- label: t('platform'),
289
- name: 'platform',
290
- options: {
291
- customBodyRenderLite: (rawIndex: number) => {
292
- const x = safeData[rawIndex];
293
- const result = parseUa(x?.ua);
294
- return (
295
- <Box sx={mergeStyle}>{[result.os?.name, result.os?.version].filter(Boolean).join('/') || t('unknown')}</Box>
296
- );
297
- },
298
- },
299
- },
300
- {
301
- label: t('deviceType'),
302
- name: 'deviceType',
303
- options: {
304
- customBodyRenderLite: (rawIndex: number) => {
305
- const x = safeData[rawIndex];
306
- const result = parseUa(x?.ua);
307
- return (
308
- <Box sx={mergeStyle}>
309
- {[result.browser?.name, result.browser?.version].filter(Boolean).join('/') || t('unknown')}
310
- </Box>
311
- );
312
- },
313
- },
314
- },
315
- {
316
- label: t('walletOS'),
317
- name: 'walletOS',
318
- options: {
319
- customBodyRenderLite: (rawIndex: number) => {
320
- const x = safeData[rawIndex];
321
- return <Box sx={mergeStyle}>{x.extra?.walletOS || t('unknown')}</Box>;
322
- },
323
- },
324
- },
325
- showAppPid && {
326
- label: 'App Pid',
327
- name: 'appPid',
328
- options: {
329
- customBodyRenderLite: (rawIndex: number) => {
330
- const x = safeData[rawIndex];
331
- return x.appPid ? <DidAddress size={14} responsive={false} compact did={x.appPid} /> : null;
332
- },
333
- },
334
- },
335
- showUser && {
336
- label: t('user'),
337
- name: 'user',
338
- options: {
339
- customBodyRenderLite: (rawIndex: number) => {
340
- const x = safeData[rawIndex];
341
- return (
342
- <Box sx={mergeSx({ minWidth: 150, maxWidth: 250 }, isMobile ? textRightStyle : {})}>
343
- <UserSessionInfo sessionUser={x.user} user={user} />
344
- </Box>
345
- );
346
- },
347
- },
348
- },
349
- {
350
- label: t('createdAt'),
351
- name: 'createdAt',
352
- options: {
353
- customBodyRenderLite: (rawIndex: number) => {
354
- const x = safeData[rawIndex];
355
- return (
356
- <Box sx={mergeStyle}>
357
- {x.createdAt ? (
358
- <RelativeTime value={x.createdAt} relativeRange={3 * 86400 * 1000} locale={locale} />
359
- ) : (
360
- t('unknown')
361
- )}
362
- </Box>
363
- );
364
- },
365
- },
366
- },
367
- !showOffline && {
368
- label: t('updatedAt'),
369
- name: 'updatedAt',
370
- options: {
371
- customBodyRenderLite: (rawIndex: number) => {
372
- const x = safeData[rawIndex];
373
- return (
374
- <Box sx={mergeStyle}>
375
- {x.status === 'expired' ? (
376
- t('expired')
377
- ) : (
378
- <RelativeTime value={x.updatedAt} relativeRange={3 * 86400 * 1000} locale={locale} />
379
- )}
380
- </Box>
381
- );
382
- },
383
- },
384
- },
385
- {
386
- label: t('lastLoginIp'),
387
- name: 'lastLoginIp',
388
- options: {
389
- customBodyRenderLite: (rawIndex: number) => {
390
- const x = safeData[rawIndex];
391
- return <UserSessionIp userSession={x} isMobile={isMobile} />;
392
- },
393
- },
394
- },
395
- showAction && {
396
- label: t('actions'),
397
- name: 'actions',
398
- options: {
399
- customBodyRenderLite: (rawIndex: number) => {
400
- const x = safeData[rawIndex];
401
- return (
402
- <Box sx={mergeStyle}>
403
- <Button
404
- sx={{
405
- whiteSpace: 'nowrap',
406
- fontSize: '12px !important',
407
- lineHeight: '1.25',
408
- px: 1,
409
- }}
410
- disabled={currentVisitorId === x.visitorId}
411
- variant="outlined"
412
- size="small"
413
- color="error"
414
- onClick={() => logout({ visitorId: x.visitorId })}>
415
- {x.status === 'expired'
416
- ? t('remove')
417
- : currentVisitorId === x.visitorId
418
- ? t('currentSession')
419
- : t('logout')}
420
- </Button>
421
- </Box>
422
- );
423
- },
424
- },
425
- },
426
- ].filter(Boolean);
427
-
428
- return (
429
- <Box
430
- className="pc-user-sessions"
431
- sx={{
432
- maxWidth: isMobile ? 'unset' : isLg ? 'calc(100vw - 300px)' : '100%',
433
- ...(isMobile && {
434
- '.pc-user-sessions-table > div:nth-child(2)': {
435
- border: '1px solid',
436
- borderColor: 'divider',
437
- borderRadius: 1,
438
- },
439
- }),
440
- '.MuiTableCell-head': {
441
- whiteSpace: 'nowrap',
442
- fontWeight: 'bold',
443
- },
444
- '.MuiTableRow-root': {
445
- border: 'unset',
446
- '&:nth-child(even)': {
447
- backgroundColor: 'grey.50',
448
- '&:hover': {
449
- backgroundColor: (theme) => `${theme.palette.grey[50]} !important`,
450
- },
451
- },
452
- },
453
- '.MuiTableRow-hover': {
454
- '&:hover': {
455
- backgroundColor: 'inherit !important',
456
- },
457
- },
458
- '.MuiTableCell-root': {
459
- paddingRight: '8px',
460
- paddingLeft: '8px',
461
- color: 'text.secondary',
462
- ...(isMobile && {
463
- padding: '8px !important',
464
- '&:first-child': {
465
- paddingTop: '20px!important',
466
- },
467
- '&:last-child': {
468
- paddingBottom: '20px!important',
469
- },
470
- }),
471
- },
472
- }}>
473
- {confirmHolder}
474
- <Datatable
475
- count={pageState.data?.total || 0}
476
- locale={locale}
477
- data={safeData}
478
- // @ts-expect-error
479
- columns={columns}
480
- // @ts-expect-error
481
- customButtons={customButtons}
482
- options={tableOptions}
483
- loading={pageState.loading}
484
- className="pc-user-sessions-table"
485
- title={
486
- <RadioGroup
487
- row
488
- sx={{ lineHeight: 1, ml: 1 }}
489
- onChange={(e) => {
490
- filterParams.status = e.target.value;
491
- }}>
492
- <FormControlLabel
493
- value="online"
494
- control={
495
- <Radio size="small" sx={{ lineHeight: 1, fontSize: 0 }} checked={filterParams.status === 'online'} />
496
- }
497
- label={
498
- <Typography sx={{ display: 'flex', alignItems: 'center' }}>
499
- {t('online')}
500
- <Typography component="span" sx={{ ml: 0.5, color: 'text.secondary' }}>
501
- ({userSessionsCountMap.online})
502
- </Typography>
503
- </Typography>
504
- }
505
- />
506
- <FormControlLabel
507
- value="expired"
508
- control={
509
- <Radio size="small" sx={{ lineHeight: 1, fontSize: 0 }} checked={filterParams.status === 'expired'} />
510
- }
511
- label={
512
- <Typography sx={{ display: 'flex', alignItems: 'center' }}>
513
- {t('expired')}
514
- <Typography component="span" sx={{ ml: 0.5, color: 'text.secondary' }}>
515
- ({userSessionsCountMap.expired})
516
- </Typography>
517
- </Typography>
518
- }
519
- />
520
- {showOffline ? (
521
- <FormControlLabel
522
- value="offline"
523
- control={
524
- <Radio size="small" sx={{ lineHeight: 1, fontSize: 0 }} checked={filterParams.status === 'offline'} />
525
- }
526
- label={
527
- <Typography sx={{ display: 'flex', alignItems: 'center' }}>
528
- {t('offline')}
529
- <Typography component="span" sx={{ ml: 0.5, color: 'text.secondary' }}>
530
- ({userSessionsCountMap.offline})
531
- </Typography>
532
- </Typography>
533
- }
534
- />
535
- ) : null}
536
- </RadioGroup>
537
- }
538
- onChange={(state) => {
539
- filterParams.page = state.page + 1;
540
- filterParams.pageSize = state.rowsPerPage;
541
- }}
542
- />
543
- </Box>
544
- );
545
- }
@@ -1 +0,0 @@
1
- export { default as UserSessions } from './components/user-sessions';
@@ -1,60 +0,0 @@
1
- export const translations = {
2
- zh: {
3
- confirm: '确认',
4
- cancel: '取消',
5
- visitorId: '设备标识',
6
- deviceType: '设备类型',
7
- platform: '操作系统',
8
- walletOS: '钱包类型',
9
- role: '角色',
10
- fullname: '姓名',
11
- email: '邮箱',
12
- avatar: '头像',
13
- user: '用户',
14
- createdAt: '首次活动时间',
15
- updatedAt: '最近活动时间',
16
- lastLoginIp: '最近活动地址',
17
- actions: '操作',
18
- logoutAll: '注销所有{type}会话',
19
- logoutAllTips: '不会注销当前会话',
20
- logout: '注销',
21
- currentSession: '当前会话',
22
- unknown: '未知',
23
- expired: '已过期',
24
- remove: '删除',
25
- logoutThisSession: '注销指定会话',
26
- logoutThisSessionConfirm: '确定要注销此会话吗?',
27
- logoutAllSession: '注销所有{type}会话',
28
- logoutAllSessionConfirm: '确定要注销所有{type}会话吗?',
29
- online: '活跃',
30
- },
31
- en: {
32
- confirm: 'Confirm',
33
- cancel: 'Cancel',
34
- visitorId: 'Device ID',
35
- deviceType: 'Device Type',
36
- platform: 'Platform',
37
- walletOS: 'Wallet OS',
38
- role: 'Role',
39
- fullname: 'Fullname',
40
- email: 'Email',
41
- avatar: 'Avatar',
42
- user: 'User',
43
- createdAt: 'First Active Time',
44
- updatedAt: 'Last Active Time',
45
- actions: 'Actions',
46
- lastLoginIp: 'Last Login IP',
47
- logoutAll: 'Logout all {type} sessions',
48
- logoutAllTips: 'Will not logout current session',
49
- logout: 'Logout',
50
- currentSession: 'Current Session',
51
- unknown: 'Unknown',
52
- expired: 'Expired',
53
- remove: 'Remove',
54
- logoutThisSession: 'Logout this session',
55
- logoutThisSessionConfirm: 'Are you sure to logout this session?',
56
- logoutAllSession: 'Logout all {type} sessions',
57
- logoutAllSessionConfirm: 'Are you sure to logout all {type} sessions?',
58
- online: 'Active',
59
- },
60
- };