@blocklet/ui-react 3.4.14 → 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 (256) hide show
  1. package/lib/common/org-switch/use-org.d.ts +4 -4
  2. package/lib/common/ws.d.ts +22 -1
  3. package/package.json +10 -7
  4. package/.aigne/doc-smith/.local/afs-storage.sqlite3 +0 -0
  5. package/.aigne/doc-smith/config.yaml +0 -78
  6. package/.aigne/doc-smith/history.yaml +0 -14
  7. package/.aigne/doc-smith/media-description.yaml +0 -11
  8. package/.aigne/doc-smith/output/structure-plan.json +0 -255
  9. package/.aigne/doc-smith/translation-cache.yaml +0 -11
  10. package/.aigne/doc-smith/upload-cache.yaml +0 -528
  11. package/build.config.ts +0 -24
  12. package/docs/_sidebar.md +0 -19
  13. package/docs/assets/diagram/component-installer-diagram-0.ja.jpg +0 -0
  14. package/docs/assets/diagram/component-installer-diagram-0.jpg +0 -0
  15. package/docs/assets/diagram/component-installer-diagram-0.zh-TW.jpg +0 -0
  16. package/docs/assets/diagram/component-installer-diagram-0.zh.jpg +0 -0
  17. package/docs/assets/diagram/component-management-diagram-0.ja.jpg +0 -0
  18. package/docs/assets/diagram/component-management-diagram-0.jpg +0 -0
  19. package/docs/assets/diagram/component-management-diagram-0.zh-TW.jpg +0 -0
  20. package/docs/assets/diagram/component-management-diagram-0.zh.jpg +0 -0
  21. package/docs/assets/diagram/core-concepts-diagram-0.ja.jpg +0 -0
  22. package/docs/assets/diagram/core-concepts-diagram-0.jpg +0 -0
  23. package/docs/assets/diagram/core-concepts-diagram-0.zh-TW.jpg +0 -0
  24. package/docs/assets/diagram/core-concepts-diagram-0.zh.jpg +0 -0
  25. package/docs/assets/diagram/dashboard-diagram-0.ja.jpg +0 -0
  26. package/docs/assets/diagram/dashboard-diagram-0.jpg +0 -0
  27. package/docs/assets/diagram/dashboard-diagram-0.zh-TW.jpg +0 -0
  28. package/docs/assets/diagram/dashboard-diagram-0.zh.jpg +0 -0
  29. package/docs/assets/diagram/header-diagram-0.ja.jpg +0 -0
  30. package/docs/assets/diagram/header-diagram-0.jpg +0 -0
  31. package/docs/assets/diagram/header-diagram-0.zh-TW.jpg +0 -0
  32. package/docs/assets/diagram/header-diagram-0.zh.jpg +0 -0
  33. package/docs/assets/diagram/layout-diagram-0.ja.jpg +0 -0
  34. package/docs/assets/diagram/layout-diagram-0.jpg +0 -0
  35. package/docs/assets/diagram/layout-diagram-0.zh-TW.jpg +0 -0
  36. package/docs/assets/diagram/layout-diagram-0.zh.jpg +0 -0
  37. package/docs/assets/diagram/notifications-diagram-0.ja.jpg +0 -0
  38. package/docs/assets/diagram/notifications-diagram-0.jpg +0 -0
  39. package/docs/assets/diagram/notifications-diagram-0.zh-TW.jpg +0 -0
  40. package/docs/assets/diagram/notifications-diagram-0.zh.jpg +0 -0
  41. package/docs/assets/diagram/overview-diagram-0.ja.jpg +0 -0
  42. package/docs/assets/diagram/overview-diagram-0.jpg +0 -0
  43. package/docs/assets/diagram/overview-diagram-0.zh-TW.jpg +0 -0
  44. package/docs/assets/diagram/overview-diagram-0.zh.jpg +0 -0
  45. package/docs/assets/diagram/user-center-diagram-0.ja.jpg +0 -0
  46. package/docs/assets/diagram/user-center-diagram-0.jpg +0 -0
  47. package/docs/assets/diagram/user-center-diagram-0.zh-TW.jpg +0 -0
  48. package/docs/assets/diagram/user-center-diagram-0.zh.jpg +0 -0
  49. package/docs/assets/diagram/user-management-diagram-0.ja.jpg +0 -0
  50. package/docs/assets/diagram/user-management-diagram-0.jpg +0 -0
  51. package/docs/assets/diagram/user-management-diagram-0.zh-TW.jpg +0 -0
  52. package/docs/assets/diagram/user-management-diagram-0.zh.jpg +0 -0
  53. package/docs/assets/diagram/user-sessions-diagram-0.ja.jpg +0 -0
  54. package/docs/assets/diagram/user-sessions-diagram-0.jpg +0 -0
  55. package/docs/assets/diagram/user-sessions-diagram-0.zh-TW.jpg +0 -0
  56. package/docs/assets/diagram/user-sessions-diagram-0.zh.jpg +0 -0
  57. package/docs/components-component-management-blocklet-studio.ja.md +0 -194
  58. package/docs/components-component-management-blocklet-studio.md +0 -194
  59. package/docs/components-component-management-blocklet-studio.zh-TW.md +0 -194
  60. package/docs/components-component-management-blocklet-studio.zh.md +0 -194
  61. package/docs/components-component-management-component-installer.ja.md +0 -182
  62. package/docs/components-component-management-component-installer.md +0 -182
  63. package/docs/components-component-management-component-installer.zh-TW.md +0 -182
  64. package/docs/components-component-management-component-installer.zh.md +0 -182
  65. package/docs/components-component-management.ja.md +0 -30
  66. package/docs/components-component-management.md +0 -30
  67. package/docs/components-component-management.zh-TW.md +0 -30
  68. package/docs/components-component-management.zh.md +0 -30
  69. package/docs/components-layout-dashboard.ja.md +0 -185
  70. package/docs/components-layout-dashboard.md +0 -187
  71. package/docs/components-layout-dashboard.zh-TW.md +0 -185
  72. package/docs/components-layout-dashboard.zh.md +0 -185
  73. package/docs/components-layout-footer.ja.md +0 -165
  74. package/docs/components-layout-footer.md +0 -165
  75. package/docs/components-layout-footer.zh-TW.md +0 -165
  76. package/docs/components-layout-footer.zh.md +0 -165
  77. package/docs/components-layout-header.ja.md +0 -183
  78. package/docs/components-layout-header.md +0 -183
  79. package/docs/components-layout-header.zh-TW.md +0 -183
  80. package/docs/components-layout-header.zh.md +0 -183
  81. package/docs/components-layout.ja.md +0 -31
  82. package/docs/components-layout.md +0 -31
  83. package/docs/components-layout.zh-TW.md +0 -31
  84. package/docs/components-layout.zh.md +0 -31
  85. package/docs/components-notifications.ja.md +0 -125
  86. package/docs/components-notifications.md +0 -125
  87. package/docs/components-notifications.zh-TW.md +0 -125
  88. package/docs/components-notifications.zh.md +0 -125
  89. package/docs/components-user-management-user-center.ja.md +0 -148
  90. package/docs/components-user-management-user-center.md +0 -147
  91. package/docs/components-user-management-user-center.zh-TW.md +0 -148
  92. package/docs/components-user-management-user-center.zh.md +0 -148
  93. package/docs/components-user-management-user-sessions.ja.md +0 -121
  94. package/docs/components-user-management-user-sessions.md +0 -123
  95. package/docs/components-user-management-user-sessions.zh-TW.md +0 -121
  96. package/docs/components-user-management-user-sessions.zh.md +0 -121
  97. package/docs/components-user-management.ja.md +0 -49
  98. package/docs/components-user-management.md +0 -51
  99. package/docs/components-user-management.zh-TW.md +0 -49
  100. package/docs/components-user-management.zh.md +0 -49
  101. package/docs/components-utilities-icon.ja.md +0 -106
  102. package/docs/components-utilities-icon.md +0 -106
  103. package/docs/components-utilities-icon.zh-TW.md +0 -106
  104. package/docs/components-utilities-icon.zh.md +0 -106
  105. package/docs/components-utilities.ja.md +0 -136
  106. package/docs/components-utilities.md +0 -136
  107. package/docs/components-utilities.zh-TW.md +0 -136
  108. package/docs/components-utilities.zh.md +0 -136
  109. package/docs/components.ja.md +0 -27
  110. package/docs/components.md +0 -27
  111. package/docs/components.zh-TW.md +0 -27
  112. package/docs/components.zh.md +0 -27
  113. package/docs/core-concepts.ja.md +0 -134
  114. package/docs/core-concepts.md +0 -135
  115. package/docs/core-concepts.zh-TW.md +0 -134
  116. package/docs/core-concepts.zh.md +0 -134
  117. package/docs/getting-started.ja.md +0 -132
  118. package/docs/getting-started.md +0 -132
  119. package/docs/getting-started.zh-TW.md +0 -132
  120. package/docs/getting-started.zh.md +0 -132
  121. package/docs/hooks-api.ja.md +0 -214
  122. package/docs/hooks-api.md +0 -214
  123. package/docs/hooks-api.zh-TW.md +0 -214
  124. package/docs/hooks-api.zh.md +0 -214
  125. package/docs/how-to-guides.ja.md +0 -413
  126. package/docs/how-to-guides.md +0 -413
  127. package/docs/how-to-guides.zh-TW.md +0 -413
  128. package/docs/how-to-guides.zh.md +0 -413
  129. package/docs/overview.ja.md +0 -51
  130. package/docs/overview.md +0 -51
  131. package/docs/overview.zh-TW.md +0 -51
  132. package/docs/overview.zh.md +0 -51
  133. package/glossary.md +0 -12
  134. package/src/@types/index.ts +0 -230
  135. package/src/@types/shims.d.ts +0 -18
  136. package/src/BlockletStudio/README.md +0 -116
  137. package/src/BlockletStudio/index.tsx +0 -145
  138. package/src/ComponentInstaller/ComponentInstaller.stories.jsx +0 -16
  139. package/src/ComponentInstaller/index.jsx +0 -207
  140. package/src/ComponentInstaller/installer-item.jsx +0 -129
  141. package/src/ComponentInstaller/locales.js +0 -22
  142. package/src/ComponentInstaller/use-component-installed.js +0 -88
  143. package/src/ComponentManager/components/add-component.tsx +0 -136
  144. package/src/ComponentManager/components/check-component.tsx +0 -3
  145. package/src/ComponentManager/components/publish-component.tsx +0 -90
  146. package/src/ComponentManager/components/resource-dialog.tsx +0 -91
  147. package/src/ComponentManager/index.tsx +0 -3
  148. package/src/ComponentManager/libs/locales.ts +0 -15
  149. package/src/Dashboard/Dashboard.stories.jsx +0 -20
  150. package/src/Dashboard/app-shell/app-badge.stories.tsx +0 -64
  151. package/src/Dashboard/app-shell/app-badge.tsx +0 -94
  152. package/src/Dashboard/app-shell/app-header.tsx +0 -104
  153. package/src/Dashboard/app-shell/app-info-context.tsx +0 -182
  154. package/src/Dashboard/app-shell/badges/app-badge-default.tsx +0 -130
  155. package/src/Dashboard/app-shell/badges/app-badge-did.tsx +0 -28
  156. package/src/Dashboard/app-shell/badges/app-badge-state.tsx +0 -40
  157. package/src/Dashboard/app-shell/badges/app-badge-switch.tsx +0 -72
  158. package/src/Dashboard/app-shell/badges/app-badge-version.tsx +0 -60
  159. package/src/Dashboard/app-shell/index.ts +0 -5
  160. package/src/Dashboard/index.jsx +0 -184
  161. package/src/Footer/Footer.stories.jsx +0 -33
  162. package/src/Footer/brand.jsx +0 -81
  163. package/src/Footer/copyright.jsx +0 -22
  164. package/src/Footer/index.jsx +0 -111
  165. package/src/Footer/internal-footer.jsx +0 -139
  166. package/src/Footer/layout/plain.jsx +0 -55
  167. package/src/Footer/layout/row.jsx +0 -43
  168. package/src/Footer/layout/standard.jsx +0 -114
  169. package/src/Footer/links.jsx +0 -321
  170. package/src/Footer/social-media.jsx +0 -55
  171. package/src/Header/Header.stories.jsx +0 -30
  172. package/src/Header/index.tsx +0 -259
  173. package/src/Icon/Icon.stories.jsx +0 -12
  174. package/src/Icon/index.tsx +0 -87
  175. package/src/Notifications/Snackbar.tsx +0 -261
  176. package/src/Notifications/hooks/use-title.tsx +0 -254
  177. package/src/Notifications/hooks/use-width.tsx +0 -16
  178. package/src/Notifications/utils.ts +0 -246
  179. package/src/UserCenter/assets/banner.png +0 -0
  180. package/src/UserCenter/components/config-inviter.tsx +0 -48
  181. package/src/UserCenter/components/config-profile.tsx +0 -99
  182. package/src/UserCenter/components/danger-zone.tsx +0 -82
  183. package/src/UserCenter/components/editable-field.tsx +0 -273
  184. package/src/UserCenter/components/fallback.tsx +0 -57
  185. package/src/UserCenter/components/nft-preview.tsx +0 -84
  186. package/src/UserCenter/components/nft.tsx +0 -279
  187. package/src/UserCenter/components/notification.tsx +0 -319
  188. package/src/UserCenter/components/passport.tsx +0 -107
  189. package/src/UserCenter/components/privacy.tsx +0 -120
  190. package/src/UserCenter/components/settings.tsx +0 -170
  191. package/src/UserCenter/components/status-dialog/date-picker.tsx +0 -77
  192. package/src/UserCenter/components/status-dialog/index.tsx +0 -293
  193. package/src/UserCenter/components/status-selector/duration-menu.tsx +0 -90
  194. package/src/UserCenter/components/status-selector/index.tsx +0 -58
  195. package/src/UserCenter/components/status-selector/menu-item.tsx +0 -56
  196. package/src/UserCenter/components/storage/action.tsx +0 -49
  197. package/src/UserCenter/components/storage/connected.tsx +0 -61
  198. package/src/UserCenter/components/storage/delete.tsx +0 -72
  199. package/src/UserCenter/components/storage/disconnect.tsx +0 -40
  200. package/src/UserCenter/components/storage/icons/empty-spaces-nft.svg +0 -1
  201. package/src/UserCenter/components/storage/icons/long-arrow.svg +0 -5
  202. package/src/UserCenter/components/storage/icons/space-connected.svg +0 -3
  203. package/src/UserCenter/components/storage/icons/space-disconnect.svg +0 -3
  204. package/src/UserCenter/components/storage/index.tsx +0 -41
  205. package/src/UserCenter/components/storage/preview-nft.tsx +0 -72
  206. package/src/UserCenter/components/third-party-login/index.tsx +0 -199
  207. package/src/UserCenter/components/third-party-login/third-party-item.tsx +0 -296
  208. package/src/UserCenter/components/user-center.tsx +0 -787
  209. package/src/UserCenter/components/user-info/address.tsx +0 -143
  210. package/src/UserCenter/components/user-info/index.tsx +0 -4
  211. package/src/UserCenter/components/user-info/link-preview-input.tsx +0 -274
  212. package/src/UserCenter/components/user-info/metadata.tsx +0 -658
  213. package/src/UserCenter/components/user-info/social-actions/chat.tsx +0 -43
  214. package/src/UserCenter/components/user-info/social-actions/follow.tsx +0 -23
  215. package/src/UserCenter/components/user-info/social-actions/index.tsx +0 -17
  216. package/src/UserCenter/components/user-info/switch-role.tsx +0 -42
  217. package/src/UserCenter/components/user-info/timezone-select.tsx +0 -119
  218. package/src/UserCenter/components/user-info/user-basic-info.tsx +0 -292
  219. package/src/UserCenter/components/user-info/user-info-item.tsx +0 -54
  220. package/src/UserCenter/components/user-info/user-info.tsx +0 -91
  221. package/src/UserCenter/components/user-info/user-status.tsx +0 -234
  222. package/src/UserCenter/components/user-info/utils.ts +0 -320
  223. package/src/UserCenter/components/webhook-item.tsx +0 -248
  224. package/src/UserCenter/index.tsx +0 -1
  225. package/src/UserCenter/libs/locales.ts +0 -378
  226. package/src/UserCenter/libs/utils.ts +0 -30
  227. package/src/UserSessions/components/user-session-info.tsx +0 -78
  228. package/src/UserSessions/components/user-sessions.tsx +0 -545
  229. package/src/UserSessions/index.tsx +0 -1
  230. package/src/UserSessions/libs/locales.ts +0 -60
  231. package/src/UserSessions/libs/utils.ts +0 -82
  232. package/src/blocklets.js +0 -195
  233. package/src/common/domain-warning.jsx +0 -178
  234. package/src/common/header-addons.jsx +0 -119
  235. package/src/common/link-blocker.jsx +0 -20
  236. package/src/common/notification-addon.jsx +0 -135
  237. package/src/common/org-switch/avatar-uploader.jsx +0 -271
  238. package/src/common/org-switch/create.jsx +0 -267
  239. package/src/common/org-switch/index.jsx +0 -407
  240. package/src/common/org-switch/locales.js +0 -52
  241. package/src/common/org-switch/use-org.jsx +0 -79
  242. package/src/common/overridable-theme-provider.jsx +0 -17
  243. package/src/common/wallet-hidden-topbar.js +0 -14
  244. package/src/common/wizard-modal.jsx +0 -200
  245. package/src/common/ws.js +0 -68
  246. package/src/contexts/config-user-space.tsx +0 -88
  247. package/src/contexts/user-followers.tsx +0 -54
  248. package/src/hooks/use-follow.tsx +0 -75
  249. package/src/hooks/use-mobile.tsx +0 -6
  250. package/src/index.ts +0 -16
  251. package/src/libs/constant.ts +0 -1
  252. package/src/libs/spaces.tsx +0 -18
  253. package/src/libs/with-hide-when-embed.tsx +0 -24
  254. package/src/types.js +0 -45
  255. package/src/utils.js +0 -161
  256. 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
- };