aboutsummaryrefslogtreecommitdiff
path: root/Timeline/ClientApp/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-09-03 18:56:40 +0800
committercrupest <crupest@outlook.com>2020-09-03 18:56:40 +0800
commit880ed701d5ae3f3b21b30d3b9e2db5d98d6b9513 (patch)
tree15f1fab11da36d9f2257fbc13396ea517ac32840 /Timeline/ClientApp/src
parent2be72885e2d49a5637c2741e1844dfe92d3e197e (diff)
downloadtimeline-880ed701d5ae3f3b21b30d3b9e2db5d98d6b9513.tar.gz
timeline-880ed701d5ae3f3b21b30d3b9e2db5d98d6b9513.tar.bz2
timeline-880ed701d5ae3f3b21b30d3b9e2db5d98d6b9513.zip
Move AppBar to App .
Diffstat (limited to 'Timeline/ClientApp/src')
-rw-r--r--Timeline/ClientApp/src/app/App.tsx75
-rw-r--r--Timeline/ClientApp/src/app/views/about/index.tsx156
-rw-r--r--Timeline/ClientApp/src/app/views/admin/Admin.tsx2
-rw-r--r--Timeline/ClientApp/src/app/views/home/index.tsx2
-rw-r--r--Timeline/ClientApp/src/app/views/login/index.tsx151
-rw-r--r--Timeline/ClientApp/src/app/views/settings/index.tsx170
-rw-r--r--Timeline/ClientApp/src/app/views/timeline-common/TimelinePageTemplateUI.tsx7
7 files changed, 268 insertions, 295 deletions
diff --git a/Timeline/ClientApp/src/app/App.tsx b/Timeline/ClientApp/src/app/App.tsx
index b64414b7..b68eddb6 100644
--- a/Timeline/ClientApp/src/app/App.tsx
+++ b/Timeline/ClientApp/src/app/App.tsx
@@ -11,6 +11,7 @@ import About from "./views/about";
import User from "./views/user";
import TimelinePage from "./views/timeline";
import AlertHost from "./views/common/alert/AlertHost";
+
import { dataStorage } from "./services/common";
import { userService, useRawUser } from "./services/user";
@@ -38,50 +39,46 @@ const App: React.FC = () => {
void dataStorage.ready().then(() => setLoading(false));
}, []);
- let body;
if (user === undefined || loading) {
- body = <LoadingPage />;
+ return <LoadingPage />;
} else {
- body = (
- <Router>
- <Switch>
- <Route exact path="/">
- <Home />
- </Route>
- <Route exact path="/login">
- <Login />
- </Route>
- <Route path="/settings">
- <Settings />
- </Route>
- <Route path="/about">
- <About />
- </Route>
- <Route path="/timelines/:name">
- <TimelinePage />
- </Route>
- <Route path="/users/:username">
- <User />
- </Route>
- {user && user.administrator && (
- <Route path="/admin">
- <LazyAdmin user={user} />
+ return (
+ <React.Suspense fallback={<LoadingPage />}>
+ <Router>
+ <AppBar />
+ <Switch>
+ <Route exact path="/">
+ <Home />
+ </Route>
+ <Route exact path="/login">
+ <Login />
+ </Route>
+ <Route path="/settings">
+ <Settings />
+ </Route>
+ <Route path="/about">
+ <About />
+ </Route>
+ <Route path="/timelines/:name">
+ <TimelinePage />
</Route>
- )}
- <Route>
- <NoMatch />
- </Route>
- </Switch>
- </Router>
+ <Route path="/users/:username">
+ <User />
+ </Route>
+ {user && user.administrator && (
+ <Route path="/admin">
+ <LazyAdmin user={user} />
+ </Route>
+ )}
+ <Route>
+ <NoMatch />
+ </Route>
+ </Switch>
+ <AlertHost />
+ </Router>
+ </React.Suspense>
);
}
-
- return (
- <React.Suspense fallback={<LoadingPage />}>
- {body}
- <AlertHost />
- </React.Suspense>
- );
};
export default hot(App);
diff --git a/Timeline/ClientApp/src/app/views/about/index.tsx b/Timeline/ClientApp/src/app/views/about/index.tsx
index 78cffb5f..e7771cec 100644
--- a/Timeline/ClientApp/src/app/views/about/index.tsx
+++ b/Timeline/ClientApp/src/app/views/about/index.tsx
@@ -1,8 +1,6 @@
import React from "react";
import { useTranslation, Trans } from "react-i18next";
-import AppBar from "../common/AppBar";
-
import authorAvatarUrl from "./author-avatar.png";
import githubLogoUrl from "./github.png";
@@ -75,97 +73,91 @@ const AboutPage: React.FC = () => {
const { t } = useTranslation();
return (
- <>
- <AppBar />
- <div className="mt-appbar px-2 mb-4">
- <div className="container mt-4 py-3 shadow border border-primary rounded bg-light">
- <h4 id="author-info">{t("about.author.title")}</h4>
- <div>
- <div className="d-flex">
- <img
- src={authorAvatarUrl}
- className="align-self-start avatar large rounded-circle"
- />
- <div>
- <p>
- <small>{t("about.author.fullname")}</small>
- <span className="text-primary">杨宇千</span>
- </p>
- <p>
- <small>{t("about.author.nickname")}</small>
- <span className="text-primary">crupest</span>
- </p>
- <p>
- <small>{t("about.author.introduction")}</small>
- {t("about.author.introductionContent")}
- </p>
- </div>
+ <div className="mt-appbar px-2 mb-4">
+ <div className="container mt-4 py-3 shadow border border-primary rounded bg-light">
+ <h4 id="author-info">{t("about.author.title")}</h4>
+ <div>
+ <div className="d-flex">
+ <img
+ src={authorAvatarUrl}
+ className="align-self-start avatar large rounded-circle"
+ />
+ <div>
+ <p>
+ <small>{t("about.author.fullname")}</small>
+ <span className="text-primary">杨宇千</span>
+ </p>
+ <p>
+ <small>{t("about.author.nickname")}</small>
+ <span className="text-primary">crupest</span>
+ </p>
+ <p>
+ <small>{t("about.author.introduction")}</small>
+ {t("about.author.introductionContent")}
+ </p>
</div>
- <p>
- <small>{t("about.author.links")}</small>
- <a
- href="https://github.com/crupest"
- target="_blank"
- rel="noopener noreferrer"
- >
- <img
- src={githubLogoUrl}
- className="about-link-icon text-body"
- />
- </a>
- </p>
</div>
- </div>
- <div className="container mt-4 py-3 shadow border border-primary rounded bg-light">
- <h4>{t("about.site.title")}</h4>
- <p>
- <Trans i18nKey="about.site.content">
- 0<span className="text-primary">1</span>2<b>3</b>4
- <a href="#author-info">5</a>6
- </Trans>
- </p>
<p>
+ <small>{t("about.author.links")}</small>
<a
- href="https://github.com/crupest/Timeline"
+ href="https://github.com/crupest"
target="_blank"
rel="noopener noreferrer"
>
- {t("about.site.repo")}
+ <img src={githubLogoUrl} className="about-link-icon text-body" />
</a>
</p>
</div>
- <div className="container mt-4 py-3 shadow border border-primary rounded bg-light">
- <h4>{t("about.credits.title")}</h4>
- <p>{t("about.credits.content")}</p>
- <p>{t("about.credits.frontend")}</p>
- <ul>
- {frontendCredits.map((item, index) => {
- return (
- <li key={index}>
- <a href={item.url} target="_blank" rel="noopener noreferrer">
- {item.name}
- </a>
- </li>
- );
- })}
- <li>...</li>
- </ul>
- <p>{t("about.credits.backend")}</p>
- <ul>
- {backendCredits.map((item, index) => {
- return (
- <li key={index}>
- <a href={item.url} target="_blank" rel="noopener noreferrer">
- {item.name}
- </a>
- </li>
- );
- })}
- <li>...</li>
- </ul>
- </div>
</div>
- </>
+ <div className="container mt-4 py-3 shadow border border-primary rounded bg-light">
+ <h4>{t("about.site.title")}</h4>
+ <p>
+ <Trans i18nKey="about.site.content">
+ 0<span className="text-primary">1</span>2<b>3</b>4
+ <a href="#author-info">5</a>6
+ </Trans>
+ </p>
+ <p>
+ <a
+ href="https://github.com/crupest/Timeline"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ {t("about.site.repo")}
+ </a>
+ </p>
+ </div>
+ <div className="container mt-4 py-3 shadow border border-primary rounded bg-light">
+ <h4>{t("about.credits.title")}</h4>
+ <p>{t("about.credits.content")}</p>
+ <p>{t("about.credits.frontend")}</p>
+ <ul>
+ {frontendCredits.map((item, index) => {
+ return (
+ <li key={index}>
+ <a href={item.url} target="_blank" rel="noopener noreferrer">
+ {item.name}
+ </a>
+ </li>
+ );
+ })}
+ <li>...</li>
+ </ul>
+ <p>{t("about.credits.backend")}</p>
+ <ul>
+ {backendCredits.map((item, index) => {
+ return (
+ <li key={index}>
+ <a href={item.url} target="_blank" rel="noopener noreferrer">
+ {item.name}
+ </a>
+ </li>
+ );
+ })}
+ <li>...</li>
+ </ul>
+ </div>
+ </div>
);
};
diff --git a/Timeline/ClientApp/src/app/views/admin/Admin.tsx b/Timeline/ClientApp/src/app/views/admin/Admin.tsx
index e0f59b0f..9c0250e7 100644
--- a/Timeline/ClientApp/src/app/views/admin/Admin.tsx
+++ b/Timeline/ClientApp/src/app/views/admin/Admin.tsx
@@ -8,7 +8,6 @@ import {
} from "react-router";
import { Nav } from "react-bootstrap";
-import AppBar from "../common/AppBar";
import { UserWithToken } from "@/services/user";
import UserAdmin from "./UserAdmin";
@@ -34,7 +33,6 @@ const Admin: React.FC<AdminProps> = (props) => {
): React.ReactNode => {
return (
<Route path={`${match.path}/${name}`}>
- <AppBar />
<div style={{ height: 56 }} className="flex-fix-length" />
<Nav variant="tabs">
<Nav.Item>
diff --git a/Timeline/ClientApp/src/app/views/home/index.tsx b/Timeline/ClientApp/src/app/views/home/index.tsx
index e2e3e6f9..11672c10 100644
--- a/Timeline/ClientApp/src/app/views/home/index.tsx
+++ b/Timeline/ClientApp/src/app/views/home/index.tsx
@@ -4,7 +4,6 @@ import { useTranslation } from "react-i18next";
import { Row, Container, Button, Col } from "react-bootstrap";
import { useUser } from "@/services/user";
-import AppBar from "../common/AppBar";
import SearchInput from "../common/SearchInput";
import BoardWithoutUser from "./BoardWithoutUser";
@@ -34,7 +33,6 @@ const HomePage: React.FC = () => {
return (
<>
- <AppBar />
<Container fluid>
<Row>
<Col>
diff --git a/Timeline/ClientApp/src/app/views/login/index.tsx b/Timeline/ClientApp/src/app/views/login/index.tsx
index 545fc05a..a3071264 100644
--- a/Timeline/ClientApp/src/app/views/login/index.tsx
+++ b/Timeline/ClientApp/src/app/views/login/index.tsx
@@ -1,7 +1,7 @@
-import React, { Fragment, useState, useEffect } from "react";
+import React from "react";
import { useHistory } from "react-router";
import { useTranslation } from "react-i18next";
-import { Form, Spinner, Button } from "react-bootstrap";
+import { Form } from "react-bootstrap";
import { useUser, userService } from "@/services/user";
@@ -11,17 +11,17 @@ import LoadingButton from "../common/LoadingButton";
const LoginPage: React.FC = (_) => {
const { t } = useTranslation();
const history = useHistory();
- const [username, setUsername] = useState<string>("");
- const [usernameDirty, setUsernameDirty] = useState<boolean>(false);
- const [password, setPassword] = useState<string>("");
- const [passwordDirty, setPasswordDirty] = useState<boolean>(false);
- const [rememberMe, setRememberMe] = useState<boolean>(true);
- const [process, setProcess] = useState<boolean>(false);
- const [error, setError] = useState<string | null>(null);
+ const [username, setUsername] = React.useState<string>("");
+ const [usernameDirty, setUsernameDirty] = React.useState<boolean>(false);
+ const [password, setPassword] = React.useState<string>("");
+ const [passwordDirty, setPasswordDirty] = React.useState<boolean>(false);
+ const [rememberMe, setRememberMe] = React.useState<boolean>(true);
+ const [process, setProcess] = React.useState<boolean>(false);
+ const [error, setError] = React.useState<string | null>(null);
const user = useUser();
- useEffect(() => {
+ React.useEffect(() => {
if (user != null) {
const id = setTimeout(() => history.push("/"), 3000);
return () => {
@@ -72,73 +72,70 @@ const LoginPage: React.FC = (_) => {
}
return (
- <Fragment>
- <AppBar />
- <div className="container login-container mt-appbar">
- <h1>{t("welcome")}</h1>
- <Form>
- <Form.Group>
- <Form.Label htmlFor="username">{t("user.username")}</Form.Label>
- <Form.Control
- id="username"
- disabled={process}
- onChange={(e) => {
- setUsername(e.target.value);
- setUsernameDirty(true);
- }}
- value={username}
- isInvalid={usernameDirty && username === ""}
- />
- {usernameDirty && username === "" && (
- <Form.Control.Feedback type="invalid">
- {t("login.emptyUsername")}
- </Form.Control.Feedback>
- )}
- </Form.Group>
- <Form.Group>
- <Form.Label htmlFor="password">{t("user.password")}</Form.Label>
- <Form.Control
- id="password"
- type="password"
- disabled={process}
- onChange={(e) => {
- setPassword(e.target.value);
- setPasswordDirty(true);
- }}
- value={password}
- isInvalid={passwordDirty && password === ""}
- />
- {passwordDirty && password === "" && (
- <Form.Control.Feedback type="invalid">
- {t("login.emptyPassword")}
- </Form.Control.Feedback>
- )}
- </Form.Group>
- <Form.Group>
- <Form.Check<"input">
- id="remember-me"
- type="checkbox"
- checked={rememberMe}
- onChange={(e) => {
- setRememberMe(e.target.checked);
- }}
- label={t("user.rememberMe")}
- />
- </Form.Group>
- {error ? <p className="text-danger">{t(error)}</p> : null}
- <div className="text-right">
- <LoadingButton
- loading={process}
- variant="primary"
- onClick={onSubmit}
- disabled={username === "" || password === "" ? true : undefined}
- >
- {t("user.login")}
- </LoadingButton>
- </div>
- </Form>
- </div>
- </Fragment>
+ <div className="container login-container mt-appbar">
+ <h1>{t("welcome")}</h1>
+ <Form>
+ <Form.Group>
+ <Form.Label htmlFor="username">{t("user.username")}</Form.Label>
+ <Form.Control
+ id="username"
+ disabled={process}
+ onChange={(e) => {
+ setUsername(e.target.value);
+ setUsernameDirty(true);
+ }}
+ value={username}
+ isInvalid={usernameDirty && username === ""}
+ />
+ {usernameDirty && username === "" && (
+ <Form.Control.Feedback type="invalid">
+ {t("login.emptyUsername")}
+ </Form.Control.Feedback>
+ )}
+ </Form.Group>
+ <Form.Group>
+ <Form.Label htmlFor="password">{t("user.password")}</Form.Label>
+ <Form.Control
+ id="password"
+ type="password"
+ disabled={process}
+ onChange={(e) => {
+ setPassword(e.target.value);
+ setPasswordDirty(true);
+ }}
+ value={password}
+ isInvalid={passwordDirty && password === ""}
+ />
+ {passwordDirty && password === "" && (
+ <Form.Control.Feedback type="invalid">
+ {t("login.emptyPassword")}
+ </Form.Control.Feedback>
+ )}
+ </Form.Group>
+ <Form.Group>
+ <Form.Check<"input">
+ id="remember-me"
+ type="checkbox"
+ checked={rememberMe}
+ onChange={(e) => {
+ setRememberMe(e.target.checked);
+ }}
+ label={t("user.rememberMe")}
+ />
+ </Form.Group>
+ {error ? <p className="text-danger">{t(error)}</p> : null}
+ <div className="text-right">
+ <LoadingButton
+ loading={process}
+ variant="primary"
+ onClick={onSubmit}
+ disabled={username === "" || password === "" ? true : undefined}
+ >
+ {t("user.login")}
+ </LoadingButton>
+ </div>
+ </Form>
+ </div>
);
};
diff --git a/Timeline/ClientApp/src/app/views/settings/index.tsx b/Timeline/ClientApp/src/app/views/settings/index.tsx
index 123e1353..964e7442 100644
--- a/Timeline/ClientApp/src/app/views/settings/index.tsx
+++ b/Timeline/ClientApp/src/app/views/settings/index.tsx
@@ -4,7 +4,6 @@ import { useTranslation } from "react-i18next";
import { Form, Container, Row, Col, Button, Modal } from "react-bootstrap";
import { useUser, userService } from "@/services/user";
-import AppBar from "../common/AppBar";
import OperationDialog, {
OperationInputErrorInfo,
} from "../common/OperationDialog";
@@ -121,92 +120,89 @@ const SettingsPage: React.FC = (_) => {
const language = i18n.language.slice(0, 2);
return (
- <>
- <AppBar />
- <Container fluid>
- {user ? (
- <>
- <Row className="border-bottom p-3 cursor-pointer">
- <Col xs="12">
- <h5
- onClick={() => {
- history.push(`/users/${user.username}`);
- }}
- >
- {t("settings.gotoSelf")}
- </h5>
- </Col>
- </Row>
- <Row className="border-bottom p-3 cursor-pointer">
- <Col xs="12">
- <h5
- className="text-danger"
- onClick={() => setDialog("changepassword")}
- >
- {t("settings.changePassword")}
- </h5>
- </Col>
- </Row>
- <Row className="border-bottom p-3 cursor-pointer">
- <Col xs="12">
- <h5
- className="text-danger"
- onClick={() => {
- setDialog("logout");
- }}
- >
- {t("settings.logout")}
- </h5>
- </Col>
- </Row>
- </>
- ) : null}
- <Row className="align-items-center border-bottom p-3">
- <Col xs="12" sm="auto">
- <h5>{t("settings.languagePrimary")}</h5>
- <p>{t("settings.languageSecondary")}</p>
- </Col>
- <Col xs="auto" className="ml-auto">
- <Form.Control
- as="select"
- value={language}
- onChange={(e) => {
- void i18n.changeLanguage(e.target.value);
- }}
- >
- <option value="zh">中文</option>
- <option value="en">English</option>
- </Form.Control>
- </Col>
- </Row>
- {(() => {
- switch (dialog) {
- case "changepassword":
- return (
- <ChangePasswordDialog
- open
- close={() => {
- setDialog(null);
- }}
- />
- );
- case "logout":
- return (
- <ConfirmLogoutDialog
- toggle={() => setDialog(null)}
- onConfirm={() => {
- void userService.logout().then(() => {
- history.push("/");
- });
- }}
- />
- );
- default:
- return null;
- }
- })()}
- </Container>
- </>
+ <Container fluid>
+ {user ? (
+ <>
+ <Row className="border-bottom p-3 cursor-pointer">
+ <Col xs="12">
+ <h5
+ onClick={() => {
+ history.push(`/users/${user.username}`);
+ }}
+ >
+ {t("settings.gotoSelf")}
+ </h5>
+ </Col>
+ </Row>
+ <Row className="border-bottom p-3 cursor-pointer">
+ <Col xs="12">
+ <h5
+ className="text-danger"
+ onClick={() => setDialog("changepassword")}
+ >
+ {t("settings.changePassword")}
+ </h5>
+ </Col>
+ </Row>
+ <Row className="border-bottom p-3 cursor-pointer">
+ <Col xs="12">
+ <h5
+ className="text-danger"
+ onClick={() => {
+ setDialog("logout");
+ }}
+ >
+ {t("settings.logout")}
+ </h5>
+ </Col>
+ </Row>
+ </>
+ ) : null}
+ <Row className="align-items-center border-bottom p-3">
+ <Col xs="12" sm="auto">
+ <h5>{t("settings.languagePrimary")}</h5>
+ <p>{t("settings.languageSecondary")}</p>
+ </Col>
+ <Col xs="auto" className="ml-auto">
+ <Form.Control
+ as="select"
+ value={language}
+ onChange={(e) => {
+ void i18n.changeLanguage(e.target.value);
+ }}
+ >
+ <option value="zh">中文</option>
+ <option value="en">English</option>
+ </Form.Control>
+ </Col>
+ </Row>
+ {(() => {
+ switch (dialog) {
+ case "changepassword":
+ return (
+ <ChangePasswordDialog
+ open
+ close={() => {
+ setDialog(null);
+ }}
+ />
+ );
+ case "logout":
+ return (
+ <ConfirmLogoutDialog
+ toggle={() => setDialog(null)}
+ onConfirm={() => {
+ void userService.logout().then(() => {
+ history.push("/");
+ });
+ }}
+ />
+ );
+ default:
+ return null;
+ }
+ })()}
+ </Container>
);
};
diff --git a/Timeline/ClientApp/src/app/views/timeline-common/TimelinePageTemplateUI.tsx b/Timeline/ClientApp/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
index e25ed962..c33bc0e5 100644
--- a/Timeline/ClientApp/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
+++ b/Timeline/ClientApp/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
@@ -310,10 +310,5 @@ export default function TimelinePageTemplateUI<TManageItems>(
}
}
- return (
- <>
- <AppBar />
- {body}
- </>
- );
+ return body;
}