From e7854c1ed8facc2955ef9ad96f0bb2513041bba9 Mon Sep 17 00:00:00 2001 From: crupest Date: Mon, 16 Nov 2020 16:30:32 +0800 Subject: ... --- FrontEnd/src/app/views/admin/Admin.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'FrontEnd/src/app/views/admin/Admin.tsx') diff --git a/FrontEnd/src/app/views/admin/Admin.tsx b/FrontEnd/src/app/views/admin/Admin.tsx index 9c0250e7..a64a9bc0 100644 --- a/FrontEnd/src/app/views/admin/Admin.tsx +++ b/FrontEnd/src/app/views/admin/Admin.tsx @@ -8,12 +8,12 @@ import { } from "react-router"; import { Nav } from "react-bootstrap"; -import { UserWithToken } from "@/services/user"; +import { AuthUser } from "@/services/user"; import UserAdmin from "./UserAdmin"; interface AdminProps { - user: UserWithToken; + user: AuthUser; } const Admin: React.FC = (props) => { -- cgit v1.2.3 From 8f5ffab46b18eb30dfebeb8407435dd85dc35232 Mon Sep 17 00:00:00 2001 From: crupest Date: Mon, 16 Nov 2020 17:20:42 +0800 Subject: ... --- FrontEnd/src/app/http/user.ts | 8 +++ FrontEnd/src/app/views/admin/Admin.tsx | 64 ++++----------------- FrontEnd/src/app/views/admin/AdminSubPage.tsx | 44 +++++++++++++++ FrontEnd/src/app/views/admin/UserAdmin.tsx | 80 ++++++--------------------- 4 files changed, 80 insertions(+), 116 deletions(-) create mode 100644 FrontEnd/src/app/views/admin/AdminSubPage.tsx (limited to 'FrontEnd/src/app/views/admin/Admin.tsx') diff --git a/FrontEnd/src/app/http/user.ts b/FrontEnd/src/app/http/user.ts index 9ba6508f..92a6433e 100644 --- a/FrontEnd/src/app/http/user.ts +++ b/FrontEnd/src/app/http/user.ts @@ -49,6 +49,7 @@ export class HttpChangePasswordBadCredentialError extends Error { } export interface IHttpUserClient { + list(): Promise; get(username: string): Promise; patch( username: string, @@ -75,6 +76,13 @@ export interface IHttpUserClient { } export class HttpUserClient implements IHttpUserClient { + list(): Promise { + return axios + .get(`${apiBaseUrl}/users`) + .then(extractResponseData) + .catch(convertToNetworkError); + } + get(username: string): Promise { return axios .get(`${apiBaseUrl}/users/${username}`) diff --git a/FrontEnd/src/app/views/admin/Admin.tsx b/FrontEnd/src/app/views/admin/Admin.tsx index a64a9bc0..e17da5bc 100644 --- a/FrontEnd/src/app/views/admin/Admin.tsx +++ b/FrontEnd/src/app/views/admin/Admin.tsx @@ -1,12 +1,5 @@ import React, { Fragment } from "react"; -import { - Redirect, - Route, - Switch, - useRouteMatch, - useHistory, -} from "react-router"; -import { Nav } from "react-bootstrap"; +import { Redirect, Route, Switch, useRouteMatch, match } from "react-router"; import { AuthUser } from "@/services/user"; @@ -16,57 +9,22 @@ interface AdminProps { user: AuthUser; } -const Admin: React.FC = (props) => { +const Admin: React.FC = ({ user }) => { const match = useRouteMatch(); - const history = useHistory(); - type TabNames = "users" | "more"; - - const tabName = history.location.pathname.replace(match.path + "/", ""); - - function toggle(newTab: TabNames): void { - history.push(`${match.url}/${newTab}`); - } - - const createRoute = ( - name: string, - body: React.ReactNode - ): React.ReactNode => { - return ( - -
- - {body} - - ); - }; return ( - {createRoute("users", )} - {createRoute("more",
More Page Works
)} + + {(p) => { + const match = p.match as match<{ name: string }>; + const name = match.params["name"]; + if (name === "users") { + return ; + } + }} +
); diff --git a/FrontEnd/src/app/views/admin/AdminSubPage.tsx b/FrontEnd/src/app/views/admin/AdminSubPage.tsx new file mode 100644 index 00000000..5d2df13c --- /dev/null +++ b/FrontEnd/src/app/views/admin/AdminSubPage.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import { Nav } from "react-bootstrap"; +import { useHistory, useRouteMatch } from "react-router"; + +const AdminSubPage: React.FC = ({ children }) => { + const match = useRouteMatch<{ name: string }>(); + const history = useHistory(); + + const name = match.params.name; + + function toggle(newTab: string): void { + history.push(`/admin/${newTab}`); + } + + return ( + <> + + {children} + + ); +}; + +export default AdminSubPage; diff --git a/FrontEnd/src/app/views/admin/UserAdmin.tsx b/FrontEnd/src/app/views/admin/UserAdmin.tsx index 4ad9ed09..856e6136 100644 --- a/FrontEnd/src/app/views/admin/UserAdmin.tsx +++ b/FrontEnd/src/app/views/admin/UserAdmin.tsx @@ -10,19 +10,16 @@ import { } from "react-bootstrap"; import OperationDialog from "../common/OperationDialog"; +import AdminSubPage from "./AdminSubPage"; + import { User, AuthUser } from "@/services/user"; +import { getHttpUserClient } from "@/http/user"; const apiBaseUrl = "/api"; -async function fetchUserList(_token: string): Promise { - const res = await axios.get(`${apiBaseUrl}/users`); - return res.data; -} - interface CreateUserInfo { username: string; password: string; - administrator: boolean; } async function createUser(user: CreateUserInfo, token: string): Promise { @@ -57,16 +54,6 @@ function changePassword( }); } -function changePermission( - username: string, - newPermission: boolean, - token: string -): Promise { - return axios.patch(`${apiBaseUrl}/users/${username}?token=${token}`, { - administrator: newPermission, - }); -} - const kChangeUsername = "changeusername"; const kChangePassword = "changepassword"; const kChangePermission = "changepermission"; @@ -103,9 +90,9 @@ const UserItem: React.FC = (props) => {

{user.username}

- {user.administrator ? "administrator" : "user"} + {user.permissions ? "administrator" : "user"} @@ -156,14 +143,12 @@ const CreateUserDialog: React.FC = (props) => { [ { type: "text", label: "Username" }, { type: "text", label: "Password" }, - { type: "bool", label: "Administrator" }, ] as const } - onProcess={([username, password, administrator]) => + onProcess={([username, password]) => props.process({ username: username, password: password, - administrator: administrator, }) } close={props.close} @@ -316,15 +301,17 @@ const UserAdmin: React.FC = (props) => { useEffect(() => { let subscribe = true; - void fetchUserList(props.user.token).then((us) => { - if (subscribe) { - setUsers(us); - } - }); + void getHttpUserClient() + .list() + .then((us) => { + if (subscribe) { + setUsers(us); + } + }); return () => { subscribe = false; }; - }, [props.user]); + }, []); let dialogNode: React.ReactNode; if (dialog) @@ -389,26 +376,6 @@ const UserAdmin: React.FC = (props) => { ); break; case kChangePermission: { - const newPermission = dialog.newPermission; - dialogNode = ( - setDialog(null)} - username={dialog.username} - newPermission={newPermission} - process={async () => { - await changePermission(dialog.username, newPermission, token); - setUsers((oldUsers) => { - const users = (oldUsers ?? []).slice(); - const findedUser = users.find( - (u) => u.username === dialog.username - ); - if (findedUser) findedUser.administrator = newPermission; - return users; - }); - }} - /> - ); break; } } @@ -419,26 +386,13 @@ const UserAdmin: React.FC = (props) => { { - setDialog( - item === kChangePermission - ? { - type: kChangePermission, - username: user.username, - newPermission: !user.administrator, - } - : { - type: item, - username: user.username, - } - ); - }} + onContextMenu={(item) => {}} /> ); }); return ( - <> + {userComponents} {dialogNode} - + ); } else { return ; -- cgit v1.2.3 From 1e6e30ec4bdf58b5b6bc19edf8c34f15656e9eb2 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 20 Nov 2020 18:31:15 +0800 Subject: ... --- FrontEnd/src/app/index.sass | 2 ++ FrontEnd/src/app/views/admin/Admin.tsx | 18 ++++++++-- FrontEnd/src/app/views/admin/AdminNav.tsx | 41 ++++++++++++++++++++++ FrontEnd/src/app/views/admin/AdminSubPage.tsx | 34 ------------------ .../src/app/views/admin/HighlightTimelineAdmin.tsx | 13 +++++++ FrontEnd/src/app/views/admin/UserAdmin.tsx | 5 ++- FrontEnd/src/app/views/admin/admin.sass | 0 7 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 FrontEnd/src/app/views/admin/AdminNav.tsx delete mode 100644 FrontEnd/src/app/views/admin/AdminSubPage.tsx create mode 100644 FrontEnd/src/app/views/admin/HighlightTimelineAdmin.tsx create mode 100644 FrontEnd/src/app/views/admin/admin.sass (limited to 'FrontEnd/src/app/views/admin/Admin.tsx') diff --git a/FrontEnd/src/app/index.sass b/FrontEnd/src/app/index.sass index b8cc464e..e3c1c5b9 100644 --- a/FrontEnd/src/app/index.sass +++ b/FrontEnd/src/app/index.sass @@ -10,6 +10,8 @@ @import './views/timeline/timeline' @import './views/user/user' +@import './views/admin/admin' + body margin: 0 diff --git a/FrontEnd/src/app/views/admin/Admin.tsx b/FrontEnd/src/app/views/admin/Admin.tsx index e17da5bc..ac640700 100644 --- a/FrontEnd/src/app/views/admin/Admin.tsx +++ b/FrontEnd/src/app/views/admin/Admin.tsx @@ -1,9 +1,12 @@ import React, { Fragment } from "react"; import { Redirect, Route, Switch, useRouteMatch, match } from "react-router"; +import { Container } from "react-bootstrap"; import { AuthUser } from "@/services/user"; +import AdminNav from "./AdminNav"; import UserAdmin from "./UserAdmin"; +import HighlightTimelineAdmin from "./HighlightTimelineAdmin"; interface AdminProps { user: AuthUser; @@ -20,9 +23,18 @@ const Admin: React.FC = ({ user }) => { {(p) => { const match = p.match as match<{ name: string }>; const name = match.params["name"]; - if (name === "users") { - return ; - } + return ( + + + {(() => { + if (name === "users") { + return ; + } else if (name === "highlighttimelines") { + return ; + } + })()} + + ); }} diff --git a/FrontEnd/src/app/views/admin/AdminNav.tsx b/FrontEnd/src/app/views/admin/AdminNav.tsx new file mode 100644 index 00000000..040b479f --- /dev/null +++ b/FrontEnd/src/app/views/admin/AdminNav.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { Nav } from "react-bootstrap"; +import { useHistory, useRouteMatch } from "react-router"; + +const AdminNav: React.FC = () => { + const match = useRouteMatch<{ name: string }>(); + const history = useHistory(); + + const name = match.params.name; + + function toggle(newTab: string): void { + history.push(`/admin/${newTab}`); + } + + return ( + + ); +}; + +export default AdminNav; diff --git a/FrontEnd/src/app/views/admin/AdminSubPage.tsx b/FrontEnd/src/app/views/admin/AdminSubPage.tsx deleted file mode 100644 index 5efe1ee3..00000000 --- a/FrontEnd/src/app/views/admin/AdminSubPage.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from "react"; -import { Container, Nav } from "react-bootstrap"; -import { useHistory, useRouteMatch } from "react-router"; - -const AdminSubPage: React.FC = ({ children }) => { - const match = useRouteMatch<{ name: string }>(); - const history = useHistory(); - - const name = match.params.name; - - function toggle(newTab: string): void { - history.push(`/admin/${newTab}`); - } - - return ( - - - {children} - - ); -}; - -export default AdminSubPage; diff --git a/FrontEnd/src/app/views/admin/HighlightTimelineAdmin.tsx b/FrontEnd/src/app/views/admin/HighlightTimelineAdmin.tsx new file mode 100644 index 00000000..3de7d5a6 --- /dev/null +++ b/FrontEnd/src/app/views/admin/HighlightTimelineAdmin.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +import { AuthUser } from "@/services/user"; + +export interface HighlightTimelineAdminProps { + user: AuthUser; +} + +const HighlightTimelineAdmin: React.FC = () => { + return <>This is highlight timeline administration page.; +}; + +export default HighlightTimelineAdmin; diff --git a/FrontEnd/src/app/views/admin/UserAdmin.tsx b/FrontEnd/src/app/views/admin/UserAdmin.tsx index c78490d8..37ad2ef7 100644 --- a/FrontEnd/src/app/views/admin/UserAdmin.tsx +++ b/FrontEnd/src/app/views/admin/UserAdmin.tsx @@ -9,7 +9,6 @@ import { } from "react-bootstrap"; import OperationDialog from "../common/OperationDialog"; -import AdminSubPage from "./AdminSubPage"; import { User, AuthUser } from "@/services/user"; import { getHttpUserClient, HttpUser } from "@/http/user"; @@ -266,7 +265,7 @@ const UserAdmin: React.FC = (props) => { }); return ( - + <>
@@ -249,6 +258,8 @@ interface UserAdminProps { } const UserAdmin: React.FC = (props) => { + const { t } = useTranslation(); + type DialogInfo = | null | { @@ -384,7 +395,7 @@ const UserAdmin: React.FC = (props) => { }) } > - Create + {t("admin:create")} diff --git a/FrontEnd/src/app/views/common/AppBar.tsx b/FrontEnd/src/app/views/common/AppBar.tsx index 11d3de04..c862a6d3 100644 --- a/FrontEnd/src/app/views/common/AppBar.tsx +++ b/FrontEnd/src/app/views/common/AppBar.tsx @@ -63,7 +63,7 @@ const AppBar: React.FC = (_) => { activeClassName="active" onClick={collapse} > - Administration + {t("nav.administration")} )} -- cgit v1.2.3 From f1aabc06f1005b26bd1c0c5f36c98c28a62fc31e Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 22 Nov 2020 09:49:58 +0800 Subject: fix: Fix i18n. --- FrontEnd/src/app/views/admin/Admin.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'FrontEnd/src/app/views/admin/Admin.tsx') diff --git a/FrontEnd/src/app/views/admin/Admin.tsx b/FrontEnd/src/app/views/admin/Admin.tsx index 94e97713..446cd36d 100644 --- a/FrontEnd/src/app/views/admin/Admin.tsx +++ b/FrontEnd/src/app/views/admin/Admin.tsx @@ -1,22 +1,21 @@ import React, { Fragment } from "react"; import { Redirect, Route, Switch, useRouteMatch, match } from "react-router"; import { Container } from "react-bootstrap"; +import { useTranslation } from "react-i18next"; import { AuthUser } from "@/services/user"; -import i18n from "@/i18n"; - import AdminNav from "./AdminNav"; import UserAdmin from "./UserAdmin"; import HighlightTimelineAdmin from "./HighlightTimelineAdmin"; -void i18n.loadNamespaces("admin"); - interface AdminProps { user: AuthUser; } const Admin: React.FC = ({ user }) => { + useTranslation("admin"); + const match = useRouteMatch(); return ( -- cgit v1.2.3