mirror of
https://github.com/usememos/memos.git
synced 2025-02-19 04:40:40 +01:00
chore: update data initial requests (#538)
This commit is contained in:
parent
362306a9cb
commit
a0667abec8
@ -4,7 +4,7 @@ import "github.com/usememos/memos/server/profile"
|
|||||||
|
|
||||||
type SystemStatus struct {
|
type SystemStatus struct {
|
||||||
Host *User `json:"host"`
|
Host *User `json:"host"`
|
||||||
Profile *profile.Profile `json:"profile"`
|
Profile profile.Profile `json:"profile"`
|
||||||
DBSize int64 `json:"dbSize"`
|
DBSize int64 `json:"dbSize"`
|
||||||
|
|
||||||
// System settings
|
// System settings
|
||||||
|
@ -41,7 +41,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
systemStatus := api.SystemStatus{
|
systemStatus := api.SystemStatus{
|
||||||
Host: hostUser,
|
Host: hostUser,
|
||||||
Profile: s.Profile,
|
Profile: *s.Profile,
|
||||||
DBSize: 0,
|
DBSize: 0,
|
||||||
AllowSignUp: false,
|
AllowSignUp: false,
|
||||||
AdditionalStyle: "",
|
AdditionalStyle: "",
|
||||||
|
@ -2,49 +2,43 @@ import { CssVarsProvider } from "@mui/joy/styles";
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { RouterProvider } from "react-router-dom";
|
import { RouterProvider } from "react-router-dom";
|
||||||
import { globalService, locationService } from "./services";
|
import { locationService } from "./services";
|
||||||
import { useAppSelector } from "./store";
|
import { useAppSelector } from "./store";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import * as api from "./helpers/api";
|
|
||||||
import * as storage from "./helpers/storage";
|
import * as storage from "./helpers/storage";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const global = useAppSelector((state) => state.global);
|
const { locale, systemStatus } = useAppSelector((state) => state.global);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
locationService.updateStateWithLocation();
|
locationService.updateStateWithLocation();
|
||||||
window.onpopstate = () => {
|
window.onpopstate = () => {
|
||||||
locationService.updateStateWithLocation();
|
locationService.updateStateWithLocation();
|
||||||
};
|
};
|
||||||
|
|
||||||
globalService.initialState();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Inject additional style and script codes.
|
// Inject additional style and script codes.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.getSystemStatus().then(({ data }) => {
|
if (systemStatus.additionalStyle) {
|
||||||
const { data: status } = data;
|
|
||||||
if (status.additionalStyle) {
|
|
||||||
const styleEl = document.createElement("style");
|
const styleEl = document.createElement("style");
|
||||||
styleEl.innerHTML = status.additionalStyle;
|
styleEl.innerHTML = systemStatus.additionalStyle;
|
||||||
styleEl.setAttribute("type", "text/css");
|
styleEl.setAttribute("type", "text/css");
|
||||||
document.head.appendChild(styleEl);
|
document.head.appendChild(styleEl);
|
||||||
}
|
}
|
||||||
if (status.additionalScript) {
|
if (systemStatus.additionalScript) {
|
||||||
const scriptEl = document.createElement("script");
|
const scriptEl = document.createElement("script");
|
||||||
scriptEl.innerHTML = status.additionalScript;
|
scriptEl.innerHTML = systemStatus.additionalScript;
|
||||||
document.head.appendChild(scriptEl);
|
document.head.appendChild(scriptEl);
|
||||||
}
|
}
|
||||||
});
|
}, [systemStatus]);
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
i18n.changeLanguage(global.locale);
|
i18n.changeLanguage(locale);
|
||||||
storage.set({
|
storage.set({
|
||||||
locale: global.locale,
|
locale: locale,
|
||||||
});
|
});
|
||||||
}, [global.locale]);
|
}, [locale]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CssVarsProvider>
|
<CssVarsProvider>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import * as api from "../helpers/api";
|
import { useAppSelector } from "../store";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import { generateDialog } from "./Dialog";
|
import { generateDialog } from "./Dialog";
|
||||||
import GitHubBadge from "./GitHubBadge";
|
import GitHubBadge from "./GitHubBadge";
|
||||||
@ -10,23 +9,7 @@ type Props = DialogProps;
|
|||||||
|
|
||||||
const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
|
const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [profile, setProfile] = useState<Profile>();
|
const profile = useAppSelector((state) => state.global.systemStatus.profile);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
api.getSystemStatus().then(({ data }) => {
|
|
||||||
const {
|
|
||||||
data: { profile },
|
|
||||||
} = data;
|
|
||||||
setProfile(profile);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
setProfile({
|
|
||||||
mode: "dev",
|
|
||||||
version: "0.0.0",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleCloseBtnClick = () => {
|
const handleCloseBtnClick = () => {
|
||||||
destroy();
|
destroy();
|
||||||
@ -49,15 +32,13 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
|
|||||||
<br />
|
<br />
|
||||||
<div className="addtion-info-container">
|
<div className="addtion-info-container">
|
||||||
<GitHubBadge />
|
<GitHubBadge />
|
||||||
{profile !== undefined && (
|
|
||||||
<>
|
<>
|
||||||
{t("common.version")}:
|
{t("common.version")}:
|
||||||
<span className="pre-text">
|
<span className="pre-text">
|
||||||
{profile?.version}-{profile?.mode}
|
{profile.version}-{profile.mode}
|
||||||
</span>
|
</span>
|
||||||
🎉
|
🎉
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -8,6 +8,7 @@ import "../less/memo-filter.less";
|
|||||||
|
|
||||||
const MemoFilter = () => {
|
const MemoFilter = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
useAppSelector((state) => state.shortcut.shortcuts);
|
||||||
const query = useAppSelector((state) => state.location.query);
|
const query = useAppSelector((state) => state.location.query);
|
||||||
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = query;
|
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = query;
|
||||||
const shortcut = shortcutId ? shortcutService.getShortcutById(shortcutId) : null;
|
const shortcut = shortcutId ? shortcutService.getShortcutById(shortcutId) : null;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useAppSelector } from "../store";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import * as storage from "../helpers/storage";
|
import * as storage from "../helpers/storage";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
@ -10,22 +11,14 @@ interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UpdateVersionBanner: React.FC = () => {
|
const UpdateVersionBanner: React.FC = () => {
|
||||||
|
const profile = useAppSelector((state) => state.global.systemStatus.profile);
|
||||||
const [state, setState] = useState<State>({
|
const [state, setState] = useState<State>({
|
||||||
latestVersion: "",
|
latestVersion: "",
|
||||||
show: false,
|
show: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Promise.all([api.getRepoLatestTag(), api.getSystemStatus()])
|
api.getRepoLatestTag().then((latestTag) => {
|
||||||
.then(
|
|
||||||
([
|
|
||||||
latestTag,
|
|
||||||
{
|
|
||||||
data: {
|
|
||||||
data: { profile },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]) => {
|
|
||||||
const { skippedVersion } = storage.get(["skippedVersion"]);
|
const { skippedVersion } = storage.get(["skippedVersion"]);
|
||||||
const latestVersion = latestTag.slice(1) || "0.0.0";
|
const latestVersion = latestTag.slice(1) || "0.0.0";
|
||||||
const currentVersion = profile.version;
|
const currentVersion = profile.version;
|
||||||
@ -34,10 +27,6 @@ const UpdateVersionBanner: React.FC = () => {
|
|||||||
latestVersion,
|
latestVersion,
|
||||||
show: !skipped && currentVersion < latestVersion,
|
show: !skipped && currentVersion < latestVersion,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
)
|
|
||||||
.catch(() => {
|
|
||||||
// do nth
|
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useAppSelector } from "../store";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import { validate, ValidatorConfig } from "../helpers/validator";
|
import { validate, ValidatorConfig } from "../helpers/validator";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
@ -19,23 +20,11 @@ const validateConfig: ValidatorConfig = {
|
|||||||
const Auth = () => {
|
const Auth = () => {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const pageLoadingState = useLoading(true);
|
const systemStatus = useAppSelector((state) => state.global.systemStatus);
|
||||||
const [systemStatus, setSystemStatus] = useState<SystemStatus>();
|
|
||||||
const [email, setEmail] = useState("");
|
|
||||||
const [password, setPassword] = useState("");
|
|
||||||
const actionBtnLoadingState = useLoading(false);
|
const actionBtnLoadingState = useLoading(false);
|
||||||
|
const mode = systemStatus.profile.mode;
|
||||||
useEffect(() => {
|
const [email, setEmail] = useState(mode === "dev" ? "demo@usememos.com" : "");
|
||||||
api.getSystemStatus().then(({ data }) => {
|
const [password, setPassword] = useState(mode === "dev" ? "secret" : "");
|
||||||
const { data: status } = data;
|
|
||||||
setSystemStatus(status);
|
|
||||||
if (status.profile.mode === "dev") {
|
|
||||||
setEmail("demo@usememos.com");
|
|
||||||
setPassword("secret");
|
|
||||||
}
|
|
||||||
pageLoadingState.setFinish();
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleEmailInputChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleEmailInputChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const text = e.target.value as string;
|
const text = e.target.value as string;
|
||||||
@ -138,8 +127,6 @@ const Auth = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="action-btns-container">
|
<div className="action-btns-container">
|
||||||
{!pageLoadingState.isLoading && (
|
|
||||||
<>
|
|
||||||
{systemStatus?.host ? (
|
{systemStatus?.host ? (
|
||||||
<>
|
<>
|
||||||
{actionBtnLoadingState.isLoading && <Icon.Loader className="w-4 h-auto animate-spin" />}
|
{actionBtnLoadingState.isLoading && <Icon.Loader className="w-4 h-auto animate-spin" />}
|
||||||
@ -154,10 +141,7 @@ const Auth = () => {
|
|||||||
<span className="mr-2 font-mono text-gray-200">/</span>
|
<span className="mr-2 font-mono text-gray-200">/</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<button
|
<button className={`btn signin-btn ${actionBtnLoadingState.isLoading ? "requesting" : ""}`} onClick={handleSigninBtnsClick}>
|
||||||
className={`btn signin-btn ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
|
|
||||||
onClick={handleSigninBtnsClick}
|
|
||||||
>
|
|
||||||
{t("common.sign-in")}
|
{t("common.sign-in")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
@ -171,8 +155,6 @@ const Auth = () => {
|
|||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{!systemStatus?.host && <p className="tip-text">{t("auth.host-tip")}</p>}
|
{!systemStatus?.host && <p className="tip-text">{t("auth.host-tip")}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createBrowserRouter, redirect } from "react-router-dom";
|
import { createBrowserRouter, redirect } from "react-router-dom";
|
||||||
import { isNullorUndefined } from "../helpers/utils";
|
import { isNullorUndefined } from "../helpers/utils";
|
||||||
import { userService } from "../services";
|
import { globalService, userService } from "../services";
|
||||||
import Auth from "../pages/Auth";
|
import Auth from "../pages/Auth";
|
||||||
import Explore from "../pages/Explore";
|
import Explore from "../pages/Explore";
|
||||||
import Home from "../pages/Home";
|
import Home from "../pages/Home";
|
||||||
@ -10,12 +10,20 @@ const router = createBrowserRouter([
|
|||||||
{
|
{
|
||||||
path: "/auth",
|
path: "/auth",
|
||||||
element: <Auth />,
|
element: <Auth />,
|
||||||
|
loader: async () => {
|
||||||
|
try {
|
||||||
|
await globalService.initialState();
|
||||||
|
} catch (error) {
|
||||||
|
// do nth
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
element: <Home />,
|
element: <Home />,
|
||||||
loader: async () => {
|
loader: async () => {
|
||||||
try {
|
try {
|
||||||
|
await globalService.initialState();
|
||||||
await userService.initialState();
|
await userService.initialState();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// do nth
|
// do nth
|
||||||
@ -34,6 +42,7 @@ const router = createBrowserRouter([
|
|||||||
element: <Home />,
|
element: <Home />,
|
||||||
loader: async () => {
|
loader: async () => {
|
||||||
try {
|
try {
|
||||||
|
await globalService.initialState();
|
||||||
await userService.initialState();
|
await userService.initialState();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// do nth
|
// do nth
|
||||||
@ -50,6 +59,7 @@ const router = createBrowserRouter([
|
|||||||
element: <Explore />,
|
element: <Explore />,
|
||||||
loader: async () => {
|
loader: async () => {
|
||||||
try {
|
try {
|
||||||
|
await globalService.initialState();
|
||||||
await userService.initialState();
|
await userService.initialState();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// do nth
|
// do nth
|
||||||
@ -66,6 +76,7 @@ const router = createBrowserRouter([
|
|||||||
element: <MemoDetail />,
|
element: <MemoDetail />,
|
||||||
loader: async () => {
|
loader: async () => {
|
||||||
try {
|
try {
|
||||||
|
await globalService.initialState();
|
||||||
await userService.initialState();
|
await userService.initialState();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// do nth
|
// do nth
|
||||||
|
@ -2,7 +2,6 @@ import store from "../store";
|
|||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import * as storage from "../helpers/storage";
|
import * as storage from "../helpers/storage";
|
||||||
import { setGlobalState, setLocale } from "../store/modules/global";
|
import { setGlobalState, setLocale } from "../store/modules/global";
|
||||||
import { convertResponseModelUser } from "./userService";
|
|
||||||
|
|
||||||
const globalService = {
|
const globalService = {
|
||||||
getState: () => {
|
getState: () => {
|
||||||
@ -12,19 +11,22 @@ const globalService = {
|
|||||||
initialState: async () => {
|
initialState: async () => {
|
||||||
const defaultGlobalState = {
|
const defaultGlobalState = {
|
||||||
locale: "en" as Locale,
|
locale: "en" as Locale,
|
||||||
|
systemStatus: {
|
||||||
|
allowSignUp: false,
|
||||||
|
additionalStyle: "",
|
||||||
|
additionalScript: "",
|
||||||
|
} as SystemStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { locale: storageLocale } = storage.get(["locale"]);
|
const { locale: storageLocale } = storage.get(["locale"]);
|
||||||
if (storageLocale) {
|
if (storageLocale) {
|
||||||
defaultGlobalState.locale = storageLocale;
|
defaultGlobalState.locale = storageLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { data } = (await api.getMyselfUser()).data;
|
const { data } = (await api.getSystemStatus()).data;
|
||||||
if (data) {
|
if (data) {
|
||||||
const user = convertResponseModelUser(data);
|
defaultGlobalState.systemStatus = data;
|
||||||
if (user.setting.locale) {
|
|
||||||
defaultGlobalState.locale = user.setting.locale;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// do nth
|
// do nth
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { locationService } from ".";
|
import { globalService, locationService } from ".";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import { UNKNOWN_ID } from "../helpers/consts";
|
import { UNKNOWN_ID } from "../helpers/consts";
|
||||||
import store from "../store";
|
import store from "../store";
|
||||||
|
import { setLocale } from "../store/modules/global";
|
||||||
import { setUser, patchUser, setHost, setOwner } from "../store/modules/user";
|
import { setUser, patchUser, setHost, setOwner } from "../store/modules/user";
|
||||||
|
|
||||||
const defauleSetting: Setting = {
|
const defauleSetting: Setting = {
|
||||||
@ -35,11 +36,9 @@ const userService = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
initialState: async () => {
|
initialState: async () => {
|
||||||
const {
|
const { systemStatus } = globalService.getState();
|
||||||
data: { host },
|
if (systemStatus.host) {
|
||||||
} = (await api.getSystemStatus()).data;
|
store.dispatch(setHost(convertResponseModelUser(systemStatus.host)));
|
||||||
if (host) {
|
|
||||||
store.dispatch(setHost(convertResponseModelUser(host)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerUserId = userService.getUserIdFromPath();
|
const ownerUserId = userService.getUserIdFromPath();
|
||||||
@ -53,6 +52,9 @@ const userService = {
|
|||||||
const { data: user } = (await api.getMyselfUser()).data;
|
const { data: user } = (await api.getMyselfUser()).data;
|
||||||
if (user) {
|
if (user) {
|
||||||
store.dispatch(setUser(convertResponseModelUser(user)));
|
store.dispatch(setUser(convertResponseModelUser(user)));
|
||||||
|
if (user.setting.locale) {
|
||||||
|
store.dispatch(setLocale(user.setting.locale));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2,11 +2,25 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
locale: Locale;
|
locale: Locale;
|
||||||
|
systemStatus: SystemStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const globalSlice = createSlice({
|
const globalSlice = createSlice({
|
||||||
name: "global",
|
name: "global",
|
||||||
initialState: {} as State,
|
initialState: {
|
||||||
|
locale: "en",
|
||||||
|
systemStatus: {
|
||||||
|
host: undefined,
|
||||||
|
profile: {
|
||||||
|
mode: "dev",
|
||||||
|
version: "",
|
||||||
|
},
|
||||||
|
dbSize: 0,
|
||||||
|
allowSignUp: false,
|
||||||
|
additionalStyle: "",
|
||||||
|
additionalScript: "",
|
||||||
|
},
|
||||||
|
} as State,
|
||||||
reducers: {
|
reducers: {
|
||||||
setGlobalState: (_, action: PayloadAction<State>) => {
|
setGlobalState: (_, action: PayloadAction<State>) => {
|
||||||
return action.payload;
|
return action.payload;
|
||||||
|
2
web/src/types/modules/system.d.ts
vendored
2
web/src/types/modules/system.d.ts
vendored
@ -4,7 +4,7 @@ interface Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface SystemStatus {
|
interface SystemStatus {
|
||||||
host: User;
|
host?: User;
|
||||||
profile: Profile;
|
profile: Profile;
|
||||||
dbSize: number;
|
dbSize: number;
|
||||||
// System settings
|
// System settings
|
||||||
|
Loading…
x
Reference in New Issue
Block a user