diff options
Diffstat (limited to 'FrontEnd/src/views/admin')
-rw-r--r-- | FrontEnd/src/views/admin/Admin.tsx | 27 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/AdminNav.tsx | 29 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/MoreAdmin.tsx | 7 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/UserAdmin.tsx | 304 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/index.css | 33 | ||||
-rw-r--r-- | FrontEnd/src/views/admin/index.tsx | 7 |
6 files changed, 0 insertions, 407 deletions
diff --git a/FrontEnd/src/views/admin/Admin.tsx b/FrontEnd/src/views/admin/Admin.tsx deleted file mode 100644 index 986c36b4..00000000 --- a/FrontEnd/src/views/admin/Admin.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Route, Routes } from "react-router-dom"; -import { useTranslation } from "react-i18next"; - -import AdminNav from "./AdminNav"; -import UserAdmin from "./UserAdmin"; -import MoreAdmin from "./MoreAdmin"; - -import "./index.css"; - -const Admin: React.FC = () => { - useTranslation("admin"); - - return ( - <> - <div className="container"> - <AdminNav className="mt-2" /> - <Routes> - <Route index element={<UserAdmin />} /> - <Route path="user" element={<UserAdmin />} /> - <Route path="more" element={<MoreAdmin />} /> - </Routes> - </div> - </> - ); -}; - -export default Admin; diff --git a/FrontEnd/src/views/admin/AdminNav.tsx b/FrontEnd/src/views/admin/AdminNav.tsx deleted file mode 100644 index b7385e5c..00000000 --- a/FrontEnd/src/views/admin/AdminNav.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useLocation } from "react-router-dom"; - -import Tabs from "../common/tab/Tabs"; - -export function AdminNav({ className }: { className?: string }) { - const location = useLocation(); - const name = location.pathname.split("/")[2] ?? "user"; - - return ( - <Tabs - className={className} - activeTabName={name} - tabs={[ - { - name: "user", - text: "admin:nav.users", - link: "/admin/user", - }, - { - name: "more", - text: "admin:nav.more", - link: "/admin/more", - }, - ]} - /> - ); -} - -export default AdminNav; diff --git a/FrontEnd/src/views/admin/MoreAdmin.tsx b/FrontEnd/src/views/admin/MoreAdmin.tsx deleted file mode 100644 index d49d211f..00000000 --- a/FrontEnd/src/views/admin/MoreAdmin.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from "react"; - -const MoreAdmin: React.FC = () => { - return <>More...</>; -}; - -export default MoreAdmin; diff --git a/FrontEnd/src/views/admin/UserAdmin.tsx b/FrontEnd/src/views/admin/UserAdmin.tsx deleted file mode 100644 index d5179bf5..00000000 --- a/FrontEnd/src/views/admin/UserAdmin.tsx +++ /dev/null @@ -1,304 +0,0 @@ -import { useState, useEffect } from "react"; -import * as React from "react"; -import { Trans, useTranslation } from "react-i18next"; -import classnames from "classnames"; - -import { getHttpUserClient, HttpUser, kUserPermissionList } from "@/http/user"; - -import OperationDialog, { - OperationDialogBoolInput, -} from "../common/dialog/OperationDialog"; -import Button from "../common/button/Button"; -import Spinner from "../common/Spinner"; -import FlatButton from "../common/button/FlatButton"; -import IconButton from "../common/button/IconButton"; - -const CreateUserDialog: React.FC<{ - open: boolean; - close: () => void; - onSuccess: (user: HttpUser) => void; -}> = ({ open, close, onSuccess }) => { - return ( - <OperationDialog - title="admin:user.dialog.create.title" - themeColor="success" - inputPrompt="admin:user.dialog.create.prompt" - inputScheme={ - [ - { type: "text", label: "admin:user.username" }, - { type: "text", label: "admin:user.password" }, - ] as const - } - onProcess={([username, password]) => - getHttpUserClient().post({ - username, - password, - }) - } - onClose={close} - open={open} - onSuccessAndClose={onSuccess} - /> - ); -}; - -const UsernameLabel: React.FC<{ children: React.ReactNode }> = (props) => { - return <span style={{ color: "blue" }}>{props.children}</span>; -}; - -const UserDeleteDialog: React.FC<{ - open: boolean; - close: () => void; - user: HttpUser; - onSuccess: () => void; -}> = ({ open, close, user, onSuccess }) => { - return ( - <OperationDialog - open={open} - onClose={close} - title="admin:user.dialog.delete.title" - themeColor="danger" - inputPrompt={() => ( - <Trans i18nKey="user.dialog.delete.prompt" ns="admin"> - 0<UsernameLabel>{user.username}</UsernameLabel>2 - </Trans> - )} - onProcess={() => getHttpUserClient().delete(user.username)} - onSuccessAndClose={onSuccess} - /> - ); -}; - -const UserModifyDialog: React.FC<{ - open: boolean; - close: () => void; - user: HttpUser; - onSuccess: () => void; -}> = ({ open, close, user, onSuccess }) => { - return ( - <OperationDialog - open={open} - onClose={close} - title="admin:user.dialog.modify.title" - themeColor="danger" - inputPrompt={() => ( - <Trans i18nKey="admin:user.dialog.modify.prompt"> - 0<UsernameLabel>{user.username}</UsernameLabel>2 - </Trans> - )} - inputScheme={ - [ - { - type: "text", - label: "admin:user.username", - initValue: user.username, - }, - { type: "text", label: "admin:user.password" }, - { - type: "text", - label: "admin:user.nickname", - initValue: user.nickname, - }, - ] as const - } - onProcess={([username, password, nickname]) => - getHttpUserClient().patch(user.username, { - username: username !== user.username ? username : undefined, - password: password !== "" ? password : undefined, - nickname: nickname !== user.nickname ? nickname : undefined, - }) - } - onSuccessAndClose={onSuccess} - /> - ); -}; - -const UserPermissionModifyDialog: React.FC<{ - open: boolean; - close: () => void; - user: HttpUser; - onSuccess: () => void; -}> = ({ open, close, user, onSuccess }) => { - const oldPermissionBoolList: boolean[] = kUserPermissionList.map( - (permission) => user.permissions.includes(permission) - ); - - return ( - <OperationDialog - open={open} - onClose={close} - title="admin:user.dialog.modifyPermissions.title" - themeColor="danger" - inputPrompt={() => ( - <Trans i18nKey="admin:user.dialog.modifyPermissions.prompt"> - 0<UsernameLabel>{user.username}</UsernameLabel>2 - </Trans> - )} - inputScheme={kUserPermissionList.map<OperationDialogBoolInput>( - (permission, index) => ({ - type: "bool", - label: { type: "custom", value: permission }, - initValue: oldPermissionBoolList[index], - }) - )} - onProcess={async (newPermissionBoolList): Promise<boolean[]> => { - for (let index = 0; index < kUserPermissionList.length; index++) { - const oldValue = oldPermissionBoolList[index]; - const newValue = newPermissionBoolList[index]; - const permission = kUserPermissionList[index]; - if (oldValue === newValue) continue; - if (newValue) { - await getHttpUserClient().putUserPermission( - user.username, - permission - ); - } else { - await getHttpUserClient().deleteUserPermission( - user.username, - permission - ); - } - } - return newPermissionBoolList; - }} - onSuccessAndClose={onSuccess} - /> - ); -}; - -interface UserItemProps { - user: HttpUser; - onChange: () => void; -} - -const UserItem: React.FC<UserItemProps> = ({ user, onChange }) => { - const { t } = useTranslation(); - - const [dialog, setDialog] = useState< - "delete" | "modify" | "permission" | null - >(null); - - const [editMaskVisible, setEditMaskVisible] = React.useState<boolean>(false); - - return ( - <> - <div className="admin-user-item"> - <IconButton - icon="pencil-square" - className="cru-float-right" - onClick={() => setEditMaskVisible(true)} - /> - <h5 className="cru-color-primary">{user.username}</h5> - <small className="d-block cru-color-secondary"> - {t("admin:user.nickname")} - {user.nickname} - </small> - <small className="d-block cru-color-secondary"> - {t("admin:user.uniqueId")} - {user.uniqueId} - </small> - <small className="d-block cru-color-secondary"> - {t("admin:user.permissions")} - {user.permissions.map((permission) => { - return ( - <span key={permission} className="cru-color-danger"> - {permission} - </span> - ); - })} - </small> - <div - className={classnames("edit-mask", !editMaskVisible && "d-none")} - onClick={() => setEditMaskVisible(false)} - > - <FlatButton - text="admin:user.modify" - onClick={() => setDialog("modify")} - /> - <FlatButton - text="admin:user.modifyPermissions" - onClick={() => setDialog("permission")} - /> - <FlatButton - text="admin:user.delete" - color="danger" - onClick={() => setDialog("delete")} - /> - </div> - </div> - <UserDeleteDialog - open={dialog === "delete"} - close={() => setDialog(null)} - user={user} - onSuccess={onChange} - /> - <UserModifyDialog - open={dialog === "modify"} - close={() => setDialog(null)} - user={user} - onSuccess={onChange} - /> - <UserPermissionModifyDialog - open={dialog === "permission"} - close={() => setDialog(null)} - user={user} - onSuccess={onChange} - /> - </> - ); -}; - -const UserAdmin: React.FC = () => { - const [users, setUsers] = useState<HttpUser[] | null>(null); - const [dialog, setDialog] = useState<"create" | null>(null); - const [usersVersion, setUsersVersion] = useState<number>(0); - const updateUsers = (): void => { - setUsersVersion(usersVersion + 1); - }; - - useEffect(() => { - let subscribe = true; - void getHttpUserClient() - .list() - .then((us) => { - if (subscribe) { - setUsers(us.items); - } - }); - return () => { - subscribe = false; - }; - }, [usersVersion]); - - if (users) { - const userComponents = users.map((user) => { - return ( - <UserItem key={user.username} user={user} onChange={updateUsers} /> - ); - }); - - return ( - <> - <div className="row justify-content-end my-2"> - <div className="col col-auto"> - <Button - text="admin:create" - color="success" - onClick={() => setDialog("create")} - /> - </div> - </div> - {userComponents} - <CreateUserDialog - open={dialog === "create"} - close={() => setDialog(null)} - onSuccess={updateUsers} - /> - </> - ); - } else { - return <Spinner />; - } -}; - -export default UserAdmin; diff --git a/FrontEnd/src/views/admin/index.css b/FrontEnd/src/views/admin/index.css deleted file mode 100644 index 17e24586..00000000 --- a/FrontEnd/src/views/admin/index.css +++ /dev/null @@ -1,33 +0,0 @@ -.admin-user-item {
- position: relative;
- border: var(--cru-primary-color) solid;
- border-width: 1px 1px 0;
- padding: 1em;
-}
-
-.admin-user-item:last-of-type {
- border-bottom-width: 1px;
-}
-
-.admin-user-item .edit-mask {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- background: rgba(255, 255, 255, 0.9);
- position: absolute;
- display: flex;
- justify-content: space-around;
- align-items: center;
-}
-
-@media (max-width: 576px) {
- .admin-user-item .edit-mask {
- flex-direction: column;
- }
-}
-
-.admin-user-item .edit-mask button {
- margin: 0.5em 2em;
-}
diff --git a/FrontEnd/src/views/admin/index.tsx b/FrontEnd/src/views/admin/index.tsx deleted file mode 100644 index 0467711d..00000000 --- a/FrontEnd/src/views/admin/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { lazy } from "react"; - -const Admin = lazy( - () => import(/* webpackChunkName: "admin" */ "./Admin") -); - -export default Admin; |