mirror of
https://github.com/usememos/memos.git
synced 2024-12-22 10:41:30 +03:00
chore: update i18n for auth page
This commit is contained in:
parent
84a3548232
commit
b596d04939
@ -20,10 +20,7 @@ const GitHubBadge: React.FC<Props> = () => {
|
|||||||
<Icon.GitHub className="icon-img" />
|
<Icon.GitHub className="icon-img" />
|
||||||
Star
|
Star
|
||||||
</div>
|
</div>
|
||||||
<div className="count-text">
|
<div className="count-text">{starCount || ""}</div>
|
||||||
{starCount || ""}
|
|
||||||
<span className="icon-text">🌟</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -49,11 +49,15 @@ const MenuBtnsPopup: React.FC<Props> = (props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSignOutBtnClick = async () => {
|
const handleSignOutBtnClick = async () => {
|
||||||
userService.doSignOut().catch(() => {
|
userService
|
||||||
|
.doSignOut()
|
||||||
|
.then(() => {
|
||||||
|
locationService.replaceHistory("/auth");
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
// do nth
|
// do nth
|
||||||
});
|
});
|
||||||
locationService.replaceHistory("/signin");
|
|
||||||
window.location.reload();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
105
web/src/less/auth.less
Normal file
105
web/src/less/auth.less
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
@import "./mixin.less";
|
||||||
|
|
||||||
|
.page-wrapper.auth {
|
||||||
|
@apply flex flex-row justify-center items-center w-full h-screen bg-white;
|
||||||
|
|
||||||
|
> .page-container {
|
||||||
|
@apply w-80 max-w-full h-full py-4 flex flex-col justify-start items-center;
|
||||||
|
|
||||||
|
> .auth-form-wrapper {
|
||||||
|
@apply w-full py-4 grow flex flex-col justify-center items-center;
|
||||||
|
|
||||||
|
> .page-header-container {
|
||||||
|
@apply flex flex-col justify-start items-start w-full mb-4;
|
||||||
|
|
||||||
|
> .title-container {
|
||||||
|
@apply w-full flex flex-row justify-between items-center;
|
||||||
|
|
||||||
|
> .title-text {
|
||||||
|
@apply text-2xl mb-2;
|
||||||
|
|
||||||
|
> .icon-text {
|
||||||
|
@apply text-4xl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .slogan-text {
|
||||||
|
@apply text-sm text-gray-700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .page-content-container {
|
||||||
|
@apply flex flex-col justify-start items-start w-full;
|
||||||
|
|
||||||
|
> .form-item-container {
|
||||||
|
@apply flex flex-col justify-start items-start relative w-full text-base mt-2;
|
||||||
|
|
||||||
|
> .normal-text {
|
||||||
|
@apply absolute top-3 left-3 px-1 leading-10 flex-shrink-0 text-base cursor-text text-gray-400 bg-transparent transition-all select-none;
|
||||||
|
|
||||||
|
&.not-null {
|
||||||
|
@apply text-sm top-0 z-10 leading-4 bg-white rounded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.input-form-container {
|
||||||
|
@apply py-2;
|
||||||
|
|
||||||
|
> input {
|
||||||
|
@apply w-full py-3 px-3 text-base shadow-inner rounded-lg border border-solid border-gray-400 hover:opacity-80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.requesting {
|
||||||
|
@apply opacity-80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .action-btns-container {
|
||||||
|
@apply flex flex-row justify-end items-center w-full mt-2;
|
||||||
|
|
||||||
|
> .btn {
|
||||||
|
@apply px-1 py-2 text-sm rounded hover:opacity-80;
|
||||||
|
|
||||||
|
&.signin-btn {
|
||||||
|
@apply bg-green-600 text-white px-3 shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.requesting {
|
||||||
|
@apply cursor-wait opacity-80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tip-text {
|
||||||
|
@apply w-full inline-block float-right text-sm mt-4 text-gray-500 text-right whitespace-pre-wrap;
|
||||||
|
|
||||||
|
&.host-tip {
|
||||||
|
@apply bg-blue-500 text-white px-2 py-1 rounded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .footer-container {
|
||||||
|
@apply w-full flex flex-col justify-start items-center;
|
||||||
|
|
||||||
|
> .language-container {
|
||||||
|
@apply mt-2 w-full flex flex-row justify-center items-center text-sm text-gray-400;
|
||||||
|
|
||||||
|
> .locale-item {
|
||||||
|
@apply px-2 cursor-pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
@apply text-blue-600 font-bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .split-line {
|
||||||
|
@apply font-mono text-gray-400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
@apply h-7 flex flex-row justify-start items-center border rounded cursor-pointer hover:opacity-80;
|
@apply h-7 flex flex-row justify-start items-center border rounded cursor-pointer hover:opacity-80;
|
||||||
|
|
||||||
> .github-icon {
|
> .github-icon {
|
||||||
@apply w-auto h-full px-2 border-r rounded-l flex flex-row justify-center items-center text-xs font-bold text-gray-800 bg-gray-100;
|
@apply w-auto h-full px-2 border-r rounded-l flex flex-row justify-center items-center text-xs text-gray-800 bg-gray-100;
|
||||||
|
|
||||||
> .icon-img {
|
> .icon-img {
|
||||||
@apply mr-1 w-4 h-4;
|
@apply mr-1 w-4 h-4;
|
||||||
@ -11,24 +11,5 @@
|
|||||||
|
|
||||||
> .count-text {
|
> .count-text {
|
||||||
@apply w-auto h-full flex flex-row justify-center items-center px-3 text-xs font-bold text-gray-800;
|
@apply w-auto h-full flex flex-row justify-center items-center px-3 text-xs font-bold text-gray-800;
|
||||||
|
|
||||||
> .icon-text {
|
|
||||||
@apply text-sm ml-1;
|
|
||||||
animation: 1.6s linear 0s infinite pulse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0% {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
70% {
|
|
||||||
transform: scale(1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
@import "./mixin.less";
|
|
||||||
|
|
||||||
.page-wrapper.signin {
|
|
||||||
@apply flex flex-row justify-center items-center w-full min-h-screen bg-white;
|
|
||||||
|
|
||||||
> .page-container {
|
|
||||||
@apply w-80 max-w-full py-4 -mt-16;
|
|
||||||
|
|
||||||
> .page-header-container {
|
|
||||||
@apply flex flex-col justify-start items-start w-full mb-4;
|
|
||||||
|
|
||||||
> .title-container {
|
|
||||||
@apply w-full flex flex-row justify-between items-center;
|
|
||||||
|
|
||||||
> .title-text {
|
|
||||||
@apply text-2xl mb-2;
|
|
||||||
|
|
||||||
> .icon-text {
|
|
||||||
@apply text-4xl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .slogan-text {
|
|
||||||
@apply text-sm text-gray-700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .page-content-container {
|
|
||||||
@apply flex flex-col justify-start items-start w-full;
|
|
||||||
|
|
||||||
> .form-item-container {
|
|
||||||
@apply flex flex-col justify-start items-start relative w-full text-base mt-2;
|
|
||||||
|
|
||||||
> .normal-text {
|
|
||||||
@apply absolute top-3 left-3 px-1 leading-10 flex-shrink-0 text-base cursor-text text-gray-400 bg-transparent transition-all select-none;
|
|
||||||
|
|
||||||
&.not-null {
|
|
||||||
@apply text-sm top-0 z-10 leading-4 bg-white rounded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.input-form-container {
|
|
||||||
@apply py-2;
|
|
||||||
|
|
||||||
> input {
|
|
||||||
@apply w-full py-3 px-3 text-base shadow-inner rounded-lg border border-solid border-gray-400 hover:opacity-80;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.requesting {
|
|
||||||
@apply opacity-80;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .action-btns-container {
|
|
||||||
@apply flex flex-row justify-end items-center w-full mt-2;
|
|
||||||
|
|
||||||
> .btn {
|
|
||||||
@apply px-1 py-2 text-sm rounded hover:opacity-80;
|
|
||||||
|
|
||||||
&.signin-btn {
|
|
||||||
@apply bg-green-600 text-white px-3 shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.requesting {
|
|
||||||
@apply cursor-wait opacity-80;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .tip-text {
|
|
||||||
@apply w-auto inline-block float-right text-sm mt-4 text-gray-500 text-right whitespace-pre-wrap;
|
|
||||||
|
|
||||||
&.host-tip {
|
|
||||||
@apply bg-blue-500 text-white px-2 py-1 rounded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,5 +4,11 @@
|
|||||||
"email": "Email",
|
"email": "Email",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"sign-in": "Sign in"
|
"sign-in": "Sign in"
|
||||||
|
},
|
||||||
|
"slogan": "An open source, self-hosted knowledge base that works with a SQLite db file.",
|
||||||
|
"auth": {
|
||||||
|
"signup-as-host": "Sign up as Host",
|
||||||
|
"host-tip": "You are registering as the Site Host.",
|
||||||
|
"not-host-tip": "If you don't have an account, please contact the site host."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,11 @@
|
|||||||
"email": "邮箱",
|
"email": "邮箱",
|
||||||
"password": "密码",
|
"password": "密码",
|
||||||
"sign-in": "登录"
|
"sign-in": "登录"
|
||||||
|
},
|
||||||
|
"slogan": "一个开源的、支持私有化部署的碎片化知识卡片管理工具。",
|
||||||
|
"auth": {
|
||||||
|
"signup-as-host": "注册为 Host",
|
||||||
|
"host-tip": "你正在注册为 Host 用户账号。",
|
||||||
|
"not-host-tip": "如果你没有账号,请联系站点 Host"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ import * as api from "../helpers/api";
|
|||||||
import { validate, ValidatorConfig } from "../helpers/validator";
|
import { validate, ValidatorConfig } from "../helpers/validator";
|
||||||
import useI18n from "../hooks/useI18n";
|
import useI18n from "../hooks/useI18n";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
import { locationService, userService } from "../services";
|
import { globalService, locationService, userService } from "../services";
|
||||||
import toastHelper from "../components/Toast";
|
import toastHelper from "../components/Toast";
|
||||||
import GitHubBadge from "../components/GitHubBadge";
|
import GitHubBadge from "../components/GitHubBadge";
|
||||||
import "../less/signin.less";
|
import "../less/auth.less";
|
||||||
|
|
||||||
interface Props {}
|
interface Props {}
|
||||||
|
|
||||||
@ -17,8 +17,8 @@ const validateConfig: ValidatorConfig = {
|
|||||||
noChinese: true,
|
noChinese: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Signin: React.FC<Props> = () => {
|
const Auth: React.FC<Props> = () => {
|
||||||
const { t } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const pageLoadingState = useLoading(true);
|
const pageLoadingState = useLoading(true);
|
||||||
const [siteHost, setSiteHost] = useState<User>();
|
const [siteHost, setSiteHost] = useState<User>();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@ -113,9 +113,14 @@ const Signin: React.FC<Props> = () => {
|
|||||||
actionBtnLoadingState.setFinish();
|
actionBtnLoadingState.setFinish();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleLocaleItemClick = (locale: Locale) => {
|
||||||
|
globalService.setLocale(locale);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page-wrapper signin">
|
<div className="page-wrapper auth">
|
||||||
<div className="page-container">
|
<div className="page-container">
|
||||||
|
<div className="auth-form-wrapper">
|
||||||
<div className="page-header-container">
|
<div className="page-header-container">
|
||||||
<div className="title-container">
|
<div className="title-container">
|
||||||
<p className="title-text">
|
<p className="title-text">
|
||||||
@ -123,9 +128,7 @@ const Signin: React.FC<Props> = () => {
|
|||||||
</p>
|
</p>
|
||||||
<GitHubBadge />
|
<GitHubBadge />
|
||||||
</div>
|
</div>
|
||||||
<p className="slogan-text">
|
<p className="slogan-text">{t("slogan")}</p>
|
||||||
An <i>open source</i>, <i>self-hosted</i> knowledge base that works with a SQLite db file.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={`page-content-container ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}>
|
<div className={`page-content-container ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}>
|
||||||
<div className="form-item-container input-form-container">
|
<div className="form-item-container input-form-container">
|
||||||
@ -150,18 +153,28 @@ const Signin: React.FC<Props> = () => {
|
|||||||
className={`btn signin-btn ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
|
className={`btn signin-btn ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
|
||||||
onClick={() => handleSignUpAsHostBtnsClick()}
|
onClick={() => handleSignUpAsHostBtnsClick()}
|
||||||
>
|
>
|
||||||
Sign up as Host
|
{t("auth.signup-as-host")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className={`tip-text ${siteHost || pageLoadingState.isLoading ? "" : "host-tip"}`}>
|
<p className={`tip-text ${siteHost || pageLoadingState.isLoading ? "" : "host-tip"}`}>
|
||||||
{siteHost || pageLoadingState.isLoading
|
{siteHost || pageLoadingState.isLoading ? t("auth.not-host-tip") : t("auth.host-tip")}
|
||||||
? "If you don't have an account, please\ncontact the site host."
|
|
||||||
: "You are registering as the Site Host."}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="footer-container">
|
||||||
|
<div className="language-container">
|
||||||
|
<span className={`locale-item ${locale === "en" ? "active" : ""}`} onClick={() => handleLocaleItemClick("en")}>
|
||||||
|
English
|
||||||
|
</span>
|
||||||
|
<span className="split-line">/</span>
|
||||||
|
<span className={`locale-item ${locale === "zh" ? "active" : ""}`} onClick={() => handleLocaleItemClick("zh")}>
|
||||||
|
中文
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Signin;
|
export default Auth;
|
@ -23,7 +23,7 @@ function Home() {
|
|||||||
.finally(async () => {
|
.finally(async () => {
|
||||||
const { host, owner, user } = userService.getState();
|
const { host, owner, user } = userService.getState();
|
||||||
if (!host) {
|
if (!host) {
|
||||||
locationService.replaceHistory("/signin");
|
locationService.replaceHistory("/auth");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ function Home() {
|
|||||||
<span className="icon">🏠</span> Back to Home
|
<span className="icon">🏠</span> Back to Home
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button className="btn" onClick={() => (window.location.href = "/signin")}>
|
<button className="btn" onClick={() => (window.location.href = "/auth")}>
|
||||||
<span className="icon">👉</span> Sign in
|
<span className="icon">👉</span> Sign in
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import Home from "../pages/Home";
|
import Home from "../pages/Home";
|
||||||
import Signin from "../pages/Signin";
|
import Auth from "../pages/Auth";
|
||||||
|
|
||||||
const appRouter = {
|
const appRouter = {
|
||||||
"/signin": <Signin />,
|
"/auth": <Auth />,
|
||||||
"*": <Home />,
|
"*": <Home />,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ interface State {
|
|||||||
|
|
||||||
const getValidPathname = (pathname: string): string => {
|
const getValidPathname = (pathname: string): string => {
|
||||||
const userPageUrlRegex = /^\/u\/\d+.*/;
|
const userPageUrlRegex = /^\/u\/\d+.*/;
|
||||||
if (["/", "/signin"].includes(pathname) || userPageUrlRegex.test(pathname)) {
|
if (["/", "/auth"].includes(pathname) || userPageUrlRegex.test(pathname)) {
|
||||||
return pathname;
|
return pathname;
|
||||||
} else {
|
} else {
|
||||||
return "/";
|
return "/";
|
||||||
|
Loading…
Reference in New Issue
Block a user