@blocklet/ui-react 2.12.8 → 2.12.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/@types/index.d.ts +34 -0
- package/lib/@types/index.js +16 -0
- package/lib/@types/shims.d.ts +1 -0
- package/lib/UserCenter/components/config-profile.js +23 -1
- package/lib/UserCenter/components/editable-field.d.ts +22 -0
- package/lib/UserCenter/components/editable-field.js +159 -0
- package/lib/UserCenter/components/nft.d.ts +4 -0
- package/lib/UserCenter/components/nft.js +93 -0
- package/lib/UserCenter/components/settings.js +32 -15
- package/lib/UserCenter/components/status-selector/duration-menu.d.ts +9 -0
- package/lib/UserCenter/components/status-selector/duration-menu.js +75 -0
- package/lib/UserCenter/components/status-selector/index.d.ts +9 -0
- package/lib/UserCenter/components/status-selector/index.js +39 -0
- package/lib/UserCenter/components/status-selector/menu-item.d.ts +24 -0
- package/lib/UserCenter/components/status-selector/menu-item.js +24 -0
- package/lib/UserCenter/components/user-center.js +119 -122
- package/lib/UserCenter/components/user-info/clock.d.ts +4 -0
- package/lib/UserCenter/components/user-info/clock.js +23 -0
- package/lib/UserCenter/components/user-info/link-preview-input.d.ts +5 -0
- package/lib/UserCenter/components/user-info/link-preview-input.js +181 -0
- package/lib/UserCenter/components/user-info/metadata.d.ts +7 -0
- package/lib/UserCenter/components/user-info/metadata.js +458 -0
- package/lib/UserCenter/components/user-info/switch-role.js +2 -3
- package/lib/UserCenter/components/user-info/user-basic-info.d.ts +2 -0
- package/lib/UserCenter/components/user-info/user-basic-info.js +159 -90
- package/lib/UserCenter/components/user-info/user-info.js +2 -16
- package/lib/UserCenter/components/user-info/user-status.d.ts +8 -0
- package/lib/UserCenter/components/user-info/user-status.js +153 -0
- package/lib/UserCenter/components/user-info/utils.d.ts +19 -0
- package/lib/UserCenter/components/user-info/utils.js +86 -0
- package/lib/UserCenter/libs/locales.d.ts +65 -0
- package/lib/UserCenter/libs/locales.js +67 -2
- package/lib/UserSessions/components/user-sessions.js +48 -14
- package/package.json +8 -5
- package/src/@types/index.ts +39 -0
- package/src/@types/shims.d.ts +1 -0
- package/src/UserCenter/components/config-profile.tsx +20 -1
- package/src/UserCenter/components/editable-field.tsx +180 -0
- package/src/UserCenter/components/nft.tsx +122 -0
- package/src/UserCenter/components/settings.tsx +16 -4
- package/src/UserCenter/components/status-selector/duration-menu.tsx +87 -0
- package/src/UserCenter/components/status-selector/index.tsx +52 -0
- package/src/UserCenter/components/status-selector/menu-item.tsx +52 -0
- package/src/UserCenter/components/user-center.tsx +104 -103
- package/src/UserCenter/components/user-info/clock.tsx +29 -0
- package/src/UserCenter/components/user-info/link-preview-input.tsx +227 -0
- package/src/UserCenter/components/user-info/metadata.tsx +465 -0
- package/src/UserCenter/components/user-info/switch-role.tsx +3 -3
- package/src/UserCenter/components/user-info/user-basic-info.tsx +150 -87
- package/src/UserCenter/components/user-info/user-info.tsx +6 -16
- package/src/UserCenter/components/user-info/user-status.tsx +182 -0
- package/src/UserCenter/components/user-info/utils.ts +114 -0
- package/src/UserCenter/libs/locales.ts +65 -0
- package/src/UserSessions/components/user-sessions.tsx +68 -18
|
@@ -39,7 +39,10 @@ export declare const translations: {
|
|
|
39
39
|
required: string;
|
|
40
40
|
invalid: string;
|
|
41
41
|
setting: string;
|
|
42
|
+
save: string;
|
|
42
43
|
profile: string;
|
|
44
|
+
nft: string;
|
|
45
|
+
noNFT: string;
|
|
43
46
|
};
|
|
44
47
|
toPublic: string;
|
|
45
48
|
currentPassport: string;
|
|
@@ -94,6 +97,35 @@ export declare const translations: {
|
|
|
94
97
|
title: string;
|
|
95
98
|
locale: string;
|
|
96
99
|
};
|
|
100
|
+
userStatus: {
|
|
101
|
+
Online: string;
|
|
102
|
+
Meeting: string;
|
|
103
|
+
Community: string;
|
|
104
|
+
Holiday: string;
|
|
105
|
+
OffSick: string;
|
|
106
|
+
WorkingRemotely: string;
|
|
107
|
+
duration: {
|
|
108
|
+
ThirtyMinutes: string;
|
|
109
|
+
OneHour: string;
|
|
110
|
+
FourHours: string;
|
|
111
|
+
Today: string;
|
|
112
|
+
ThisWeek: string;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
profile: {
|
|
116
|
+
addLink: string;
|
|
117
|
+
location: string;
|
|
118
|
+
timezone: string;
|
|
119
|
+
setStatus: string;
|
|
120
|
+
localTime: string;
|
|
121
|
+
email: string;
|
|
122
|
+
emailInvalid: string;
|
|
123
|
+
phone: string;
|
|
124
|
+
phoneInvalid: string;
|
|
125
|
+
editProfile: string;
|
|
126
|
+
removeStatusAfter: string;
|
|
127
|
+
justForYou: string;
|
|
128
|
+
};
|
|
97
129
|
};
|
|
98
130
|
en: {
|
|
99
131
|
settings: string;
|
|
@@ -135,7 +167,10 @@ export declare const translations: {
|
|
|
135
167
|
required: string;
|
|
136
168
|
invalid: string;
|
|
137
169
|
setting: string;
|
|
170
|
+
save: string;
|
|
138
171
|
profile: string;
|
|
172
|
+
nft: string;
|
|
173
|
+
noNFT: string;
|
|
139
174
|
};
|
|
140
175
|
toPublic: string;
|
|
141
176
|
currentPassport: string;
|
|
@@ -190,5 +225,35 @@ export declare const translations: {
|
|
|
190
225
|
title: string;
|
|
191
226
|
locale: string;
|
|
192
227
|
};
|
|
228
|
+
userStatus: {
|
|
229
|
+
Online: string;
|
|
230
|
+
Meeting: string;
|
|
231
|
+
Community: string;
|
|
232
|
+
Holiday: string;
|
|
233
|
+
OffSick: string;
|
|
234
|
+
WorkingRemotely: string;
|
|
235
|
+
duration: {
|
|
236
|
+
ThirtyMinutes: string;
|
|
237
|
+
OneHour: string;
|
|
238
|
+
FourHours: string;
|
|
239
|
+
Today: string;
|
|
240
|
+
ThisWeek: string;
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
profile: {
|
|
244
|
+
addLink: string;
|
|
245
|
+
location: string;
|
|
246
|
+
timezone: string;
|
|
247
|
+
setStatus: string;
|
|
248
|
+
localTime: string;
|
|
249
|
+
email: string;
|
|
250
|
+
emailInvalid: string;
|
|
251
|
+
phone: string;
|
|
252
|
+
phoneInvalid: string;
|
|
253
|
+
editProfile: string;
|
|
254
|
+
removeStatusAfter: string;
|
|
255
|
+
justForYou: string;
|
|
256
|
+
maxInputLength: string;
|
|
257
|
+
};
|
|
193
258
|
};
|
|
194
259
|
};
|
|
@@ -39,7 +39,10 @@ export const translations = {
|
|
|
39
39
|
required: "\u5FC5\u586B\u7684",
|
|
40
40
|
invalid: "\u65E0\u6548",
|
|
41
41
|
setting: "\u8BBE\u7F6E",
|
|
42
|
-
|
|
42
|
+
save: "\u4FDD\u5B58",
|
|
43
|
+
profile: "\u4FE1\u606F",
|
|
44
|
+
nft: "NFTs",
|
|
45
|
+
noNFT: "\u6682\u65E0 NFT"
|
|
43
46
|
},
|
|
44
47
|
toPublic: "\u516C\u5F00 \u201C{name}\u201D \u9875\u9762",
|
|
45
48
|
currentPassport: "\u5F53\u524D\u4F7F\u7528\u7684\u901A\u884C\u8BC1",
|
|
@@ -93,6 +96,35 @@ export const translations = {
|
|
|
93
96
|
commonSetting: {
|
|
94
97
|
title: "\u901A\u7528\u8BBE\u7F6E",
|
|
95
98
|
locale: "\u504F\u597D\u8BED\u8A00"
|
|
99
|
+
},
|
|
100
|
+
userStatus: {
|
|
101
|
+
Online: "\u5728\u7EBF",
|
|
102
|
+
Meeting: "\u5F00\u4F1A\u4E2D",
|
|
103
|
+
Community: "\u901A\u52E4\u4E2D",
|
|
104
|
+
Holiday: "\u4F11\u5047",
|
|
105
|
+
OffSick: "\u75C5\u5047",
|
|
106
|
+
WorkingRemotely: "\u8FDC\u7A0B\u5DE5\u4F5C",
|
|
107
|
+
duration: {
|
|
108
|
+
ThirtyMinutes: "30\u5206\u949F",
|
|
109
|
+
OneHour: "1\u5C0F\u65F6",
|
|
110
|
+
FourHours: "4\u5C0F\u65F6",
|
|
111
|
+
Today: "\u4ECA\u5929",
|
|
112
|
+
ThisWeek: "\u672C\u5468"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
profile: {
|
|
116
|
+
addLink: "\u6DFB\u52A0\u8FDE\u63A5",
|
|
117
|
+
location: "\u4F4D\u7F6E",
|
|
118
|
+
timezone: "\u65F6\u533A",
|
|
119
|
+
setStatus: "\u8BBE\u7F6E\u72B6\u6001",
|
|
120
|
+
localTime: "\u5F53\u5730\u65F6\u95F4:",
|
|
121
|
+
email: "\u90AE\u7BB1\u5730\u5740",
|
|
122
|
+
emailInvalid: "\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E",
|
|
123
|
+
phone: "\u7535\u8BDD\u53F7\u7801",
|
|
124
|
+
phoneInvalid: "\u7535\u8BDD\u53F7\u7801\u683C\u5F0F\u4E0D\u6B63\u786E",
|
|
125
|
+
editProfile: "\u7F16\u8F91\u8D44\u6599",
|
|
126
|
+
removeStatusAfter: "\u79FB\u9664\u72B6\u6001",
|
|
127
|
+
justForYou: "\u4EC5\u5BF9\u60A8\u53EF\u89C1"
|
|
96
128
|
}
|
|
97
129
|
},
|
|
98
130
|
en: {
|
|
@@ -135,7 +167,10 @@ export const translations = {
|
|
|
135
167
|
required: "Required",
|
|
136
168
|
invalid: "Invalid",
|
|
137
169
|
setting: "Settings",
|
|
138
|
-
|
|
170
|
+
save: "Save",
|
|
171
|
+
profile: "Profile",
|
|
172
|
+
nft: "NFTs",
|
|
173
|
+
noNFT: "No NFT"
|
|
139
174
|
},
|
|
140
175
|
toPublic: 'Public "{name}" page',
|
|
141
176
|
currentPassport: "Passport currently in use",
|
|
@@ -189,6 +224,36 @@ export const translations = {
|
|
|
189
224
|
commonSetting: {
|
|
190
225
|
title: "Common Settings",
|
|
191
226
|
locale: "Preferred language"
|
|
227
|
+
},
|
|
228
|
+
userStatus: {
|
|
229
|
+
Online: "Online",
|
|
230
|
+
Meeting: "In a Meeting",
|
|
231
|
+
Community: "Commuting",
|
|
232
|
+
Holiday: "On Holiday",
|
|
233
|
+
OffSick: "Off Sick",
|
|
234
|
+
WorkingRemotely: "Working Remotely",
|
|
235
|
+
duration: {
|
|
236
|
+
ThirtyMinutes: "30 minutes",
|
|
237
|
+
OneHour: "1 hour",
|
|
238
|
+
FourHours: "4 hours",
|
|
239
|
+
Today: "Today",
|
|
240
|
+
ThisWeek: "This Week"
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
profile: {
|
|
244
|
+
addLink: "Add link",
|
|
245
|
+
location: "Location",
|
|
246
|
+
timezone: "Timezone",
|
|
247
|
+
setStatus: "Set a Status",
|
|
248
|
+
localTime: "Local Time: ",
|
|
249
|
+
email: "Email",
|
|
250
|
+
emailInvalid: "Email is invalid",
|
|
251
|
+
phone: "Phone",
|
|
252
|
+
phoneInvalid: "Phone number is invalid",
|
|
253
|
+
editProfile: "Edit Profile",
|
|
254
|
+
removeStatusAfter: "Remove status after",
|
|
255
|
+
justForYou: "Visible to you only",
|
|
256
|
+
maxInputLength: "Max input length is"
|
|
192
257
|
}
|
|
193
258
|
}
|
|
194
259
|
};
|
|
@@ -8,6 +8,7 @@ import sortBy from "lodash/sortBy";
|
|
|
8
8
|
import UAParser from "ua-parser-js";
|
|
9
9
|
import { getVisitorId } from "@arcblock/ux/lib/Util";
|
|
10
10
|
import { useConfirm } from "@arcblock/ux/lib/Dialog";
|
|
11
|
+
import { temp as colors } from "@arcblock/ux/lib/Colors";
|
|
11
12
|
import pAll from "p-all";
|
|
12
13
|
import PQueue from "p-queue";
|
|
13
14
|
import { Box, Button, CircularProgress, Tooltip, Typography, useMediaQuery } from "@mui/material";
|
|
@@ -27,7 +28,7 @@ const parseUa = (ua) => {
|
|
|
27
28
|
return result;
|
|
28
29
|
};
|
|
29
30
|
const queue = new PQueue({ concurrency: 1 });
|
|
30
|
-
const UserSessionIp = memo(({ userSession }) => {
|
|
31
|
+
const UserSessionIp = memo(({ userSession, isMobile = false }) => {
|
|
31
32
|
const currentState = useReactive({
|
|
32
33
|
loading: true,
|
|
33
34
|
ipRegion: ""
|
|
@@ -42,7 +43,7 @@ const UserSessionIp = memo(({ userSession }) => {
|
|
|
42
43
|
}
|
|
43
44
|
});
|
|
44
45
|
}, [currentState, userSession.lastLoginIp]);
|
|
45
|
-
return /* @__PURE__ */ jsx(Box, { children: currentState.ipRegion ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
46
|
+
return /* @__PURE__ */ jsx(Box, { ...isMobile && { display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 1 }, children: currentState.ipRegion ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
46
47
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: currentState.ipRegion }),
|
|
47
48
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "grey", children: userSession.lastLoginIp || t("unknown") })
|
|
48
49
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -165,7 +166,7 @@ export default function UserSessions({
|
|
|
165
166
|
customBodyRenderLite: (rawIndex) => {
|
|
166
167
|
const x = safeData[rawIndex];
|
|
167
168
|
const result = parseUa(x.ua);
|
|
168
|
-
return /* @__PURE__ */ jsx(Box, { children: [result.os?.name, result.os?.version].filter(Boolean).join("/") || t("unknown") });
|
|
169
|
+
return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: [result.os?.name, result.os?.version].filter(Boolean).join("/") || t("unknown") });
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
},
|
|
@@ -176,7 +177,7 @@ export default function UserSessions({
|
|
|
176
177
|
customBodyRenderLite: (rawIndex) => {
|
|
177
178
|
const x = safeData[rawIndex];
|
|
178
179
|
const result = parseUa(x.ua);
|
|
179
|
-
return /* @__PURE__ */ jsx(Box, { children: [result.browser?.name, result.browser?.version].filter(Boolean).join("/") || t("unknown") });
|
|
180
|
+
return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: [result.browser?.name, result.browser?.version].filter(Boolean).join("/") || t("unknown") });
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
183
|
},
|
|
@@ -186,7 +187,7 @@ export default function UserSessions({
|
|
|
186
187
|
options: {
|
|
187
188
|
customBodyRenderLite: (rawIndex) => {
|
|
188
189
|
const x = safeData[rawIndex];
|
|
189
|
-
return /* @__PURE__ */ jsx(Box, { children: x.extra?.walletOS || t("unknown") });
|
|
190
|
+
return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: x.extra?.walletOS || t("unknown") });
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
},
|
|
@@ -196,7 +197,7 @@ export default function UserSessions({
|
|
|
196
197
|
options: {
|
|
197
198
|
customBodyRenderLite: (rawIndex) => {
|
|
198
199
|
const x = safeData[rawIndex];
|
|
199
|
-
return /* @__PURE__ */ jsx(Box, { sx: { minWidth: 150, maxWidth: 250 }, children: /* @__PURE__ */ jsx(UserSessionInfo, { sessionUser: x.user, user }) });
|
|
200
|
+
return /* @__PURE__ */ jsx(Box, { sx: { minWidth: 150, maxWidth: 250, ...isMobile && { textAlign: "right" } }, children: /* @__PURE__ */ jsx(UserSessionInfo, { sessionUser: x.user, user }) });
|
|
200
201
|
}
|
|
201
202
|
}
|
|
202
203
|
},
|
|
@@ -206,7 +207,7 @@ export default function UserSessions({
|
|
|
206
207
|
options: {
|
|
207
208
|
customBodyRenderLite: (rawIndex) => {
|
|
208
209
|
const x = safeData[rawIndex];
|
|
209
|
-
return x.createdAt ? /* @__PURE__ */ jsx(RelativeTime, { value: x.createdAt, relativeRange: 3 * 86400 * 1e3, locale }) : t("unknown");
|
|
210
|
+
return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: x.createdAt ? /* @__PURE__ */ jsx(RelativeTime, { value: x.createdAt, relativeRange: 3 * 86400 * 1e3, locale }) : t("unknown") });
|
|
210
211
|
}
|
|
211
212
|
}
|
|
212
213
|
},
|
|
@@ -216,7 +217,7 @@ export default function UserSessions({
|
|
|
216
217
|
options: {
|
|
217
218
|
customBodyRenderLite: (rawIndex) => {
|
|
218
219
|
const x = safeData[rawIndex];
|
|
219
|
-
return x.status === "expired" ? t("expired") : /* @__PURE__ */ jsx(RelativeTime, { value: x.updatedAt, relativeRange: 3 * 86400 * 1e3, locale });
|
|
220
|
+
return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: x.status === "expired" ? t("expired") : /* @__PURE__ */ jsx(RelativeTime, { value: x.updatedAt, relativeRange: 3 * 86400 * 1e3, locale }) });
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
223
|
},
|
|
@@ -226,7 +227,7 @@ export default function UserSessions({
|
|
|
226
227
|
options: {
|
|
227
228
|
customBodyRenderLite: (rawIndex) => {
|
|
228
229
|
const x = safeData[rawIndex];
|
|
229
|
-
return /* @__PURE__ */ jsx(UserSessionIp, { userSession: x });
|
|
230
|
+
return /* @__PURE__ */ jsx(UserSessionIp, { userSession: x, isMobile });
|
|
230
231
|
}
|
|
231
232
|
}
|
|
232
233
|
},
|
|
@@ -236,12 +237,13 @@ export default function UserSessions({
|
|
|
236
237
|
options: {
|
|
237
238
|
customBodyRenderLite: (rawIndex) => {
|
|
238
239
|
const x = safeData[rawIndex];
|
|
239
|
-
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
240
|
+
return /* @__PURE__ */ jsx(Box, { sx: isMobile ? { textAlign: "right" } : {}, children: /* @__PURE__ */ jsx(
|
|
240
241
|
Button,
|
|
241
242
|
{
|
|
242
243
|
sx: {
|
|
243
244
|
whiteSpace: "nowrap",
|
|
244
|
-
fontSize: "12px",
|
|
245
|
+
fontSize: "12px !important",
|
|
246
|
+
lineHeight: "1.25",
|
|
245
247
|
px: 1
|
|
246
248
|
},
|
|
247
249
|
disabled: currentVisitorId === x.visitorId,
|
|
@@ -259,14 +261,45 @@ export default function UserSessions({
|
|
|
259
261
|
return /* @__PURE__ */ jsxs(
|
|
260
262
|
Box,
|
|
261
263
|
{
|
|
264
|
+
className: "pc-user-sessions",
|
|
262
265
|
sx: {
|
|
263
|
-
maxWidth: isMobile ? "unset" : isLg ? "calc(100vw - 300px)" : "
|
|
266
|
+
maxWidth: isMobile ? "unset" : isLg ? "calc(100vw - 300px)" : "100%",
|
|
267
|
+
...isMobile && {
|
|
268
|
+
".pc-user-sessions-table > div:nth-child(2)": {
|
|
269
|
+
border: `1px solid ${colors.dividerColor}`,
|
|
270
|
+
borderRadius: "8px"
|
|
271
|
+
}
|
|
272
|
+
},
|
|
264
273
|
".MuiTableCell-head": {
|
|
265
274
|
whiteSpace: "nowrap",
|
|
266
275
|
fontWeight: "bold"
|
|
267
276
|
},
|
|
277
|
+
".MuiTableRow-root": {
|
|
278
|
+
border: "unset",
|
|
279
|
+
"&:nth-child(even)": {
|
|
280
|
+
backgroundColor: "#F9FAFB",
|
|
281
|
+
"&:hover": {
|
|
282
|
+
backgroundColor: "#F9FAFB !important"
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
".MuiTableRow-hover": {
|
|
287
|
+
"&:hover": {
|
|
288
|
+
backgroundColor: "inherit !important"
|
|
289
|
+
}
|
|
290
|
+
},
|
|
268
291
|
".MuiTableCell-root": {
|
|
269
|
-
paddingRight: "8px"
|
|
292
|
+
paddingRight: "8px",
|
|
293
|
+
paddingLeft: "8px",
|
|
294
|
+
...isMobile && {
|
|
295
|
+
padding: "8px !important",
|
|
296
|
+
"&:first-child": {
|
|
297
|
+
paddingTop: "20px!important"
|
|
298
|
+
},
|
|
299
|
+
"&:last-child": {
|
|
300
|
+
paddingBottom: "20px!important"
|
|
301
|
+
}
|
|
302
|
+
}
|
|
270
303
|
}
|
|
271
304
|
},
|
|
272
305
|
children: [
|
|
@@ -279,7 +312,8 @@ export default function UserSessions({
|
|
|
279
312
|
columns,
|
|
280
313
|
customButtons,
|
|
281
314
|
options: tableOptions,
|
|
282
|
-
loading: pageState.loading
|
|
315
|
+
loading: pageState.loading,
|
|
316
|
+
className: "pc-user-sessions-table"
|
|
283
317
|
}
|
|
284
318
|
)
|
|
285
319
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/ui-react",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.10",
|
|
4
4
|
"description": "Some useful front-end web components that can be used in Blocklets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@abtnode/constant": "^1.16.39",
|
|
36
|
-
"@arcblock/bridge": "^2.12.
|
|
37
|
-
"@arcblock/react-hooks": "^2.12.
|
|
36
|
+
"@arcblock/bridge": "^2.12.10",
|
|
37
|
+
"@arcblock/react-hooks": "^2.12.10",
|
|
38
38
|
"@arcblock/ws": "^1.19.15",
|
|
39
39
|
"@blocklet/did-space-react": "^1.0.26",
|
|
40
40
|
"@iconify-icons/logos": "^1.2.36",
|
|
@@ -44,11 +44,13 @@
|
|
|
44
44
|
"axios": "^1.7.5",
|
|
45
45
|
"clsx": "^2.1.0",
|
|
46
46
|
"core-js": "^3.25.5",
|
|
47
|
+
"dayjs": "^1.11.5",
|
|
47
48
|
"iconify-icon": "^1.0.8",
|
|
48
49
|
"iconify-icons-material-symbols-400": "^0.0.1",
|
|
49
50
|
"is-url": "^1.2.4",
|
|
50
51
|
"js-cookie": "^2.2.1",
|
|
51
52
|
"lodash": "^4.17.21",
|
|
53
|
+
"moment-timezone": "^0.5.37",
|
|
52
54
|
"p-all": "^5.0.0",
|
|
53
55
|
"p-queue": "^6.6.2",
|
|
54
56
|
"p-wait-for": "^5.0.2",
|
|
@@ -57,7 +59,8 @@
|
|
|
57
59
|
"react-placeholder": "^4.1.0",
|
|
58
60
|
"type-fest": "^4.22.0",
|
|
59
61
|
"ua-parser-js": "^1.0.37",
|
|
60
|
-
"ufo": "^1.5.3"
|
|
62
|
+
"ufo": "^1.5.3",
|
|
63
|
+
"validator": "^13.9.0"
|
|
61
64
|
},
|
|
62
65
|
"peerDependencies": {
|
|
63
66
|
"@arcblock/did-connect": "^2.11.48",
|
|
@@ -84,5 +87,5 @@
|
|
|
84
87
|
"jest": "^29.7.0",
|
|
85
88
|
"unbuild": "^2.0.0"
|
|
86
89
|
},
|
|
87
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "a4e740e658ec69a4889872ce0c4f1ef6746fa57b"
|
|
88
91
|
}
|
package/src/@types/index.ts
CHANGED
|
@@ -44,6 +44,44 @@ export type NFTAccount = {
|
|
|
44
44
|
|
|
45
45
|
export type ConnectedAccount = OAuthAccount | WalletAccount | NFTAccount;
|
|
46
46
|
|
|
47
|
+
export type UserMetadataLink = {
|
|
48
|
+
url: string;
|
|
49
|
+
favicon?: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export enum DurationEnum {
|
|
53
|
+
ThirtyMinutes = '30_minutes',
|
|
54
|
+
OneHour = '1_hour',
|
|
55
|
+
FourHours = '4_hours',
|
|
56
|
+
Today = 'today',
|
|
57
|
+
ThisWeek = 'this_week',
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export enum StatusEnum {
|
|
61
|
+
Meeting = 'meeting',
|
|
62
|
+
Community = 'community',
|
|
63
|
+
Holiday = 'holiday',
|
|
64
|
+
OffSick = 'off_sick',
|
|
65
|
+
WorkingRemotely = 'working_remotely',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type UserMetadata = {
|
|
69
|
+
bio?: string;
|
|
70
|
+
location?: string;
|
|
71
|
+
timezone?: string;
|
|
72
|
+
joinedAt?: string;
|
|
73
|
+
status?: {
|
|
74
|
+
value: string;
|
|
75
|
+
duration?: DurationEnum;
|
|
76
|
+
dateRange?: Date[];
|
|
77
|
+
};
|
|
78
|
+
links?: UserMetadataLink[];
|
|
79
|
+
cover?: string;
|
|
80
|
+
// 这两个字段是 User, 方便数据更新,在保存时同步
|
|
81
|
+
email?: string;
|
|
82
|
+
phone?: string;
|
|
83
|
+
};
|
|
84
|
+
|
|
47
85
|
export type User = UserPublicInfo & {
|
|
48
86
|
role: string;
|
|
49
87
|
email?: string;
|
|
@@ -61,6 +99,7 @@ export type User = UserPublicInfo & {
|
|
|
61
99
|
inviter?: string;
|
|
62
100
|
emailVerified?: boolean;
|
|
63
101
|
phoneVerified?: boolean;
|
|
102
|
+
metadata?: UserMetadata;
|
|
64
103
|
};
|
|
65
104
|
|
|
66
105
|
export type UserCenterTab = {
|
package/src/@types/shims.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { useMemoizedFn, useReactive } from 'ahooks';
|
|
|
3
3
|
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
4
4
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
5
5
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
6
|
+
import { temp as colors } from '@arcblock/ux/lib/Colors';
|
|
7
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
8
|
+
import ArrowDownwardIcon from '@arcblock/icons/lib/ArrowDown';
|
|
6
9
|
|
|
7
10
|
import { translations } from '../libs/locales';
|
|
8
11
|
import { client } from '../../libs/client';
|
|
@@ -60,7 +63,23 @@ export default function ConfigProfile({ user, onSave }: { user: User; onSave: (t
|
|
|
60
63
|
height: 2,
|
|
61
64
|
}}
|
|
62
65
|
/>
|
|
63
|
-
<Select
|
|
66
|
+
<Select
|
|
67
|
+
value={currentState.locale}
|
|
68
|
+
onChange={handleChange}
|
|
69
|
+
size="small"
|
|
70
|
+
// eslint-disable-next-line react/no-unstable-nested-components
|
|
71
|
+
IconComponent={(props) => <ArrowDownwardIcon {...props} width={20} height={20} />}
|
|
72
|
+
sx={{
|
|
73
|
+
minWidth: 300,
|
|
74
|
+
'&:hover': {
|
|
75
|
+
'fieldset.MuiOutlinedInput-notchedOutline': {
|
|
76
|
+
borderColor: colors.dividerColor,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
fieldset: {
|
|
80
|
+
borderColor: colors.dividerColor,
|
|
81
|
+
},
|
|
82
|
+
}}>
|
|
64
83
|
{(window.blocklet.languages || languages).map((x: { name: string; code: string }) => (
|
|
65
84
|
<MenuItem value={x.code} key={x.code}>
|
|
66
85
|
{x.name}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, TextField, Typography, Tooltip, TooltipProps } from '@mui/material';
|
|
3
|
+
import { useCreation, useMemoizedFn } from 'ahooks';
|
|
4
|
+
import { temp as colors } from '@arcblock/ux/lib/Colors';
|
|
5
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
6
|
+
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
7
|
+
import VerifiedIcon from '@mui/icons-material/Verified';
|
|
8
|
+
import { translations } from '../libs/locales';
|
|
9
|
+
|
|
10
|
+
interface EditableFieldProps {
|
|
11
|
+
value: string;
|
|
12
|
+
onChange?: (value: string) => void;
|
|
13
|
+
onValueValidate?: (value: string) => void;
|
|
14
|
+
editable: boolean;
|
|
15
|
+
component?: 'input' | 'textarea';
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
rows?: number;
|
|
18
|
+
maxLength?: number; // 最大字符数
|
|
19
|
+
icon?: React.ReactNode;
|
|
20
|
+
label?: string;
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
tooltip?: TooltipProps['title'];
|
|
23
|
+
inline?: boolean;
|
|
24
|
+
style?: React.CSSProperties;
|
|
25
|
+
verified?: boolean;
|
|
26
|
+
errorMsg?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const inputFieldStyle = {
|
|
30
|
+
width: '100%',
|
|
31
|
+
'.MuiOutlinedInput-root': {
|
|
32
|
+
'&:hover': {
|
|
33
|
+
fieldset: {
|
|
34
|
+
borderColor: colors.dividerColor,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
'&.Mui-focused': {
|
|
38
|
+
fieldset: {
|
|
39
|
+
borderColor: colors.dividerColor,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
fieldset: {
|
|
45
|
+
borderColor: colors.dividerColor,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function EditableField({
|
|
50
|
+
value,
|
|
51
|
+
onChange = () => {},
|
|
52
|
+
onValueValidate = () => {},
|
|
53
|
+
errorMsg = '',
|
|
54
|
+
editable = false,
|
|
55
|
+
component = 'input',
|
|
56
|
+
placeholder = '',
|
|
57
|
+
rows = 2,
|
|
58
|
+
maxLength,
|
|
59
|
+
icon,
|
|
60
|
+
label = '',
|
|
61
|
+
children,
|
|
62
|
+
tooltip,
|
|
63
|
+
inline = true,
|
|
64
|
+
style = {},
|
|
65
|
+
verified = false,
|
|
66
|
+
}: EditableFieldProps) {
|
|
67
|
+
const { locale } = useLocaleContext();
|
|
68
|
+
const t = useMemoizedFn((key, data = {}) => {
|
|
69
|
+
return translate(translations, key, locale, 'en', data);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const handleChange = useMemoizedFn((v: string) => {
|
|
73
|
+
if (onChange) {
|
|
74
|
+
onChange(v);
|
|
75
|
+
}
|
|
76
|
+
if (onValueValidate) {
|
|
77
|
+
onValueValidate(v);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const content = useCreation(() => {
|
|
82
|
+
if (children) {
|
|
83
|
+
return children;
|
|
84
|
+
}
|
|
85
|
+
if (component === 'input') {
|
|
86
|
+
return (
|
|
87
|
+
<TextField
|
|
88
|
+
variant="outlined"
|
|
89
|
+
className="editable-field"
|
|
90
|
+
InputProps={{
|
|
91
|
+
sx: { backgroundColor: 'transparent' },
|
|
92
|
+
placeholder,
|
|
93
|
+
}}
|
|
94
|
+
value={value}
|
|
95
|
+
onChange={(e) => handleChange(e.target.value)}
|
|
96
|
+
sx={inputFieldStyle}
|
|
97
|
+
error={Boolean(errorMsg)}
|
|
98
|
+
helperText={errorMsg}
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const isTooLong = value.length > (maxLength || 300);
|
|
104
|
+
return (
|
|
105
|
+
<Box position="relative">
|
|
106
|
+
<TextField
|
|
107
|
+
variant="outlined"
|
|
108
|
+
InputProps={{
|
|
109
|
+
multiline: true,
|
|
110
|
+
minRows: rows,
|
|
111
|
+
placeholder,
|
|
112
|
+
}}
|
|
113
|
+
sx={inputFieldStyle}
|
|
114
|
+
value={value}
|
|
115
|
+
onChange={(e) => handleChange(e.target.value)}
|
|
116
|
+
error={Boolean(errorMsg)}
|
|
117
|
+
helperText={errorMsg}
|
|
118
|
+
/>
|
|
119
|
+
<Typography
|
|
120
|
+
position="absolute"
|
|
121
|
+
bottom={-22}
|
|
122
|
+
right={2}
|
|
123
|
+
variant="caption"
|
|
124
|
+
fontSize="12px"
|
|
125
|
+
component="span"
|
|
126
|
+
color={isTooLong ? 'error' : 'text.secondary'}>
|
|
127
|
+
{isTooLong ? `(${t('profile.maxInputLength')} ${maxLength}) ` : ''}
|
|
128
|
+
{value.length} / {maxLength}
|
|
129
|
+
</Typography>
|
|
130
|
+
</Box>
|
|
131
|
+
);
|
|
132
|
+
}, [value, handleChange, component, placeholder, rows, children]);
|
|
133
|
+
|
|
134
|
+
if (!editable) {
|
|
135
|
+
return value ? (
|
|
136
|
+
<Tooltip title={tooltip} placement="top">
|
|
137
|
+
<Typography
|
|
138
|
+
variant="subtitle1"
|
|
139
|
+
component="p"
|
|
140
|
+
gutterBottom
|
|
141
|
+
sx={{
|
|
142
|
+
width: '100%',
|
|
143
|
+
mb: 0,
|
|
144
|
+
lineHeight: 1.4,
|
|
145
|
+
overflow: 'hidden',
|
|
146
|
+
}}
|
|
147
|
+
display="flex"
|
|
148
|
+
alignItems="center"
|
|
149
|
+
gap={1}>
|
|
150
|
+
{icon}
|
|
151
|
+
<Box display="flex" flexDirection="row" alignItems="center" width="90%">
|
|
152
|
+
<Typography
|
|
153
|
+
sx={{
|
|
154
|
+
whiteSpace: 'pre-wrap',
|
|
155
|
+
...(inline ? { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } : {}),
|
|
156
|
+
}}>
|
|
157
|
+
{value}
|
|
158
|
+
</Typography>
|
|
159
|
+
{verified && (
|
|
160
|
+
<VerifiedIcon color="success" style={{ fontSize: 16, width: 16, marginLeft: 4, flexShrink: 0 }} />
|
|
161
|
+
)}
|
|
162
|
+
</Box>
|
|
163
|
+
</Typography>
|
|
164
|
+
</Tooltip>
|
|
165
|
+
) : null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<Box sx={{ width: '100%' }} style={style}>
|
|
170
|
+
{label && (
|
|
171
|
+
<Typography variant="subtitle1" gutterBottom sx={{ mb: 0.5, fontSize: '12px', color: '#4B5563' }}>
|
|
172
|
+
{label}
|
|
173
|
+
</Typography>
|
|
174
|
+
)}
|
|
175
|
+
{content}
|
|
176
|
+
</Box>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export default EditableField;
|