diff --git a/web/src/components/Memo.tsx b/web/src/components/Memo.tsx
index 40579052..f5d1d602 100644
--- a/web/src/components/Memo.tsx
+++ b/web/src/components/Memo.tsx
@@ -1,6 +1,6 @@
import { memo, useEffect, useRef, useState } from "react";
import { escape, indexOf } from "lodash-es";
-import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG, UNKNOWN_ID } from "../helpers/consts";
+import { IMAGE_URL_REG, LINK_URL_REG, MEMO_LINK_REG, TAG_REG, UNKNOWN_ID } from "../helpers/consts";
import * as utils from "../helpers/utils";
import { DONE_BLOCK_REG, parseMarkedToHtml, TODO_BLOCK_REG } from "../helpers/marked";
import { editorStateService, locationService, memoService, userService } from "../services";
@@ -229,9 +229,9 @@ export function formatMemoContent(content: string) {
return tempElement.innerHTML
.replace(IMAGE_URL_REG, "")
- .replace(TAG_REG, "#$1 ")
- .replace(LINK_REG, "$1")
- .replace(MEMO_LINK_REG, "$1");
+ .replace(MEMO_LINK_REG, "$1")
+ .replace(LINK_URL_REG, "$1")
+ .replace(TAG_REG, "#$1 ");
}
export default memo(Memo);
diff --git a/web/src/components/MemoEditor.tsx b/web/src/components/MemoEditor.tsx
index 74413832..90787450 100644
--- a/web/src/components/MemoEditor.tsx
+++ b/web/src/components/MemoEditor.tsx
@@ -28,7 +28,7 @@ const MemoEditor: React.FC = () => {
useEffect(() => {
if (editorState.markMemoId && editorState.markMemoId !== UNKNOWN_ID) {
const editorCurrentValue = editorRef.current?.getContent();
- const memoLinkText = `${editorCurrentValue ? "\n" : ""}Mark: [@MEMO](${editorState.markMemoId})`;
+ const memoLinkText = `${editorCurrentValue ? "\n" : ""}Mark: @[MEMO](${editorState.markMemoId})`;
editorRef.current?.insertText(memoLinkText);
editorStateService.clearMarkMemo();
}
diff --git a/web/src/components/MemoList.tsx b/web/src/components/MemoList.tsx
index 40ce0649..f184c173 100644
--- a/web/src/components/MemoList.tsx
+++ b/web/src/components/MemoList.tsx
@@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from "react";
import { memoService, shortcutService } from "../services";
import { useAppSelector } from "../store";
-import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG } from "../helpers/consts";
+import { IMAGE_URL_REG, LINK_URL_REG, MEMO_LINK_REG, TAG_REG } from "../helpers/consts";
import * as utils from "../helpers/utils";
import { checkShouldShowMemoWithFilters } from "../helpers/filter";
import toastHelper from "./Toast";
@@ -58,7 +58,7 @@ const MemoList: React.FC = () => {
if (memoType) {
if (memoType === "NOT_TAGGED" && memo.content.match(TAG_REG) !== null) {
shouldShow = false;
- } else if (memoType === "LINKED" && memo.content.match(LINK_REG) === null) {
+ } else if (memoType === "LINKED" && memo.content.match(LINK_URL_REG) === null) {
shouldShow = false;
} else if (memoType === "IMAGED" && memo.content.match(IMAGE_URL_REG) === null) {
shouldShow = false;
diff --git a/web/src/components/UserBanner.tsx b/web/src/components/UserBanner.tsx
index a7dca2b6..d8bec85a 100644
--- a/web/src/components/UserBanner.tsx
+++ b/web/src/components/UserBanner.tsx
@@ -3,14 +3,13 @@ import * as utils from "../helpers/utils";
import userService from "../services/userService";
import { locationService } from "../services";
import { useAppSelector } from "../store";
-import toastHelper from "./Toast";
import MenuBtnsPopup from "./MenuBtnsPopup";
import "../less/user-banner.less";
interface Props {}
const UserBanner: React.FC = () => {
- const user = useAppSelector((state) => state.user.user);
+ const { user, owner } = useAppSelector((state) => state.user);
const { memos, tags } = useAppSelector((state) => state.memo);
const [shouldShowPopupBtns, setShouldShowPopupBtns] = useState(false);
const [username, setUsername] = useState("Memos");
@@ -18,24 +17,15 @@ const UserBanner: React.FC = () => {
const isVisitorMode = userService.isVisitorMode();
useEffect(() => {
- const currentUserId = userService.getUserIdFromPath();
- if (isVisitorMode && currentUserId) {
- userService
- .getUserById(currentUserId)
- .then((user) => {
- if (user) {
- setUsername(user.name);
- setCreatedDays(user ? Math.ceil((Date.now() - utils.getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24) : 0);
- } else {
- toastHelper.error("User not found");
- }
- })
- .catch(() => {
- // do nth
- });
+ if (isVisitorMode) {
+ if (!owner) {
+ return;
+ }
+ setUsername(owner.name);
+ setCreatedDays(Math.ceil((Date.now() - utils.getTimeStampByDate(owner.createdTs)) / 1000 / 3600 / 24));
} else if (user) {
setUsername(user.name);
- setCreatedDays(user ? Math.ceil((Date.now() - utils.getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24) : 0);
+ setCreatedDays(Math.ceil((Date.now() - utils.getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24));
}
}, []);
diff --git a/web/src/helpers/consts.ts b/web/src/helpers/consts.ts
index 52e9d29d..01b4bcc0 100644
--- a/web/src/helpers/consts.ts
+++ b/web/src/helpers/consts.ts
@@ -13,11 +13,11 @@ export const DAILY_TIMESTAMP = 3600 * 24 * 1000;
// tag regex
export const TAG_REG = /#(.+?) /g;
-// URL regex
-export const LINK_REG = /(https?:\/\/[^\s<\\*>']+)/g;
-
-// image regex
+// markdown image regex
export const IMAGE_URL_REG = /!\[.*?\]\((.+?)\)/g;
+// markdown link regex
+export const LINK_URL_REG = /\[(.*?)\]\((.+?)\)/g;
+
// linked memo regex
-export const MEMO_LINK_REG = /\[@(.+?)\]\((.+?)\)/g;
+export const MEMO_LINK_REG = /@\[(.+?)\]\((.+?)\)/g;
diff --git a/web/src/helpers/filter.ts b/web/src/helpers/filter.ts
index b9290e5e..78f83e48 100644
--- a/web/src/helpers/filter.ts
+++ b/web/src/helpers/filter.ts
@@ -1,4 +1,4 @@
-import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG } from "./consts";
+import { IMAGE_URL_REG, LINK_URL_REG, MEMO_LINK_REG, TAG_REG } from "./consts";
export const relationConsts = [
{ text: "And", value: "AND" },
@@ -142,7 +142,7 @@ export const checkShouldShowMemo = (memo: Memo, filter: Filter) => {
let matched = false;
if (value === "NOT_TAGGED" && memo.content.match(TAG_REG) === null) {
matched = true;
- } else if (value === "LINKED" && memo.content.match(LINK_REG) !== null) {
+ } else if (value === "LINKED" && memo.content.match(LINK_URL_REG) !== null) {
matched = true;
} else if (value === "IMAGED" && memo.content.match(IMAGE_URL_REG) !== null) {
matched = true;
diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx
index e7de74a4..e28e9eae 100644
--- a/web/src/pages/Home.tsx
+++ b/web/src/pages/Home.tsx
@@ -15,19 +15,22 @@ function Home() {
useEffect(() => {
userService
- .doSignIn()
+ .initialState()
.catch()
.finally(async () => {
- if (!userService.getState().user) {
- if (userService.isVisitorMode()) {
- const currentUserId = userService.getUserIdFromPath() as number;
- const user = await userService.getUserById(currentUserId);
- if (!user) {
- toastHelper.error("User not found");
- }
- } else {
- locationService.replaceHistory("/signin");
- return;
+ const { host, owner, user } = userService.getState();
+ if (!host) {
+ locationService.replaceHistory("/signin");
+ return;
+ }
+
+ if (userService.isVisitorMode()) {
+ if (!owner) {
+ toastHelper.error("User not found");
+ }
+ } else {
+ if (!user) {
+ locationService.replaceHistory(`/u/${host.id}`);
}
}
loadingState.setFinish();
diff --git a/web/src/services/memoService.ts b/web/src/services/memoService.ts
index a1446fa7..7f93c21b 100644
--- a/web/src/services/memoService.ts
+++ b/web/src/services/memoService.ts
@@ -17,9 +17,10 @@ const memoService = {
},
fetchAllMemos: async () => {
- const memoFind: MemoFind = {
- creatorId: userService.getUserIdFromPath(),
- };
+ const memoFind: MemoFind = {};
+ if (userService.isVisitorMode()) {
+ memoFind.creatorId = userService.getUserIdFromPath();
+ }
const { data } = (await api.getMemoList(memoFind)).data;
const memos = data.filter((m) => m.rowStatus !== "ARCHIVED").map((m) => convertResponseModelMemo(m));
store.dispatch(setMemos(memos));
@@ -29,9 +30,11 @@ const memoService = {
fetchArchivedMemos: async () => {
const memoFind: MemoFind = {
- creatorId: userService.getUserIdFromPath(),
rowStatus: "ARCHIVED",
};
+ if (userService.isVisitorMode()) {
+ memoFind.creatorId = userService.getUserIdFromPath();
+ }
const { data } = (await api.getMemoList(memoFind)).data;
const archivedMemos = data.map((m) => {
return convertResponseModelMemo(m);
@@ -50,9 +53,10 @@ const memoService = {
},
updateTagsState: async () => {
- const tagFind: TagFind = {
- creatorId: userService.getUserIdFromPath(),
- };
+ const tagFind: TagFind = {};
+ if (userService.isVisitorMode()) {
+ tagFind.creatorId = userService.getUserIdFromPath();
+ }
const { data } = (await api.getTagList(tagFind)).data;
store.dispatch(setTags(data));
},
diff --git a/web/src/services/userService.ts b/web/src/services/userService.ts
index e176c040..fea35093 100644
--- a/web/src/services/userService.ts
+++ b/web/src/services/userService.ts
@@ -2,7 +2,7 @@ import { isUndefined } from "lodash-es";
import { locationService } from ".";
import * as api from "../helpers/api";
import store from "../store";
-import { setUser, patchUser } from "../store/modules/user";
+import { setUser, patchUser, setHost, setOwner } from "../store/modules/user";
const convertResponseModelUser = (user: User): User => {
return {
@@ -17,12 +17,30 @@ const userService = {
return store.getState().user;
},
- isVisitorMode: () => {
- return !isUndefined(userService.getUserIdFromPath());
+ initialState: async () => {
+ const {
+ data: { host },
+ } = (await api.getSystemStatus()).data;
+ if (host) {
+ store.dispatch(setHost(convertResponseModelUser(host)));
+ }
+
+ const ownerUserId = userService.getUserIdFromPath();
+ if (ownerUserId) {
+ const { data: owner } = (await api.getUserById(ownerUserId)).data;
+ if (owner) {
+ store.dispatch(setOwner(convertResponseModelUser(owner)));
+ }
+ }
+
+ const { data: user } = (await api.getUser()).data;
+ if (user) {
+ store.dispatch(setUser(convertResponseModelUser(user)));
+ }
},
- getCurrentUserId: () => {
- return userService.getUserIdFromPath() ?? store.getState().user.user?.id;
+ isVisitorMode: () => {
+ return !isUndefined(userService.getUserIdFromPath());
},
getUserIdFromPath: () => {
diff --git a/web/src/store/modules/user.ts b/web/src/store/modules/user.ts
index a1e58fc3..a1d34e81 100644
--- a/web/src/store/modules/user.ts
+++ b/web/src/store/modules/user.ts
@@ -1,6 +1,11 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface State {
+ // host is the user who hist the system
+ host?: User;
+ // owner is the user who owns the page. If in `/u/101`, then owner's id is `101`
+ owner?: User;
+ // user is the user who is currently logged in
user?: User;
}
@@ -8,6 +13,18 @@ const userSlice = createSlice({
name: "user",
initialState: {} as State,
reducers: {
+ setHost: (state, action: PayloadAction) => {
+ return {
+ ...state,
+ host: action.payload,
+ };
+ },
+ setOwner: (state, action: PayloadAction) => {
+ return {
+ ...state,
+ owner: action.payload,
+ };
+ },
setUser: (state, action: PayloadAction) => {
return {
...state,
@@ -26,6 +43,6 @@ const userSlice = createSlice({
},
});
-export const { setUser, patchUser } = userSlice.actions;
+export const { setHost, setOwner, setUser, patchUser } = userSlice.actions;
export default userSlice.reducer;