chore: update i18n for auth page

This commit is contained in:
Steven 2022-08-14 18:43:46 +08:00
parent 84a3548232
commit b596d04939
11 changed files with 190 additions and 159 deletions

View File

@ -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>
); );
}; };

View File

@ -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
View 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;
}
}
}
}
}

View File

@ -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);
} }
} }

View File

@ -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;
}
}
}
}

View File

@ -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."
} }
} }

View File

@ -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"
} }
} }

View File

@ -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;

View File

@ -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>
)} )}

View File

@ -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 />,
}; };

View File

@ -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 "/";