import React, { useState, useEffect } from "react"; import clsx from "clsx"; import { ListGroup, Row, Col, Spinner, Button } from "react-bootstrap"; import InlineSVG from "react-inlinesvg"; import PencilSquareIcon from "bootstrap-icons/icons/pencil-square.svg"; import OperationDialog, { OperationBoolInputInfo, } from "../common/OperationDialog"; import { User, AuthUser } from "@/services/user"; import { getHttpUserClient, HttpUser, kUserPermissionList, UserPermission, } from "@/http/user"; interface DialogProps { open: boolean; close: () => void; token: string; data: TData; onSuccess: (data: TReturn) => void; } const CreateUserDialog: React.FC> = ({ open, close, token, onSuccess, }) => { return ( getHttpUserClient().createUser( { username, password, }, token ) } close={close} open={open} onSuccessAndClose={onSuccess} /> ); }; const UsernameLabel: React.FC = (props) => { return {props.children}; }; const UserDeleteDialog: React.FC> = ({ open, close, token, data: { username }, onSuccess }) => { return ( ( <> You are deleting user {username} ! )} onProcess={() => getHttpUserClient().delete(username, token)} onSuccessAndClose={onSuccess} /> ); }; const UserModifyDialog: React.FC> = ({ open, close, token, data: { oldUser }, onSuccess }) => { return ( ( <> You are change the password of user {oldUser.username} ! )} inputScheme={ [ { type: "text", label: "New Username", initValue: oldUser.username }, { type: "text", label: "New Password" }, { type: "text", label: "New Nickname", initValue: oldUser.nickname }, ] as const } onProcess={([username, password, nickname]) => getHttpUserClient().patch( oldUser.username, { username: username !== oldUser.username ? username : undefined, password: password !== "" ? password : undefined, nickname: nickname !== oldUser.nickname ? nickname : undefined, }, token ) } onSuccessAndClose={onSuccess} /> ); }; const UserPermissionModifyDialog: React.FC> = ({ open, close, token, data: { username, permissions }, onSuccess }) => { const oldPermissionBoolList: boolean[] = kUserPermissionList.map( (permission) => permissions.includes(permission) ); return ( ( <> You are modify permission of user {username} ! )} inputScheme={kUserPermissionList.map( (permission, index) => ({ type: "bool", label: permission, initValue: oldPermissionBoolList[index], }) )} onProcess={async (newPermissionBoolList): Promise => { 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( username, permission, token ); } else { await getHttpUserClient().deleteUserPermission( username, permission, token ); } } return newPermissionBoolList; }} onSuccessAndClose={(newPermissionBoolList: boolean[]) => { const permissions: UserPermission[] = []; for (let index = 0; index < kUserPermissionList.length; index++) { if (newPermissionBoolList[index]) { permissions.push(kUserPermissionList[index]); } } onSuccess(permissions); }} /> ); }; const kModify = "modify"; const kModifyPermission = "permission"; const kDelete = "delete"; type TModify = typeof kModify; type TModifyPermission = typeof kModifyPermission; type TDelete = typeof kDelete; type ContextMenuItem = TModify | TModifyPermission | TDelete; interface UserItemProps { on: { [key in ContextMenuItem]: () => void }; user: User; } const UserItem: React.FC = ({ user, on }) => { const [editMaskVisible, setEditMaskVisible] = React.useState(false); return ( setEditMaskVisible(true)} />

{user.username}

nickname: {user.nickname}
unique id: {user.uniqueId}
permissions:{" "} {user.permissions.map((permission) => { return ( {permission}{" "} ); })}
setEditMaskVisible(false)} >
); }; interface UserAdminProps { user: AuthUser; } const UserAdmin: React.FC = (props) => { type DialogInfo = | null | { type: "create"; } | { type: TModify; user: HttpUser; } | { type: TModifyPermission; username: string; permissions: UserPermission[]; } | { type: TDelete; username: string }; const [users, setUsers] = useState(null); const [dialog, setDialog] = useState(null); const [usersVersion, setUsersVersion] = useState(0); const updateUsers = (): void => { setUsersVersion(usersVersion + 1); }; const token = props.user.token; useEffect(() => { let subscribe = true; void getHttpUserClient() .list() .then((us) => { if (subscribe) { setUsers(us); } }); return () => { subscribe = false; }; }, [usersVersion]); let dialogNode: React.ReactNode; if (dialog) { switch (dialog.type) { case "create": dialogNode = ( setDialog(null)} token={token} data={undefined} onSuccess={updateUsers} /> ); break; case kDelete: dialogNode = ( setDialog(null)} token={token} data={{ username: dialog.username }} onSuccess={updateUsers} /> ); break; case kModify: dialogNode = ( setDialog(null)} token={token} data={{ oldUser: dialog.user }} onSuccess={updateUsers} /> ); break; case kModifyPermission: dialogNode = ( setDialog(null)} token={token} data={{ username: dialog.username, permissions: dialog.permissions, }} onSuccess={updateUsers} /> ); break; } } if (users) { const userComponents = users.map((user) => { return ( { setDialog({ type: "modify", user, }); }, permission: () => { setDialog({ type: kModifyPermission, username: user.username, permissions: user.permissions, }); }, delete: () => { setDialog({ type: "delete", username: user.username, }); }, }} /> ); }); return ( <> {userComponents} {dialogNode} ); } else { return ; } }; export default UserAdmin;