mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update user definition
This commit is contained in:
@@ -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"]
|
||||
|
@@ -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,
|
||||
});
|
||||
|
@@ -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";
|
||||
|
@@ -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>
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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));
|
||||
},
|
||||
});
|
||||
|
@@ -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">
|
||||
|
@@ -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>
|
||||
|
@@ -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");
|
||||
|
@@ -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 = () => {
|
||||
|
@@ -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 = [];
|
||||
|
@@ -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
|
||||
);
|
||||
|
@@ -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
|
||||
|
5
web/src/store/v1/resourceName.ts
Normal file
5
web/src/store/v1/resourceName.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export const UserNamePrefix = "users/";
|
||||
|
||||
export const extractUsernameFromName = (name: string) => {
|
||||
return name.split("/")[1];
|
||||
};
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user