mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: use username instead of uid (#1977)
* #1916 replace userId to username * resolve --------- Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
This commit is contained in:
committed by
GitHub
parent
336b32004d
commit
f91f09adea
@ -53,9 +53,10 @@ type Memo struct {
|
|||||||
Pinned bool `json:"pinned"`
|
Pinned bool `json:"pinned"`
|
||||||
|
|
||||||
// Related fields
|
// Related fields
|
||||||
CreatorName string `json:"creatorName"`
|
CreatorName string `json:"creatorName"`
|
||||||
ResourceList []*Resource `json:"resourceList"`
|
CreatorUsername string `json:"creatorUsername"`
|
||||||
RelationList []*MemoRelation `json:"relationList"`
|
ResourceList []*Resource `json:"resourceList"`
|
||||||
|
RelationList []*MemoRelation `json:"relationList"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateMemoRequest struct {
|
type CreateMemoRequest struct {
|
||||||
@ -354,11 +355,18 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
|
|||||||
findMemoMessage.CreatorID = &userID
|
findMemoMessage.CreatorID = &userID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if username := c.QueryParam("creatorUsername"); username != "" {
|
||||||
|
user, _ := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
|
||||||
|
if user != nil {
|
||||||
|
findMemoMessage.CreatorID = &user.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
|
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
// Anonymous use should only fetch PUBLIC memos with specified user
|
// Anonymous use should only fetch PUBLIC memos with specified user
|
||||||
if findMemoMessage.CreatorID == nil {
|
if findMemoMessage.CreatorID == nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find memo")
|
return echo.NewHTTPError(http.StatusBadRequest, "Missing user to find memo")
|
||||||
}
|
}
|
||||||
findMemoMessage.VisibilityList = []store.Visibility{store.Public}
|
findMemoMessage.VisibilityList = []store.Visibility{store.Public}
|
||||||
} else {
|
} else {
|
||||||
@ -467,6 +475,14 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
|
|||||||
if creatorID, err := strconv.Atoi(c.QueryParam("creatorId")); err == nil {
|
if creatorID, err := strconv.Atoi(c.QueryParam("creatorId")); err == nil {
|
||||||
findMemoMessage.CreatorID = &creatorID
|
findMemoMessage.CreatorID = &creatorID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if username := c.QueryParam("creatorUsername"); username != "" {
|
||||||
|
user, _ := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
|
||||||
|
if user != nil {
|
||||||
|
findMemoMessage.CreatorID = &user.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if findMemoMessage.CreatorID == nil {
|
if findMemoMessage.CreatorID == nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find memo")
|
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find memo")
|
||||||
}
|
}
|
||||||
@ -526,6 +542,13 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
|
|||||||
findMemoMessage.Pinned = &pinned
|
findMemoMessage.Pinned = &pinned
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if username := c.QueryParam("creatorUsername"); username != "" {
|
||||||
|
user, _ := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
|
||||||
|
if user != nil {
|
||||||
|
findMemoMessage.CreatorID = &user.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contentSearch := []string{}
|
contentSearch := []string{}
|
||||||
tag := c.QueryParam("tag")
|
tag := c.QueryParam("tag")
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
@ -650,6 +673,8 @@ func (s *APIV1Service) convertMemoFromStore(ctx context.Context, memo *store.Mem
|
|||||||
memoResponse.CreatorName = user.Username
|
memoResponse.CreatorName = user.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memoResponse.CreatorUsername = user.Username
|
||||||
|
|
||||||
// Compose display ts.
|
// Compose display ts.
|
||||||
memoResponse.DisplayTs = memoResponse.CreatedTs
|
memoResponse.DisplayTs = memoResponse.CreatedTs
|
||||||
// Find memo display with updated ts setting.
|
// Find memo display with updated ts setting.
|
||||||
|
@ -46,6 +46,7 @@ func (s *APIV1Service) registerSystemRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
g.GET("/status", func(c echo.Context) error {
|
g.GET("/status", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
|
|
||||||
systemStatus := SystemStatus{
|
systemStatus := SystemStatus{
|
||||||
Profile: *s.Profile,
|
Profile: *s.Profile,
|
||||||
DBSize: 0,
|
DBSize: 0,
|
||||||
@ -76,7 +77,7 @@ func (s *APIV1Service) registerSystemRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
|
||||||
}
|
}
|
||||||
if hostUser != nil {
|
if hostUser != nil {
|
||||||
systemStatus.Host = convertUserFromStore(hostUser)
|
systemStatus.Host = &User{ID: hostUser.ID}
|
||||||
// data desensitize
|
// data desensitize
|
||||||
systemStatus.Host.OpenID = ""
|
systemStatus.Host.OpenID = ""
|
||||||
systemStatus.Host.Email = ""
|
systemStatus.Host.Email = ""
|
||||||
|
@ -258,6 +258,26 @@ func (s *APIV1Service) registerUserRoutes(g *echo.Group) {
|
|||||||
return c.JSON(http.StatusOK, userMessage)
|
return c.JSON(http.StatusOK, userMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// GET /user/:username - Get user by username.
|
||||||
|
g.GET("/user/:username", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
username := c.Param("username")
|
||||||
|
|
||||||
|
user, err := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
|
||||||
|
}
|
||||||
|
if user == nil {
|
||||||
|
return echo.NewHTTPError(http.StatusNotFound, "User not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
userMessage := convertUserFromStore(user)
|
||||||
|
// data desensitize
|
||||||
|
userMessage.OpenID = ""
|
||||||
|
userMessage.Email = ""
|
||||||
|
return c.JSON(http.StatusOK, userMessage)
|
||||||
|
})
|
||||||
|
|
||||||
// PUT /user/:id - Update user by id.
|
// PUT /user/:id - Update user by id.
|
||||||
g.PATCH("/user/:id", func(c echo.Context) error {
|
g.PATCH("/user/:id", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
|
@ -32,7 +32,6 @@ func TestSystemServer(t *testing.T) {
|
|||||||
status, err = s.getSystemStatus()
|
status, err = s.getSystemStatus()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, user.ID, status.Host.ID)
|
require.Equal(t, user.ID, status.Host.ID)
|
||||||
require.Equal(t, user.Username, status.Host.Username)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TestingServer) getSystemStatus() (*apiv1.SystemStatus, error) {
|
func (s *TestingServer) getSystemStatus() (*apiv1.SystemStatus, error) {
|
||||||
|
@ -6,7 +6,6 @@ import { useTranslate } from "@/utils/i18n";
|
|||||||
import { resolution } from "@/utils/layout";
|
import { resolution } from "@/utils/layout";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import UserBanner from "./UserBanner";
|
import UserBanner from "./UserBanner";
|
||||||
import showAboutSiteDialog from "./AboutSiteDialog";
|
|
||||||
import UpgradeVersionView from "./UpgradeVersionBanner";
|
import UpgradeVersionView from "./UpgradeVersionBanner";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
@ -95,7 +94,7 @@ const Header = () => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isVisitorMode && (
|
{!globalStore.getDisablePublicMemos() && (
|
||||||
<>
|
<>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/explore"
|
to="/explore"
|
||||||
@ -179,13 +178,6 @@ const Header = () => {
|
|||||||
<Icon.LogIn className="mr-3 w-6 h-auto opacity-70" /> {t("common.sign-in")}
|
<Icon.LogIn className="mr-3 w-6 h-auto opacity-70" /> {t("common.sign-in")}
|
||||||
</>
|
</>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<button
|
|
||||||
id="header-about"
|
|
||||||
className="px-4 pr-5 py-2 rounded-full border border-transparent flex flex-row items-center text-lg text-gray-800 dark:text-gray-300 hover:bg-white hover:border-gray-200 dark:hover:border-zinc-600 dark:hover:bg-zinc-700"
|
|
||||||
onClick={() => showAboutSiteDialog()}
|
|
||||||
>
|
|
||||||
<Icon.CupSoda className="mr-3 w-6 h-auto opacity-70" /> {t("common.about")}
|
|
||||||
</button>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||||||
const [createdTimeStr, setCreatedTimeStr] = useState<string>(getRelativeTimeString(memo.displayTs));
|
const [createdTimeStr, setCreatedTimeStr] = useState<string>(getRelativeTimeString(memo.displayTs));
|
||||||
const [relatedMemoList, setRelatedMemoList] = useState<Memo[]>([]);
|
const [relatedMemoList, setRelatedMemoList] = useState<Memo[]>([]);
|
||||||
const memoContainerRef = useRef<HTMLDivElement>(null);
|
const memoContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const readonly = userStore.isVisitorMode() || userStore.getCurrentUserId() !== memo.creatorId;
|
const readonly = userStore.isVisitorMode() || userStore.getCurrentUsername() !== memo.creatorUsername;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Promise.allSettled(memo.relationList.map((memoRelation) => memoCacheStore.getOrFetchMemoById(memoRelation.relatedMemoId))).then(
|
Promise.allSettled(memo.relationList.map((memoRelation) => memoCacheStore.getOrFetchMemoById(memoRelation.relatedMemoId))).then(
|
||||||
@ -220,7 +220,7 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||||||
{createdTimeStr}
|
{createdTimeStr}
|
||||||
</Link>
|
</Link>
|
||||||
{showCreator && (
|
{showCreator && (
|
||||||
<Link className="name-text" to={`/u/${memo.creatorId}`}>
|
<Link className="name-text" to={`/u/${memo.creatorUsername}`}>
|
||||||
@{memo.creatorName}
|
@{memo.creatorName}
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
@ -10,7 +10,12 @@ import Empty from "./Empty";
|
|||||||
import Memo from "./Memo";
|
import Memo from "./Memo";
|
||||||
import "@/less/memo-list.less";
|
import "@/less/memo-list.less";
|
||||||
|
|
||||||
const MemoList = () => {
|
interface Props {
|
||||||
|
showCreator?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MemoList: React.FC<Props> = (props: Props) => {
|
||||||
|
const { showCreator } = props;
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const memoStore = useMemoStore();
|
const memoStore = useMemoStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
@ -20,7 +25,7 @@ const MemoList = () => {
|
|||||||
const { memos, isFetching } = memoStore.state;
|
const { memos, isFetching } = memoStore.state;
|
||||||
const [isComplete, setIsComplete] = useState<boolean>(false);
|
const [isComplete, setIsComplete] = useState<boolean>(false);
|
||||||
|
|
||||||
const currentUserId = userStore.getCurrentUserId();
|
const currentUsername = userStore.getCurrentUsername();
|
||||||
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = filter;
|
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = filter;
|
||||||
const shortcut = shortcutId ? shortcutStore.getShortcutById(shortcutId) : null;
|
const shortcut = shortcutId ? shortcutStore.getShortcutById(shortcutId) : null;
|
||||||
const showMemoFilter = Boolean(tagQuery || (duration && duration.from < duration.to) || memoType || textQuery || shortcut || visibility);
|
const showMemoFilter = Boolean(tagQuery || (duration && duration.from < duration.to) || memoType || textQuery || shortcut || visibility);
|
||||||
@ -76,7 +81,7 @@ const MemoList = () => {
|
|||||||
return shouldShow;
|
return shouldShow;
|
||||||
})
|
})
|
||||||
: memos
|
: memos
|
||||||
).filter((memo) => memo.creatorId === currentUserId && memo.rowStatus === "NORMAL");
|
).filter((memo) => memo.creatorUsername === currentUsername && memo.rowStatus === "NORMAL");
|
||||||
|
|
||||||
const pinnedMemos = shownMemos.filter((m) => m.pinned);
|
const pinnedMemos = shownMemos.filter((m) => m.pinned);
|
||||||
const unpinnedMemos = shownMemos.filter((m) => !m.pinned);
|
const unpinnedMemos = shownMemos.filter((m) => !m.pinned);
|
||||||
@ -103,7 +108,7 @@ const MemoList = () => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
toast.error(error.response.data.message);
|
toast.error(error.response.data.message);
|
||||||
});
|
});
|
||||||
}, [currentUserId]);
|
}, [currentUsername]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const pageWrapper = document.body.querySelector(".page-wrapper");
|
const pageWrapper = document.body.querySelector(".page-wrapper");
|
||||||
@ -153,7 +158,7 @@ const MemoList = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="memo-list-container">
|
<div className="memo-list-container">
|
||||||
{sortedMemos.map((memo) => (
|
{sortedMemos.map((memo) => (
|
||||||
<Memo key={`${memo.id}-${memo.displayTs}`} memo={memo} showVisibility />
|
<Memo key={`${memo.id}-${memo.displayTs}`} memo={memo} showVisibility showCreator={showCreator} />
|
||||||
))}
|
))}
|
||||||
{isFetching ? (
|
{isFetching ? (
|
||||||
<div className="status-text-container fetching-tip">
|
<div className="status-text-container fetching-tip">
|
||||||
|
@ -51,7 +51,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
|
|||||||
const createdDays = Math.ceil((Date.now() - getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24);
|
const createdDays = Math.ceil((Date.now() - getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getMemoStats(user.id)
|
getMemoStats(user.username)
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
setPartialState({
|
setPartialState({
|
||||||
memoAmount: data.length,
|
memoAmount: data.length,
|
||||||
|
@ -44,19 +44,19 @@ const UsageHeatMap = () => {
|
|||||||
const [allStat, setAllStat] = useState<DailyUsageStat[]>(getInitialUsageStat(usedDaysAmount, beginDayTimestamp));
|
const [allStat, setAllStat] = useState<DailyUsageStat[]>(getInitialUsageStat(usedDaysAmount, beginDayTimestamp));
|
||||||
const [currentStat, setCurrentStat] = useState<DailyUsageStat | null>(null);
|
const [currentStat, setCurrentStat] = useState<DailyUsageStat | null>(null);
|
||||||
const containerElRef = useRef<HTMLDivElement>(null);
|
const containerElRef = useRef<HTMLDivElement>(null);
|
||||||
const currentUserId = userStore.getCurrentUserId();
|
const currentUsername = userStore.getCurrentUsername();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
userStore.getUserById(currentUserId).then((user) => {
|
userStore.getUserByUsername(currentUsername).then((user) => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setCreatedDays(Math.ceil((Date.now() - getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24));
|
setCreatedDays(Math.ceil((Date.now() - getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24));
|
||||||
});
|
});
|
||||||
}, [currentUserId]);
|
}, [currentUsername]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getMemoStats(currentUserId)
|
getMemoStats(currentUsername)
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
setMemoAmount(data.length);
|
setMemoAmount(data.length);
|
||||||
const newStat: DailyUsageStat[] = getInitialUsageStat(usedDaysAmount, beginDayTimestamp);
|
const newStat: DailyUsageStat[] = getInitialUsageStat(usedDaysAmount, beginDayTimestamp);
|
||||||
@ -75,7 +75,7 @@ const UsageHeatMap = () => {
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
});
|
});
|
||||||
}, [memos.length, currentUserId]);
|
}, [memos.length, currentUsername]);
|
||||||
|
|
||||||
const handleUsageStatItemMouseEnter = useCallback((event: React.MouseEvent, item: DailyUsageStat) => {
|
const handleUsageStatItemMouseEnter = useCallback((event: React.MouseEvent, item: DailyUsageStat) => {
|
||||||
const tempDiv = document.createElement("div");
|
const tempDiv = document.createElement("div");
|
||||||
|
@ -43,7 +43,7 @@ const UserBanner = () => {
|
|||||||
<div className="px-4 py-2 max-w-full flex flex-row justify-start items-center cursor-pointer rounded-lg hover:shadow hover:bg-white dark:hover:bg-zinc-700">
|
<div className="px-4 py-2 max-w-full flex flex-row justify-start items-center cursor-pointer rounded-lg hover:shadow hover:bg-white dark:hover:bg-zinc-700">
|
||||||
<UserAvatar avatarUrl={user?.avatarUrl} />
|
<UserAvatar avatarUrl={user?.avatarUrl} />
|
||||||
<span className="px-1 text-lg font-medium text-slate-800 dark:text-gray-200 shrink truncate">
|
<span className="px-1 text-lg font-medium text-slate-800 dark:text-gray-200 shrink truncate">
|
||||||
{userStore.isVisitorMode() ? systemStatus.customizedProfile.name : username}
|
{user != undefined ? username : systemStatus.customizedProfile.name}
|
||||||
</span>
|
</span>
|
||||||
{user?.role === "HOST" ? (
|
{user?.role === "HOST" ? (
|
||||||
<span className="text-xs px-1 bg-blue-600 dark:bg-blue-800 rounded text-white dark:text-gray-200 shadow">MOD</span>
|
<span className="text-xs px-1 bg-blue-600 dark:bg-blue-800 rounded text-white dark:text-gray-200 shadow">MOD</span>
|
||||||
@ -54,7 +54,7 @@ const UserBanner = () => {
|
|||||||
positionClassName="top-full mt-2"
|
positionClassName="top-full mt-2"
|
||||||
actions={
|
actions={
|
||||||
<>
|
<>
|
||||||
{!userStore.isVisitorMode() && (
|
{user != undefined && (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
|
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
|
||||||
@ -64,7 +64,7 @@ const UserBanner = () => {
|
|||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
|
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
|
||||||
href={`/u/${user?.id}/rss.xml`}
|
href={`/u/${user?.username}/rss.xml`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<Icon.Rss className="w-5 h-auto mr-2 opacity-80" /> RSS
|
<Icon.Rss className="w-5 h-auto mr-2 opacity-80" /> RSS
|
||||||
@ -77,7 +77,7 @@ const UserBanner = () => {
|
|||||||
>
|
>
|
||||||
<Icon.Info className="w-5 h-auto mr-2 opacity-80" /> {t("common.about")}
|
<Icon.Info className="w-5 h-auto mr-2 opacity-80" /> {t("common.about")}
|
||||||
</button>
|
</button>
|
||||||
{!userStore.isVisitorMode() && (
|
{user != undefined && (
|
||||||
<button
|
<button
|
||||||
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
|
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
|
||||||
onClick={handleSignOutBtnClick}
|
onClick={handleSignOutBtnClick}
|
||||||
|
@ -21,14 +21,14 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
|
|||||||
const { className, isFutureDateDisabled, datestamp, handleDateStampChange } = props;
|
const { className, isFutureDateDisabled, datestamp, handleDateStampChange } = props;
|
||||||
const [currentDateStamp, setCurrentDateStamp] = useState<DateStamp>(getMonthFirstDayDateStamp(datestamp));
|
const [currentDateStamp, setCurrentDateStamp] = useState<DateStamp>(getMonthFirstDayDateStamp(datestamp));
|
||||||
const [countByDate, setCountByDate] = useState(new Map());
|
const [countByDate, setCountByDate] = useState(new Map());
|
||||||
const currentUserId = useUserStore().getCurrentUserId();
|
const currentUsername = useUserStore().getCurrentUsername();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentDateStamp(getMonthFirstDayDateStamp(datestamp));
|
setCurrentDateStamp(getMonthFirstDayDateStamp(datestamp));
|
||||||
}, [datestamp]);
|
}, [datestamp]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getMemoStats(currentUserId).then(({ data }) => {
|
getMemoStats(currentUsername).then(({ data }) => {
|
||||||
const m = new Map();
|
const m = new Map();
|
||||||
for (const record of data) {
|
for (const record of data) {
|
||||||
const date = getDateStampByDate(record * 1000);
|
const date = getDateStampByDate(record * 1000);
|
||||||
@ -36,7 +36,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
|
|||||||
}
|
}
|
||||||
setCountByDate(m);
|
setCountByDate(m);
|
||||||
});
|
});
|
||||||
}, [currentUserId]);
|
}, [currentUsername]);
|
||||||
|
|
||||||
const firstDate = new Date(currentDateStamp);
|
const firstDate = new Date(currentDateStamp);
|
||||||
const firstDateDay = firstDate.getDay() === 0 ? 7 : firstDate.getDay();
|
const firstDateDay = firstDate.getDay() === 0 ? 7 : firstDate.getDay();
|
||||||
|
@ -56,8 +56,8 @@ export function getUserList() {
|
|||||||
return axios.get<User[]>("/api/v1/user");
|
return axios.get<User[]>("/api/v1/user");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserById(id: number) {
|
export function getUserByUsername(username: string) {
|
||||||
return axios.get<User>(`/api/v1/user/${id}`);
|
return axios.get<User>(`/api/v1/user/${username}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function upsertUserSetting(upsert: UserSettingUpsert) {
|
export function upsertUserSetting(upsert: UserSettingUpsert) {
|
||||||
@ -81,13 +81,17 @@ export function getAllMemos(memoFind?: MemoFind) {
|
|||||||
queryList.push(`limit=${memoFind.limit}`);
|
queryList.push(`limit=${memoFind.limit}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (memoFind?.creatorUsername) {
|
||||||
|
queryList.push(`creatorUsername=${memoFind.creatorUsername}`);
|
||||||
|
}
|
||||||
|
|
||||||
return axios.get<Memo[]>(`/api/v1/memo/all?${queryList.join("&")}`);
|
return axios.get<Memo[]>(`/api/v1/memo/all?${queryList.join("&")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMemoList(memoFind?: MemoFind) {
|
export function getMemoList(memoFind?: MemoFind) {
|
||||||
const queryList = [];
|
const queryList = [];
|
||||||
if (memoFind?.creatorId) {
|
if (memoFind?.creatorUsername) {
|
||||||
queryList.push(`creatorId=${memoFind.creatorId}`);
|
queryList.push(`creatorUsername=${memoFind.creatorUsername}`);
|
||||||
}
|
}
|
||||||
if (memoFind?.rowStatus) {
|
if (memoFind?.rowStatus) {
|
||||||
queryList.push(`rowStatus=${memoFind.rowStatus}`);
|
queryList.push(`rowStatus=${memoFind.rowStatus}`);
|
||||||
@ -104,8 +108,8 @@ export function getMemoList(memoFind?: MemoFind) {
|
|||||||
return axios.get<Memo[]>(`/api/v1/memo?${queryList.join("&")}`);
|
return axios.get<Memo[]>(`/api/v1/memo?${queryList.join("&")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMemoStats(userId: UserId) {
|
export function getMemoStats(username: string) {
|
||||||
return axios.get<number[]>(`/api/v1/memo/stats?creatorId=${userId}`);
|
return axios.get<number[]>(`/api/v1/memo/stats?creatorUsername=${username}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMemoById(id: MemoId) {
|
export function getMemoById(id: MemoId) {
|
||||||
@ -163,8 +167,8 @@ export async function chatStreaming(messageList: Array<Message>, onmessage: any,
|
|||||||
|
|
||||||
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
||||||
const queryList = [];
|
const queryList = [];
|
||||||
if (shortcutFind?.creatorId) {
|
if (shortcutFind?.creatorUsername) {
|
||||||
queryList.push(`creatorId=${shortcutFind.creatorId}`);
|
queryList.push(`creatorUsername=${shortcutFind.creatorUsername}`);
|
||||||
}
|
}
|
||||||
return axios.get<Shortcut[]>(`/api/v1/shortcut?${queryList.join("&")}`);
|
return axios.get<Shortcut[]>(`/api/v1/shortcut?${queryList.join("&")}`);
|
||||||
}
|
}
|
||||||
@ -228,8 +232,8 @@ export function deleteMemoResource(memoId: MemoId, resourceId: ResourceId) {
|
|||||||
|
|
||||||
export function getTagList(tagFind?: TagFind) {
|
export function getTagList(tagFind?: TagFind) {
|
||||||
const queryList = [];
|
const queryList = [];
|
||||||
if (tagFind?.creatorId) {
|
if (tagFind?.creatorUsername) {
|
||||||
queryList.push(`creatorId=${tagFind.creatorId}`);
|
queryList.push(`creatorUsername=${tagFind.creatorUsername}`);
|
||||||
}
|
}
|
||||||
return axios.get<string[]>(`/api/v1/tag?${queryList.join("&")}`);
|
return axios.get<string[]>(`/api/v1/tag?${queryList.join("&")}`);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// UNKNOWN_ID is the symbol for unknown id
|
// UNKNOWN_ID is the symbol for unknown id
|
||||||
export const UNKNOWN_ID = -1;
|
export const UNKNOWN_ID = -1;
|
||||||
|
export const UNKNOWN_USERNAME = "";
|
||||||
|
|
||||||
// default animation duration
|
// default animation duration
|
||||||
export const ANIMATION_DURATION = 200;
|
export const ANIMATION_DURATION = 200;
|
||||||
|
@ -46,7 +46,7 @@ const EmbedMemo = () => {
|
|||||||
<div className="w-full flex flex-col justify-start items-start">
|
<div className="w-full flex flex-col justify-start items-start">
|
||||||
<div className="w-full mb-2 flex flex-row justify-start items-center text-sm text-gray-400 dark:text-gray-300">
|
<div className="w-full mb-2 flex flex-row justify-start items-center text-sm text-gray-400 dark:text-gray-300">
|
||||||
<span>{getDateTimeString(state.memo.displayTs)}</span>
|
<span>{getDateTimeString(state.memo.displayTs)}</span>
|
||||||
<a className="ml-2 hover:underline hover:text-green-600" href={`/u/${state.memo.creatorId}`}>
|
<a className="ml-2 hover:underline hover:text-green-600" href={`/u/${state.memo.creatorUsername}`}>
|
||||||
@{state.memo.creatorName}
|
@{state.memo.creatorName}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import { useFilterStore, useMemoStore } from "@/store/module";
|
import { useFilterStore, useMemoStore, useUserStore } from "@/store/module";
|
||||||
import { TAG_REG } from "@/labs/marked/parser";
|
import { TAG_REG } from "@/labs/marked/parser";
|
||||||
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
|
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
|
||||||
import useLoading from "@/hooks/useLoading";
|
import useLoading from "@/hooks/useLoading";
|
||||||
@ -16,24 +16,16 @@ const Explore = () => {
|
|||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const filterStore = useFilterStore();
|
const filterStore = useFilterStore();
|
||||||
const memoStore = useMemoStore();
|
const memoStore = useMemoStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const filter = filterStore.state;
|
const filter = filterStore.state;
|
||||||
const memos = memoStore.state.memos;
|
const { memos } = memoStore.state;
|
||||||
const [isComplete, setIsComplete] = useState<boolean>(false);
|
const [isComplete, setIsComplete] = useState<boolean>(false);
|
||||||
const loadingState = useLoading();
|
const loadingState = useLoading();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
memoStore.fetchAllMemos(DEFAULT_MEMO_LIMIT, 0).then((memos) => {
|
|
||||||
if (memos.length < DEFAULT_MEMO_LIMIT) {
|
|
||||||
setIsComplete(true);
|
|
||||||
}
|
|
||||||
loadingState.setFinish();
|
|
||||||
});
|
|
||||||
}, [location]);
|
|
||||||
|
|
||||||
const { tag: tagQuery, text: textQuery } = filter;
|
const { tag: tagQuery, text: textQuery } = filter;
|
||||||
const showMemoFilter = Boolean(tagQuery || textQuery);
|
const showMemoFilter = Boolean(tagQuery || textQuery);
|
||||||
|
|
||||||
const shownMemos = showMemoFilter
|
const fetchedMemos = showMemoFilter
|
||||||
? memos.filter((memo) => {
|
? memos.filter((memo) => {
|
||||||
let shouldShow = true;
|
let shouldShow = true;
|
||||||
|
|
||||||
@ -57,13 +49,35 @@ const Explore = () => {
|
|||||||
})
|
})
|
||||||
: memos;
|
: memos;
|
||||||
|
|
||||||
const sortedMemos = shownMemos
|
const username = userStore.getUsernameFromPath();
|
||||||
|
let sortedMemos = fetchedMemos
|
||||||
.filter((m) => m.rowStatus === "NORMAL" && m.visibility !== "PRIVATE")
|
.filter((m) => m.rowStatus === "NORMAL" && m.visibility !== "PRIVATE")
|
||||||
.sort((mi, mj) => mj.displayTs - mi.displayTs);
|
.sort((mi, mj) => mj.displayTs - mi.displayTs);
|
||||||
|
|
||||||
|
if (username != undefined) {
|
||||||
|
sortedMemos = sortedMemos.filter((m) => m.creatorUsername === username);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const username = userStore.getUsernameFromPath();
|
||||||
|
memoStore
|
||||||
|
.fetchAllMemos(DEFAULT_MEMO_LIMIT, 0, username)
|
||||||
|
.then((fetchedMemos) => {
|
||||||
|
if (fetchedMemos.length < DEFAULT_MEMO_LIMIT) {
|
||||||
|
setIsComplete(true);
|
||||||
|
}
|
||||||
|
loadingState.setFinish();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
toast.error(error.response.data.message);
|
||||||
|
});
|
||||||
|
}, [location]);
|
||||||
|
|
||||||
const handleFetchMoreClick = async () => {
|
const handleFetchMoreClick = async () => {
|
||||||
try {
|
try {
|
||||||
const fetchedMemos = await memoStore.fetchAllMemos(DEFAULT_MEMO_LIMIT, memos.length);
|
const username = userStore.getUsernameFromPath();
|
||||||
|
const fetchedMemos = await memoStore.fetchAllMemos(DEFAULT_MEMO_LIMIT, memos.length, username);
|
||||||
if (fetchedMemos.length < DEFAULT_MEMO_LIMIT) {
|
if (fetchedMemos.length < DEFAULT_MEMO_LIMIT) {
|
||||||
setIsComplete(true);
|
setIsComplete(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,14 +15,14 @@ function Home() {
|
|||||||
const user = userStore.state.user;
|
const user = userStore.state.user;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentUserId = userStore.getCurrentUserId();
|
const currentUsername = userStore.getCurrentUsername();
|
||||||
userStore.getUserById(currentUserId).then((user) => {
|
userStore.getUserByUsername(currentUsername).then((user) => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
toast.error(t("message.user-not-found"));
|
toast.error(t("message.user-not-found"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [userStore.getCurrentUserId()]);
|
}, [userStore.getCurrentUsername()]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user?.setting.locale) {
|
if (user?.setting.locale) {
|
||||||
|
@ -63,22 +63,25 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
const { systemStatus } = store.getState().global;
|
||||||
|
|
||||||
if (isNullorUndefined(host)) {
|
// if user is authenticated, then show home
|
||||||
return redirect("/auth");
|
if (!isNullorUndefined(user)) {
|
||||||
} else if (isNullorUndefined(user) && !systemStatus.disablePublicMemos) {
|
return null;
|
||||||
return redirect("/explore");
|
}
|
||||||
} else if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
|
|
||||||
|
// if user is anonymous, then redirect to auth if disabled public memos, else redirect to explore
|
||||||
|
if (systemStatus.disablePublicMemos) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
return redirect("/explore");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/u/:userId",
|
path: "/u/:username",
|
||||||
element: <Home />,
|
element: <Explore />,
|
||||||
loader: async () => {
|
loader: async () => {
|
||||||
await initialGlobalStateLoader();
|
await initialGlobalStateLoader();
|
||||||
|
|
||||||
@ -88,12 +91,13 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
const { systemStatus } = store.getState().global;
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -109,10 +113,10 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
const { systemStatus } = store.getState().global;
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -130,10 +134,9 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user)) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -151,10 +154,9 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user)) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -172,10 +174,9 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user)) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -194,10 +195,9 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user)) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -215,10 +215,9 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user)) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -238,10 +237,10 @@ const router = createBrowserRouter([
|
|||||||
// do nth
|
// do nth
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, user } = store.getState().user;
|
const { user } = store.getState().user;
|
||||||
const { systemStatus } = store.getState().global;
|
const { systemStatus } = store.getState().global;
|
||||||
|
|
||||||
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
|
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
|
||||||
return redirect("/auth");
|
return redirect("/auth");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -65,6 +65,9 @@ export const useGlobalStore = () => {
|
|||||||
getState: () => {
|
getState: () => {
|
||||||
return store.getState().global;
|
return store.getState().global;
|
||||||
},
|
},
|
||||||
|
getDisablePublicMemos: () => {
|
||||||
|
return store.getState().global.systemStatus.disablePublicMemos;
|
||||||
|
},
|
||||||
isDev: () => {
|
isDev: () => {
|
||||||
return state.systemStatus.profile.mode !== "prod";
|
return state.systemStatus.profile.mode !== "prod";
|
||||||
},
|
},
|
||||||
|
@ -41,7 +41,7 @@ export const useMemoStore = () => {
|
|||||||
offset,
|
offset,
|
||||||
};
|
};
|
||||||
if (userStore.isVisitorMode()) {
|
if (userStore.isVisitorMode()) {
|
||||||
memoFind.creatorId = userStore.getUserIdFromPath();
|
memoFind.creatorUsername = userStore.getUsernameFromPath();
|
||||||
}
|
}
|
||||||
const { data } = await api.getMemoList(memoFind);
|
const { data } = await api.getMemoList(memoFind);
|
||||||
const fetchedMemos = data.map((m) => convertResponseModelMemo(m));
|
const fetchedMemos = data.map((m) => convertResponseModelMemo(m));
|
||||||
@ -54,16 +54,22 @@ export const useMemoStore = () => {
|
|||||||
|
|
||||||
return fetchedMemos;
|
return fetchedMemos;
|
||||||
},
|
},
|
||||||
fetchAllMemos: async (limit = DEFAULT_MEMO_LIMIT, offset?: number) => {
|
fetchAllMemos: async (limit = DEFAULT_MEMO_LIMIT, offset?: number, username?: string) => {
|
||||||
|
store.dispatch(setIsFetching(true));
|
||||||
const memoFind: MemoFind = {
|
const memoFind: MemoFind = {
|
||||||
rowStatus: "NORMAL",
|
rowStatus: "NORMAL",
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (username != undefined) {
|
||||||
|
memoFind.creatorUsername = username;
|
||||||
|
}
|
||||||
|
|
||||||
const { data } = await api.getAllMemos(memoFind);
|
const { data } = await api.getAllMemos(memoFind);
|
||||||
const fetchedMemos = data.map((m) => convertResponseModelMemo(m));
|
const fetchedMemos = data.map((m) => convertResponseModelMemo(m));
|
||||||
store.dispatch(upsertMemos(fetchedMemos));
|
store.dispatch(upsertMemos(fetchedMemos));
|
||||||
|
store.dispatch(setIsFetching(false));
|
||||||
|
|
||||||
for (const m of fetchedMemos) {
|
for (const m of fetchedMemos) {
|
||||||
memoCacheStore.setMemoCache(m);
|
memoCacheStore.setMemoCache(m);
|
||||||
@ -76,7 +82,7 @@ export const useMemoStore = () => {
|
|||||||
rowStatus: "ARCHIVED",
|
rowStatus: "ARCHIVED",
|
||||||
};
|
};
|
||||||
if (userStore.isVisitorMode()) {
|
if (userStore.isVisitorMode()) {
|
||||||
memoFind.creatorId = userStore.getUserIdFromPath();
|
memoFind.creatorUsername = userStore.getUsernameFromPath();
|
||||||
}
|
}
|
||||||
const { data } = await api.getMemoList(memoFind);
|
const { data } = await api.getMemoList(memoFind);
|
||||||
const archivedMemos = data.map((m) => {
|
const archivedMemos = data.map((m) => {
|
||||||
|
@ -14,7 +14,7 @@ export const useTagStore = () => {
|
|||||||
fetchTags: async () => {
|
fetchTags: async () => {
|
||||||
const tagFind: TagFind = {};
|
const tagFind: TagFind = {};
|
||||||
if (userStore.isVisitorMode()) {
|
if (userStore.isVisitorMode()) {
|
||||||
tagFind.creatorId = userStore.getUserIdFromPath();
|
tagFind.creatorUsername = userStore.getUsernameFromPath();
|
||||||
}
|
}
|
||||||
const { data } = await api.getTagList(tagFind);
|
const { data } = await api.getTagList(tagFind);
|
||||||
store.dispatch(setTags(data));
|
store.dispatch(setTags(data));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { camelCase } from "lodash-es";
|
import { camelCase } from "lodash-es";
|
||||||
import * as api from "@/helpers/api";
|
import * as api from "@/helpers/api";
|
||||||
import storage from "@/helpers/storage";
|
import storage from "@/helpers/storage";
|
||||||
import { UNKNOWN_ID } from "@/helpers/consts";
|
import { UNKNOWN_USERNAME } from "@/helpers/consts";
|
||||||
import { getSystemColorScheme } from "@/helpers/utils";
|
import { getSystemColorScheme } from "@/helpers/utils";
|
||||||
import store, { useAppSelector } from "..";
|
import store, { useAppSelector } from "..";
|
||||||
import { setAppearance, setLocale } from "../reducer/global";
|
import { setAppearance, setLocale } from "../reducer/global";
|
||||||
@ -82,6 +82,16 @@ const getUserIdFromPath = () => {
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getUsernameFromPath = () => {
|
||||||
|
const pathname = window.location.pathname;
|
||||||
|
const usernameRegex = /^\/u\/(\w+).*/;
|
||||||
|
const result = pathname.match(usernameRegex);
|
||||||
|
if (result && result.length === 2) {
|
||||||
|
return String(result[1]);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const doSignIn = async () => {
|
const doSignIn = async () => {
|
||||||
const { data: user } = await api.getMyselfUser();
|
const { data: user } = await api.getMyselfUser();
|
||||||
if (user) {
|
if (user) {
|
||||||
@ -100,7 +110,7 @@ export const useUserStore = () => {
|
|||||||
const state = useAppSelector((state) => state.user);
|
const state = useAppSelector((state) => state.user);
|
||||||
|
|
||||||
const isVisitorMode = () => {
|
const isVisitorMode = () => {
|
||||||
return state.user === undefined || (getUserIdFromPath() && state.user.id !== getUserIdFromPath());
|
return state.user === undefined || (getUsernameFromPath() && state.user.username !== getUsernameFromPath());
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -110,17 +120,18 @@ export const useUserStore = () => {
|
|||||||
},
|
},
|
||||||
isVisitorMode,
|
isVisitorMode,
|
||||||
getUserIdFromPath,
|
getUserIdFromPath,
|
||||||
|
getUsernameFromPath,
|
||||||
doSignIn,
|
doSignIn,
|
||||||
doSignOut,
|
doSignOut,
|
||||||
getCurrentUserId: () => {
|
getCurrentUsername: () => {
|
||||||
if (isVisitorMode()) {
|
if (isVisitorMode()) {
|
||||||
return getUserIdFromPath() || UNKNOWN_ID;
|
return getUsernameFromPath() || UNKNOWN_USERNAME;
|
||||||
} else {
|
} else {
|
||||||
return state.user?.id || UNKNOWN_ID;
|
return state.user?.username || UNKNOWN_USERNAME;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getUserById: async (userId: UserId) => {
|
getUserByUsername: async (username: string) => {
|
||||||
const { data } = await api.getUserById(userId);
|
const { data } = await api.getUserByUsername(username);
|
||||||
if (data) {
|
if (data) {
|
||||||
const user = convertResponseModelUser(data);
|
const user = convertResponseModelUser(data);
|
||||||
store.dispatch(setUserById(user));
|
store.dispatch(setUserById(user));
|
||||||
|
4
web/src/types/modules/memo.d.ts
vendored
4
web/src/types/modules/memo.d.ts
vendored
@ -5,7 +5,7 @@ type Visibility = "PUBLIC" | "PROTECTED" | "PRIVATE";
|
|||||||
interface Memo {
|
interface Memo {
|
||||||
id: MemoId;
|
id: MemoId;
|
||||||
|
|
||||||
creatorId: UserId;
|
creatorUsername: string;
|
||||||
createdTs: TimeStamp;
|
createdTs: TimeStamp;
|
||||||
updatedTs: TimeStamp;
|
updatedTs: TimeStamp;
|
||||||
rowStatus: RowStatus;
|
rowStatus: RowStatus;
|
||||||
@ -38,7 +38,7 @@ interface MemoPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface MemoFind {
|
interface MemoFind {
|
||||||
creatorId?: UserId;
|
creatorUsername?: string;
|
||||||
rowStatus?: RowStatus;
|
rowStatus?: RowStatus;
|
||||||
pinned?: boolean;
|
pinned?: boolean;
|
||||||
visibility?: Visibility;
|
visibility?: Visibility;
|
||||||
|
4
web/src/types/modules/shortcut.d.ts
vendored
4
web/src/types/modules/shortcut.d.ts
vendored
@ -3,7 +3,7 @@ type ShortcutId = number;
|
|||||||
interface Shortcut {
|
interface Shortcut {
|
||||||
id: ShortcutId;
|
id: ShortcutId;
|
||||||
|
|
||||||
creatorId: UserId;
|
creatorUsername: string;
|
||||||
rowStatus: RowStatus;
|
rowStatus: RowStatus;
|
||||||
createdTs: TimeStamp;
|
createdTs: TimeStamp;
|
||||||
updatedTs: TimeStamp;
|
updatedTs: TimeStamp;
|
||||||
@ -25,5 +25,5 @@ interface ShortcutPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ShortcutFind {
|
interface ShortcutFind {
|
||||||
creatorId?: UserId;
|
creatorUsername?: string;
|
||||||
}
|
}
|
||||||
|
2
web/src/types/modules/tag.d.ts
vendored
2
web/src/types/modules/tag.d.ts
vendored
@ -1,3 +1,3 @@
|
|||||||
interface TagFind {
|
interface TagFind {
|
||||||
creatorId?: UserId;
|
creatorUsername?: string;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user