diff options
Diffstat (limited to 'FrontEnd/src')
-rw-r--r-- | FrontEnd/src/App.tsx | 63 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/Admin.tsx | 47 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/AdminNav.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/MoreAdmin.tsx | 8 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/UserAdmin.tsx | 13 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/index.tsx | 7 | ||||
-rw-r--r-- | FrontEnd/src/views/center/TimelineCreateDialog.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/center/index.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/home/index.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/login/index.tsx | 14 | ||||
-rw-r--r-- | FrontEnd/src/views/search/index.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/settings/ChangePasswordDialog.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/settings/index.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx | 2 | ||||
-rw-r--r-- | FrontEnd/src/views/timeline/TimelineDeleteDialog.tsx | 6 | ||||
-rw-r--r-- | FrontEnd/src/views/timeline/index.tsx | 10 | ||||
-rw-r--r-- | FrontEnd/src/views/user/index.tsx | 10 |
17 files changed, 91 insertions, 131 deletions
diff --git a/FrontEnd/src/App.tsx b/FrontEnd/src/App.tsx index 6497b071..69223abb 100644 --- a/FrontEnd/src/App.tsx +++ b/FrontEnd/src/App.tsx @@ -1,5 +1,5 @@ import React, { ReactElement } from "react"; -import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; +import { BrowserRouter, Route, Routes } from "react-router-dom"; import AppBar from "./views/common/AppBar"; import LoadingPage from "./views/common/LoadingPage"; @@ -11,6 +11,7 @@ import About from "./views/about"; import User from "./views/user"; import TimelinePage from "./views/timeline"; import Search from "./views/search"; +import Admin from "./views/admin"; import AlertHost from "./views/common/alert/AlertHost"; import { useUser } from "./services/user"; @@ -19,59 +20,29 @@ const NoMatch: React.FC = () => { return <div>Ah-oh, 404!</div>; }; -const LazyAdmin = React.lazy( - () => import(/* webpackChunkName: "admin" */ "./views/admin/Admin") -); - function App(): ReactElement | null { const user = useUser(); return ( <React.Suspense fallback={<LoadingPage />}> - <Router> + <BrowserRouter> <AppBar /> <div style={{ height: 56 }} /> - <Switch> - <Route exact path="/"> - {user == null ? <Home /> : <Center />} - </Route> - <Route exact path="/home"> - <Home /> - </Route> - {user != null ? ( - <Route exact path="/center"> - <Center /> - </Route> - ) : null} - <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> - <Route path="/search"> - <Search /> - </Route> - {user && user.hasAdministrationPermission && ( - <Route path="/admin"> - <LazyAdmin user={user} /> - </Route> - )} - <Route> - <NoMatch /> - </Route> - </Switch> + <Routes> + <Route index element={user == null ? <Home /> : <Center />} /> + <Route path="/home" element={<Home />} /> + <Route path="/center" element={<Center />} /> + <Route path="/login" element={<Login />} /> + <Route path="/settings" element={<Settings />} /> + <Route path="/about" element={<About />} /> + <Route path="/timelines/:name" element={<TimelinePage />} /> + <Route path="/users/:username" element={<User />} /> + <Route path="/search" element={<Search />} /> + <Route path="/admin" element={<Admin />} /> + <Route element={<NoMatch />} /> + </Routes> <AlertHost /> - </Router> + </BrowserRouter> </React.Suspense> ); } diff --git a/FrontEnd/src/views/admin/Admin.tsx b/FrontEnd/src/views/admin/Admin.tsx index e750621c..adb1e458 100644 --- a/FrontEnd/src/views/admin/Admin.tsx +++ b/FrontEnd/src/views/admin/Admin.tsx @@ -1,48 +1,27 @@ -import React, { Fragment } from "react"; -import { Redirect, Route, Switch, useRouteMatch, match } from "react-router"; +import React from "react"; +import { Route, Routes } from "react-router-dom"; import { useTranslation } from "react-i18next"; -import { AuthUser } from "@/services/user"; - import AdminNav from "./AdminNav"; import UserAdmin from "./UserAdmin"; import MoreAdmin from "./MoreAdmin"; import "./index.css"; -interface AdminProps { - user: AuthUser; -} - -const Admin: React.FC<AdminProps> = ({ user }) => { +const Admin: React.FC = () => { useTranslation("admin"); - const match = useRouteMatch(); - return ( - <Fragment> - <Switch> - <Redirect from={match.path} to={`${match.path}/users`} exact /> - <Route path={`${match.path}/:name`}> - {(p) => { - const match = p.match as match<{ name: string }>; - const name = match.params["name"]; - return ( - <div className="container"> - <AdminNav className="mt-2" /> - {(() => { - if (name === "users") { - return <UserAdmin user={user} />; - } else if (name === "more") { - return <MoreAdmin user={user} />; - } - })()} - </div> - ); - }} - </Route> - </Switch> - </Fragment> + <> + <div className="container"> + <AdminNav className="mt-2" /> + <Routes> + <Route index element={<UserAdmin />} /> + <Route path="/admin/user" element={<UserAdmin />} /> + <Route path="/admin/more" element={<MoreAdmin />} /> + </Routes> + </div> + </> ); }; diff --git a/FrontEnd/src/views/admin/AdminNav.tsx b/FrontEnd/src/views/admin/AdminNav.tsx index 821c9b0a..dc8b7dd0 100644 --- a/FrontEnd/src/views/admin/AdminNav.tsx +++ b/FrontEnd/src/views/admin/AdminNav.tsx @@ -1,12 +1,12 @@ import React from "react"; -import { useRouteMatch } from "react-router"; +import { useParams } from "react-router-dom"; import Tabs from "../common/tab/Tabs"; const AdminNav: React.FC<{ className?: string }> = ({ className }) => { - const match = useRouteMatch<{ name: string }>(); + const params = useParams(); - const name = match.params.name; + const name = params.name; return ( <Tabs diff --git a/FrontEnd/src/views/admin/MoreAdmin.tsx b/FrontEnd/src/views/admin/MoreAdmin.tsx index 042789a0..218ac5fb 100644 --- a/FrontEnd/src/views/admin/MoreAdmin.tsx +++ b/FrontEnd/src/views/admin/MoreAdmin.tsx @@ -1,12 +1,6 @@ import React from "react"; -import { AuthUser } from "@/services/user"; - -export interface MoreAdminProps { - user: AuthUser; -} - -const MoreAdmin: React.FC<MoreAdminProps> = () => { +const MoreAdmin: React.FC = () => { return <>More...</>; }; diff --git a/FrontEnd/src/views/admin/UserAdmin.tsx b/FrontEnd/src/views/admin/UserAdmin.tsx index 68d65409..6c411be8 100644 --- a/FrontEnd/src/views/admin/UserAdmin.tsx +++ b/FrontEnd/src/views/admin/UserAdmin.tsx @@ -1,13 +1,12 @@ import React, { useState, useEffect } from "react"; +import { Trans, useTranslation } from "react-i18next"; import classnames from "classnames"; +import { getHttpUserClient, HttpUser, kUserPermissionList } from "@/http/user"; + import OperationDialog, { OperationDialogBoolInput, } from "../common/dailog/OperationDialog"; - -import { AuthUser } from "@/services/user"; -import { getHttpUserClient, HttpUser, kUserPermissionList } from "@/http/user"; -import { Trans, useTranslation } from "react-i18next"; import Button from "../common/button/Button"; import Spinner from "../common/Spinner"; import FlatButton from "../common/button/FlatButton"; @@ -246,11 +245,7 @@ const UserItem: React.FC<UserItemProps> = ({ user, onChange }) => { ); }; -interface UserAdminProps { - user: AuthUser; -} - -const UserAdmin: React.FC<UserAdminProps> = () => { +const UserAdmin: React.FC = () => { const [users, setUsers] = useState<HttpUser[] | null>(null); const [dialog, setDialog] = useState<"create" | null>(null); const [usersVersion, setUsersVersion] = useState<number>(0); diff --git a/FrontEnd/src/views/admin/index.tsx b/FrontEnd/src/views/admin/index.tsx new file mode 100644 index 00000000..49da6586 --- /dev/null +++ b/FrontEnd/src/views/admin/index.tsx @@ -0,0 +1,7 @@ +import * as React from "react"; + +const Admin = React.lazy( + () => import(/* webpackChunkName: "admin" */ "./Admin") +); + +export default Admin; diff --git a/FrontEnd/src/views/center/TimelineCreateDialog.tsx b/FrontEnd/src/views/center/TimelineCreateDialog.tsx index 4871a5e0..d3b30575 100644 --- a/FrontEnd/src/views/center/TimelineCreateDialog.tsx +++ b/FrontEnd/src/views/center/TimelineCreateDialog.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { validateTimelineName } from "@/services/timeline"; import OperationDialog from "../common/dailog/OperationDialog"; @@ -11,7 +11,7 @@ interface TimelineCreateDialogProps { } const TimelineCreateDialog: React.FC<TimelineCreateDialogProps> = (props) => { - const history = useHistory(); + const navigate = useNavigate(); return ( <OperationDialog @@ -43,7 +43,7 @@ const TimelineCreateDialog: React.FC<TimelineCreateDialogProps> = (props) => { getHttpTimelineClient().postTimeline({ name }) } onSuccessAndClose={(timeline: HttpTimelineInfo) => { - history.push(`timelines/${timeline.name}`); + navigate(`timelines/${timeline.name}`); }} failurePrompt={(e) => `${e as string}`} /> diff --git a/FrontEnd/src/views/center/index.tsx b/FrontEnd/src/views/center/index.tsx index 430d9781..283925b9 100644 --- a/FrontEnd/src/views/center/index.tsx +++ b/FrontEnd/src/views/center/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { useUserLoggedIn } from "@/services/user"; @@ -11,7 +11,7 @@ import TimelineCreateDialog from "./TimelineCreateDialog"; import "./index.css"; const HomePage: React.FC = () => { - const history = useHistory(); + const navigate = useNavigate(); const user = useUserLoggedIn(); @@ -29,7 +29,7 @@ const HomePage: React.FC = () => { value={navText} onChange={setNavText} onButtonClick={() => { - history.push(`search?q=${navText}`); + navigate(`search?q=${navText}`); }} additionalButton={ user != null && ( diff --git a/FrontEnd/src/views/home/index.tsx b/FrontEnd/src/views/home/index.tsx index 2e23654e..9533ea5a 100644 --- a/FrontEnd/src/views/home/index.tsx +++ b/FrontEnd/src/views/home/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { HttpTimelineInfo } from "@/http/timeline"; import { getHttpHighlightClient } from "@/http/highlight"; @@ -17,7 +17,7 @@ const highlightTimelineMessageMap = { } as const; const HomeV2: React.FC = () => { - const history = useHistory(); + const navigate = useNavigate(); const [navText, setNavText] = React.useState<string>(""); @@ -60,7 +60,7 @@ const HomeV2: React.FC = () => { value={navText} onChange={setNavText} onButtonClick={() => { - history.push(`search?q=${navText}`); + navigate(`search?q=${navText}`); }} alwaysOneline /> diff --git a/FrontEnd/src/views/login/index.tsx b/FrontEnd/src/views/login/index.tsx index a3f0ccd7..3a1ccfc4 100644 --- a/FrontEnd/src/views/login/index.tsx +++ b/FrontEnd/src/views/login/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { useUser, userService } from "@/services/user"; @@ -11,7 +11,9 @@ import "./index.css"; const LoginPage: React.FC = (_) => { const { t } = useTranslation(); - const history = useHistory(); + + const navigate = useNavigate(); + const [username, setUsername] = React.useState<string>(""); const [usernameDirty, setUsernameDirty] = React.useState<boolean>(false); const [password, setPassword] = React.useState<string>(""); @@ -24,12 +26,12 @@ const LoginPage: React.FC = (_) => { React.useEffect(() => { if (user != null) { - const id = setTimeout(() => history.push("/"), 3000); + const id = setTimeout(() => navigate("/"), 3000); return () => { clearTimeout(id); }; } - }, [history, user]); + }, [navigate, user]); if (user != null) { return ( @@ -59,9 +61,9 @@ const LoginPage: React.FC = (_) => { .then( () => { if (history.length === 0) { - history.push("/"); + navigate("/"); } else { - history.goBack(); + navigate(-1); } }, (e: Error) => { diff --git a/FrontEnd/src/views/search/index.tsx b/FrontEnd/src/views/search/index.tsx index 509fd8c0..60eb6306 100644 --- a/FrontEnd/src/views/search/index.tsx +++ b/FrontEnd/src/views/search/index.tsx @@ -1,6 +1,6 @@ import React from "react"; import { useTranslation } from "react-i18next"; -import { useHistory, useLocation } from "react-router"; +import { useNavigate, useLocation } from "react-router-dom"; import { Link } from "react-router-dom"; import { HttpNetworkError } from "@/http/common"; @@ -44,7 +44,7 @@ const TimelineSearchResultItemView: React.FC<{ const SearchPage: React.FC = () => { const { t } = useTranslation(); - const history = useHistory(); + const navigate = useNavigate(); const location = useLocation(); const searchParams = new URLSearchParams(location.search); const queryParam = searchParams.get("q"); @@ -90,7 +90,7 @@ const SearchPage: React.FC = () => { if (queryParam === searchText) { setForceResearchKey((old) => old + 1); } else { - history.push(`/search?q=${searchText}`); + navigate(`/search?q=${searchText}`); } }} /> diff --git a/FrontEnd/src/views/settings/ChangePasswordDialog.tsx b/FrontEnd/src/views/settings/ChangePasswordDialog.tsx index 944fdaed..fe5868e2 100644 --- a/FrontEnd/src/views/settings/ChangePasswordDialog.tsx +++ b/FrontEnd/src/views/settings/ChangePasswordDialog.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { userService } from "@/services/user"; @@ -11,7 +11,7 @@ export interface ChangePasswordDialogProps { } const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props) => { - const history = useHistory(); + const navigate = useNavigate(); const [redirect, setRedirect] = useState<boolean>(false); @@ -58,7 +58,7 @@ const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props) => { onClose={() => { props.close(); if (redirect) { - history.push("/login"); + navigate("/login"); } }} /> diff --git a/FrontEnd/src/views/settings/index.tsx b/FrontEnd/src/views/settings/index.tsx index b9a8209b..86a8b263 100644 --- a/FrontEnd/src/views/settings/index.tsx +++ b/FrontEnd/src/views/settings/index.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { useUser, userService } from "@/services/user"; @@ -15,7 +15,7 @@ import "./index.css"; const SettingsPage: React.FC = (_) => { const { i18n, t } = useTranslation(); const user = useUser(); - const history = useHistory(); + const navigate = useNavigate(); const [dialog, setDialog] = useState< null | "changepassword" | "changeavatar" | "changenickname" | "logout" @@ -95,7 +95,7 @@ const SettingsPage: React.FC = (_) => { open={dialog === "logout"} onConfirm={() => { void userService.logout().then(() => { - history.push("/"); + navigate("/"); }); }} /> diff --git a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx b/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx index 42ba37de..b6893852 100644 --- a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx +++ b/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx @@ -2,7 +2,7 @@ import React from "react"; import classnames from "classnames"; import { useTranslation } from "react-i18next"; -import { Prompt } from "react-router"; +import { Prompt } from "react-router-dom"; import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline"; diff --git a/FrontEnd/src/views/timeline/TimelineDeleteDialog.tsx b/FrontEnd/src/views/timeline/TimelineDeleteDialog.tsx index 68dedf86..606584eb 100644 --- a/FrontEnd/src/views/timeline/TimelineDeleteDialog.tsx +++ b/FrontEnd/src/views/timeline/TimelineDeleteDialog.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; import { Trans } from "react-i18next"; import { getHttpTimelineClient, HttpTimelineInfo } from "@/http/timeline"; @@ -13,7 +13,7 @@ interface TimelineDeleteDialog { } const TimelineDeleteDialog: React.FC<TimelineDeleteDialog> = (props) => { - const history = useHistory(); + const navigate = useNavigate(); const { timeline } = props; @@ -46,7 +46,7 @@ const TimelineDeleteDialog: React.FC<TimelineDeleteDialog> = (props) => { return getHttpTimelineClient().deleteTimeline(timeline.name); }} onSuccessAndClose={() => { - history.replace("/"); + navigate("/", { replace: true }); }} /> ); diff --git a/FrontEnd/src/views/timeline/index.tsx b/FrontEnd/src/views/timeline/index.tsx index c5bfd7ab..02d773dc 100644 --- a/FrontEnd/src/views/timeline/index.tsx +++ b/FrontEnd/src/views/timeline/index.tsx @@ -1,11 +1,17 @@ import React from "react"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; + +import { UiLogicError } from "@/common"; import TimelinePageTemplate from "../timeline-common/TimelinePageTemplate"; import TimelineCard from "./TimelineCard"; const TimelinePage: React.FC = () => { - const { name } = useParams<{ name: string }>(); + const { name } = useParams(); + + if (name == null) { + throw new UiLogicError("No route param 'name'."); + } const [reloadKey, setReloadKey] = React.useState<number>(0); diff --git a/FrontEnd/src/views/user/index.tsx b/FrontEnd/src/views/user/index.tsx index 70b4f60f..7913b788 100644 --- a/FrontEnd/src/views/user/index.tsx +++ b/FrontEnd/src/views/user/index.tsx @@ -1,13 +1,19 @@ import React from "react"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import TimelinePageTemplate from "../timeline-common/TimelinePageTemplate"; import UserCard from "./UserCard"; +import { UiLogicError } from "@/common"; + import "./index.css"; const UserPage: React.FC = () => { - const { username } = useParams<{ username: string }>(); + const { username } = useParams(); + + if (username == null) { + throw new UiLogicError("No route param 'username'."); + } const [reloadKey, setReloadKey] = React.useState<number>(0); |