chore: update user definition

This commit is contained in:
Steven
2023-11-05 23:03:43 +08:00
parent e67820cabe
commit e60e47f76f
21 changed files with 323 additions and 280 deletions

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { useGlobalStore, useUserStore } from "@/store/module";
import { useUserV1Store } from "@/store/v1";
import { UserNamePrefix } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
import { generateDialog } from "./Dialog";
import Icon from "./Icon";
@@ -54,7 +55,7 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const user = userStore.getState().user as User;
await userV1Store.updateUser(
{
username: user.username,
name: `${UserNamePrefix}${user.username}`,
password: newPassword,
},
["password"]

View File

@@ -69,7 +69,7 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
try {
await userServiceClient.createUserAccessToken({
username: currentUser.username,
name: currentUser.name,
description: state.description,
expiresAt: state.expiration ? new Date(Date.now() + state.expiration * 1000) : undefined,
});

View File

@@ -5,7 +5,7 @@ import toast from "react-hot-toast";
import { activityServiceClient } from "@/grpcweb";
import useNavigateTo from "@/hooks/useNavigateTo";
import useInboxStore from "@/store/v1/inbox";
import { extractUsernameFromName } from "@/store/v1/user";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { Activity } from "@/types/proto/api/v2/activity_service";
import { Inbox, Inbox_Status } from "@/types/proto/api/v2/inbox_service";
import { useTranslate } from "@/utils/i18n";

View File

@@ -9,6 +9,7 @@ import useCurrentUser from "@/hooks/useCurrentUser";
import useNavigateTo from "@/hooks/useNavigateTo";
import { useFilterStore, useMemoStore, useUserStore } from "@/store/module";
import { useUserV1Store } from "@/store/v1";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog";
import { showCommonDialog } from "./Dialog/CommonDialog";
@@ -42,7 +43,7 @@ const Memo: React.FC<Props> = (props: Props) => {
const [shouldRender, setShouldRender] = useState<boolean>(lazyRendering ? false : true);
const [displayTime, setDisplayTime] = useState<string>(getRelativeTimeString(memo.displayTs));
const memoContainerRef = useRef<HTMLDivElement>(null);
const readonly = memo.creatorUsername !== user?.username;
const readonly = memo.creatorUsername !== extractUsernameFromName(user?.name);
const [creator, setCreator] = useState(userV1Store.getUserByUsername(memo.creatorUsername));
const referenceRelations = memo.relationList.filter((relation) => relation.type === "REFERENCE");
const commentRelations = memo.relationList.filter((relation) => relation.relatedMemoId === memo.id && relation.type === "COMMENT");
@@ -300,7 +301,7 @@ const Memo: React.FC<Props> = (props: Props) => {
<span className="flex flex-row justify-start items-center">
<UserAvatar className="!w-5 !h-auto mr-1" avatarUrl={creator.avatarUrl} />
<span className="text-sm text-gray-600 max-w-[8em] truncate dark:text-gray-400">
{creator.nickname || creator.username}
{creator.nickname || extractUsernameFromName(creator.name)}
</span>
</span>
</Tooltip>

View File

@@ -7,6 +7,7 @@ import { getTimeStampByDate } from "@/helpers/datetime";
import useCurrentUser from "@/hooks/useCurrentUser";
import { TAG_REG } from "@/labs/marked/parser";
import { useFilterStore, useMemoStore } from "@/store/module";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
import Empty from "./Empty";
import Memo from "./Memo";
@@ -21,7 +22,7 @@ const MemoList: React.FC = () => {
const user = useCurrentUser();
const { tag: tagQuery, duration, text: textQuery, visibility } = filter;
const showMemoFilter = Boolean(tagQuery || (duration && duration.from < duration.to) || textQuery || visibility);
const username = params.username || user?.username || "";
const username = params.username || extractUsernameFromName(user.name) || "";
const fetchMoreRef = useRef<HTMLSpanElement>(null);

View File

@@ -4,6 +4,7 @@ import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { userServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { UserAccessToken } from "@/types/proto/api/v2/user_service";
import { useTranslate } from "@/utils/i18n";
import showCreateAccessTokenDialog from "../CreateAccessTokenDialog";
@@ -12,7 +13,7 @@ import Icon from "../Icon";
import LearnMore from "../LearnMore";
const listAccessTokens = async (username: string) => {
const { accessTokens } = await userServiceClient.listUserAccessTokens({ username: username });
const { accessTokens } = await userServiceClient.listUserAccessTokens({ name: `${UserAccessToken}${username}` });
return accessTokens;
};
@@ -22,13 +23,13 @@ const AccessTokenSection = () => {
const [userAccessTokens, setUserAccessTokens] = useState<UserAccessToken[]>([]);
useEffect(() => {
listAccessTokens(currentUser.username).then((accessTokens) => {
listAccessTokens(extractUsernameFromName(currentUser.name)).then((accessTokens) => {
setUserAccessTokens(accessTokens);
});
}, []);
const handleCreateAccessTokenDialogConfirm = async () => {
const accessTokens = await listAccessTokens(currentUser.username);
const accessTokens = await listAccessTokens(extractUsernameFromName(currentUser.name));
setUserAccessTokens(accessTokens);
};
@@ -44,7 +45,7 @@ const AccessTokenSection = () => {
style: "danger",
dialogName: "delete-access-token-dialog",
onConfirm: async () => {
await userServiceClient.deleteUserAccessToken({ username: currentUser.username, accessToken: accessToken });
await userServiceClient.deleteUserAccessToken({ name: currentUser.name, accessToken: accessToken });
setUserAccessTokens(userAccessTokens.filter((token) => token.accessToken !== accessToken));
},
});

View File

@@ -1,5 +1,6 @@
import { Button } from "@mui/joy";
import useCurrentUser from "@/hooks/useCurrentUser";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
import showChangePasswordDialog from "../ChangePasswordDialog";
import showUpdateAccountDialog from "../UpdateAccountDialog";
@@ -18,7 +19,7 @@ const MyAccountSection = () => {
<UserAvatar className="mr-2 w-14 h-14" avatarUrl={user.avatarUrl} />
<div className="flex flex-col justify-center items-start">
<span className="text-2xl font-medium">{user.nickname}</span>
<span className="-mt-2 text-base text-gray-500 dark:text-gray-400">({user.username})</span>
<span className="-mt-2 text-base text-gray-500 dark:text-gray-400">({extractUsernameFromName(user.name)})</span>
</div>
</div>
<div className="w-full flex flex-row justify-start items-center mt-4 space-x-2">

View File

@@ -6,6 +6,7 @@ import { getDateTimeString } from "@/helpers/datetime";
import useLoading from "@/hooks/useLoading";
import toImage from "@/labs/html2image";
import { useUserV1Store } from "@/store/v1";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
import { generateDialog } from "./Dialog";
import showEmbedMemoDialog from "./EmbedMemoDialog";
@@ -120,7 +121,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
<UserAvatar className="mr-2" avatarUrl={user.avatarUrl} />
<div className="w-auto grow truncate flex mr-2 flex-col justify-center items-start">
<span className="w-full text truncate font-medium text-gray-600 dark:text-gray-300">
{user.nickname || user.username}
{user.nickname || extractUsernameFromName(user.name)}
</span>
</div>
</div>

View File

@@ -6,6 +6,7 @@ import * as utils from "@/helpers/utils";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useGlobalStore } from "@/store/module";
import { useUserV1Store } from "@/store/v1";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate, Translations } from "@/utils/i18n";
import { useFilterStore, useMemoStore } from "../store/module";
import "@/less/usage-heat-map.less";
@@ -53,20 +54,20 @@ const UsageHeatMap = () => {
const containerElRef = useRef<HTMLDivElement>(null);
useEffect(() => {
userV1Store.getOrFetchUserByUsername(user.username).then((user) => {
userV1Store.getOrFetchUserByUsername(extractUsernameFromName(user.name)).then((user) => {
if (!user) {
return;
}
setCreatedDays(Math.ceil((Date.now() - getTimeStampByDate(user.createTime)) / 1000 / 3600 / 24));
});
}, [user.username]);
}, [user.name]);
useEffect(() => {
if (memos.length === 0) {
return;
}
getMemoStats(user.username)
getMemoStats(extractUsernameFromName(user.name))
.then(({ data }) => {
setMemoAmount(data.length);
const newStat: DailyUsageStat[] = getInitialUsageStat(usedDaysAmount, beginDayTimestamp);
@@ -85,7 +86,7 @@ const UsageHeatMap = () => {
.catch((error) => {
console.error(error);
});
}, [memos.length, user.username]);
}, [memos.length, user.name]);
const handleUsageStatItemMouseEnter = useCallback((event: React.MouseEvent, item: DailyUsageStat) => {
const tempDiv = document.createElement("div");

View File

@@ -1,6 +1,7 @@
import useCurrentUser from "@/hooks/useCurrentUser";
import useNavigateTo from "@/hooks/useNavigateTo";
import { useGlobalStore, useUserStore } from "@/store/module";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { User_Role } from "@/types/proto/api/v2/user_service";
import { useTranslate } from "@/utils/i18n";
import showAboutSiteDialog from "./AboutSiteDialog";
@@ -18,7 +19,7 @@ const UserBanner = () => {
const title = user ? user.nickname : systemStatus.customizedProfile.name || "memos";
const handleMyAccountClick = () => {
navigateTo(`/u/${encodeURIComponent(user.username)}`);
navigateTo(`/u/${encodeURIComponent(extractUsernameFromName(user.name))}`);
};
const handleAboutBtnClick = () => {

View File

@@ -5,6 +5,7 @@ import { getMemoStats } from "@/helpers/api";
import { DAILY_TIMESTAMP } from "@/helpers/consts";
import { getDateStampByDate, isFutureDate } from "@/helpers/datetime";
import useCurrentUser from "@/hooks/useCurrentUser";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
import Icon from "../Icon";
import "@/less/common/date-picker.less";
@@ -28,7 +29,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
}, [datestamp]);
useEffect(() => {
getMemoStats(user.username).then(({ data }) => {
getMemoStats(extractUsernameFromName(user.name)).then(({ data }) => {
const m = new Map();
for (const record of data) {
const date = getDateStampByDate(record * 1000);
@@ -36,7 +37,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
}
setCountByDate(m);
});
}, [user.username]);
}, [user.name]);
const firstDate = new Date(currentDateStamp);
const dayList = [];

View File

@@ -15,6 +15,7 @@ import { DAILY_TIMESTAMP, DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import { getDateStampByDate, getNormalizedDateString, getTimeStampByDate, getTimeString } from "@/helpers/datetime";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useMemoStore, useUserStore } from "@/store/module";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { useTranslate } from "@/utils/i18n";
const DailyReview = () => {
@@ -32,7 +33,7 @@ const DailyReview = () => {
const selectedDateStampWithOffset = selectedDateStamp + localSetting.dailyReviewTimeOffset * 60 * 60 * 1000;
return (
m.rowStatus === "NORMAL" &&
m.creatorUsername === user.username &&
m.creatorUsername === extractUsernameFromName(user.name) &&
displayTimestamp >= selectedDateStampWithOffset &&
displayTimestamp < selectedDateStampWithOffset + DAILY_TIMESTAMP
);

View File

@@ -20,6 +20,7 @@ import useCurrentUser from "@/hooks/useCurrentUser";
import useNavigateTo from "@/hooks/useNavigateTo";
import { useGlobalStore, useMemoStore } from "@/store/module";
import { useUserV1Store } from "@/store/v1";
import { extractUsernameFromName } from "@/store/v1/resourceName";
import { User, User_Role } from "@/types/proto/api/v2/user_service";
import { useTranslate } from "@/utils/i18n";
@@ -35,7 +36,7 @@ const MemoDetail = () => {
const { systemStatus } = globalStore.state;
const memoId = Number(params.memoId);
const memo = memoStore.state.memos.find((memo) => memo.id === memoId);
const allowEdit = memo?.creatorUsername === currentUser?.username;
const allowEdit = memo?.creatorUsername === extractUsernameFromName(currentUser.name);
const referenceRelations = memo?.relationList.filter((relation) => relation.type === "REFERENCE") || [];
const commentRelations = memo?.relationList.filter((relation) => relation.relatedMemoId === memo.id && relation.type === "COMMENT") || [];
const comments = commentRelations

View File

@@ -0,0 +1,5 @@
export const UserNamePrefix = "users/";
export const extractUsernameFromName = (name: string) => {
return name.split("/")[1];
};

View File

@@ -1,6 +1,7 @@
import { create } from "zustand";
import { userServiceClient } from "@/grpcweb";
import { User } from "@/types/proto/api/v2/user_service";
import { UserNamePrefix, extractUsernameFromName } from "./resourceName";
interface UserV1Store {
userMapByUsername: Record<string, User>;
@@ -25,7 +26,7 @@ const useUserV1Store = create<UserV1Store>()((set, get) => ({
const promisedUser = userServiceClient
.getUser({
username: username,
name: `${UserNamePrefix}${username}`,
})
.then(({ user }) => user);
requestCache.set(username, promisedUser);
@@ -50,15 +51,12 @@ const useUserV1Store = create<UserV1Store>()((set, get) => ({
if (!updatedUser) {
throw new Error("User not found");
}
const username = extractUsernameFromName(updatedUser.name);
const userMap = get().userMapByUsername;
userMap[updatedUser.username] = updatedUser;
userMap[username] = updatedUser;
set(userMap);
return updatedUser;
},
}));
export const extractUsernameFromName = (name: string) => {
return name.split("/")[1];
};
export default useUserV1Store;