admin panel continuation
This commit is contained in:
parent
c8965e209b
commit
aece0cb92a
@ -13,7 +13,8 @@ import './res/adminlte.min.css';
|
||||
// views
|
||||
import View404 from "./views/404";
|
||||
const Overview = lazy(() => import('./views/overview'));
|
||||
const UserListView = lazy(() => import('./views/user-list'));
|
||||
const UserListView = lazy(() => import('./views/user/user-list'));
|
||||
const UserEditView = lazy(() => import('./views/user/user-edit'));
|
||||
const GroupListView = lazy(() => import('./views/group-list'));
|
||||
const EditGroupView = lazy(() => import('./views/group-edit'));
|
||||
|
||||
@ -66,6 +67,7 @@ export default function AdminDashboard(props) {
|
||||
<Route path={"/admin"} element={<Overview {...controlObj} />}/>
|
||||
<Route path={"/admin/dashboard"} element={<Overview {...controlObj} />}/>
|
||||
<Route path={"/admin/users"} element={<UserListView {...controlObj} />}/>
|
||||
<Route path={"/admin/user/:userId"} element={<UserEditView {...controlObj} />}/>
|
||||
<Route path={"/admin/groups"} element={<GroupListView {...controlObj} />}/>
|
||||
<Route path={"/admin/group/:groupId"} element={<EditGroupView {...controlObj} />}/>
|
||||
<Route path={"*"} element={<View404 />} />
|
||||
|
@ -250,7 +250,7 @@ export default function LoginForm(props) {
|
||||
? <Alert severity="error">
|
||||
{error}
|
||||
{emailConfirmed === false
|
||||
? <> <Link href={"/resendConfirmation"}>Click here</Link> to resend the confirmation email.</>
|
||||
? <> <Link href={"/resendConfirmEmail"}>Click here</Link> to resend the confirmation email.</>
|
||||
: <></>
|
||||
}
|
||||
</Alert>
|
||||
|
89
react/admin-panel/src/views/user/user-edit.js
Normal file
89
react/admin-panel/src/views/user/user-edit.js
Normal file
@ -0,0 +1,89 @@
|
||||
import {Link, useNavigate, useParams} from "react-router-dom";
|
||||
import {useCallback, useContext, useEffect, useState} from "react";
|
||||
import {CircularProgress} from "@material-ui/core";
|
||||
import {LocaleContext} from "shared/locale";
|
||||
import * as React from "react";
|
||||
|
||||
|
||||
export default function UserEditView(props) {
|
||||
|
||||
const { api, showDialog } = props;
|
||||
const { userId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const isNewUser = userId === "new";
|
||||
const {translate: L, requestModules, currentLocale} = useContext(LocaleContext);
|
||||
const [fetchUser, setFetchUser] = useState(!isNewUser);
|
||||
const [user, setUser] = useState(isNewUser ? {
|
||||
name: "",
|
||||
fullName: "",
|
||||
email: "",
|
||||
password: "",
|
||||
groups: [],
|
||||
confirmed: false,
|
||||
} : null);
|
||||
|
||||
useEffect(() => {
|
||||
requestModules(props.api, ["general", "account"], currentLocale).then(data => {
|
||||
if (!data.success) {
|
||||
props.showDialog("Error fetching translations: " + data.msg);
|
||||
}
|
||||
});
|
||||
}, [currentLocale]);
|
||||
|
||||
const onFetchUser = useCallback((force = false) => {
|
||||
if (!isNewUser && (force || fetchUser)) {
|
||||
setFetchUser(false);
|
||||
api.getUser(userId).then((res) => {
|
||||
if (!res.success) {
|
||||
showDialog(res.msg, L("account.error_user_get"));
|
||||
if (user === null) {
|
||||
navigate("/admin/users");
|
||||
}
|
||||
} else {
|
||||
setUser(res.user);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [api, showDialog, fetchUser, isNewUser, userId, user]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isNewUser) {
|
||||
onFetchUser(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (user === null) {
|
||||
return <CircularProgress />
|
||||
}
|
||||
|
||||
return <div className={"content-header"}>
|
||||
<div className={"container-fluid"}>
|
||||
<ol className={"breadcrumb"}>
|
||||
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
||||
<li className="breadcrumb-item active"><Link to={"/admin/users"}>User</Link></li>
|
||||
<li className="breadcrumb-item active">{ isNewUser ? "New" : "Edit" }</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div className={"content"}>
|
||||
<div className={"container-fluid"}>
|
||||
<h3>{L(isNewUser ? "Create new User" : "Edit User")}</h3>
|
||||
<div className={"col-sm-12 col-lg-6"}>
|
||||
<div className={"row"}>
|
||||
<div className={"col-sm-6 form-group"}>
|
||||
<label htmlFor={"username"}>{L("account.username")}</label>
|
||||
<input type={"text"} className={"form-control"} placeholder={L("account.username")}
|
||||
name={"username"} id={"username"} maxLength={32} value={user.name}
|
||||
onChange={(e) => setUser({...user, name: e.target.value})}/>
|
||||
</div>
|
||||
<div className={"col-sm-6 form-group"}>
|
||||
<label htmlFor={"fullName"}>{L("account.full_name")}</label>
|
||||
<input type={"text"} className={"form-control"} placeholder={L("account.full_name")}
|
||||
name={"fullName"} id={"fullName"} maxLength={32} value={user.fullName}
|
||||
onChange={(e) => setUser({...user, fullName: e.target.value})}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
93
react/admin-panel/src/views/user/user-list.js
Normal file
93
react/admin-panel/src/views/user/user-list.js
Normal file
@ -0,0 +1,93 @@
|
||||
import {Link, useNavigate} from "react-router-dom";
|
||||
import {useCallback, useContext, useEffect, useState} from "react";
|
||||
import {LocaleContext} from "shared/locale";
|
||||
import {
|
||||
BoolColumn,
|
||||
ControlsColumn,
|
||||
DataColumn,
|
||||
DataTable,
|
||||
NumericColumn,
|
||||
StringColumn
|
||||
} from "shared/elements/data-table";
|
||||
import {Button} from "@material-ui/core";
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import {Chip} from "@mui/material";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import usePagination from "shared/hooks/pagination";
|
||||
|
||||
|
||||
export default function UserListView(props) {
|
||||
|
||||
const api = props.api;
|
||||
const showDialog = props.showDialog;
|
||||
const {translate: L, requestModules, currentLocale} = useContext(LocaleContext);
|
||||
const navigate = useNavigate();
|
||||
const pagination = usePagination();
|
||||
const [users, setUsers] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
requestModules(props.api, ["general", "account"], currentLocale).then(data => {
|
||||
if (!data.success) {
|
||||
props.showDialog("Error fetching translations: " + data.msg);
|
||||
}
|
||||
});
|
||||
}, [currentLocale]);
|
||||
|
||||
const onFetchUsers = useCallback((page, count, orderBy, sortOrder) => {
|
||||
api.fetchUsers(page, count, orderBy, sortOrder).then((res) => {
|
||||
if (res.success) {
|
||||
setUsers(res.users);
|
||||
pagination.update(res.pagination);
|
||||
} else {
|
||||
showDialog(res.msg, "Error fetching users");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}, [api, showDialog]);
|
||||
|
||||
const groupColumn = (() => {
|
||||
let column = new DataColumn(L("account.groups"), "groups");
|
||||
column.renderData = (L, entry) => {
|
||||
return Object.values(entry.groups).map(group => <Chip key={"group-" + group.id} label={group.name}/>)
|
||||
}
|
||||
return column;
|
||||
})();
|
||||
|
||||
const columnDefinitions = [
|
||||
new NumericColumn(L("general.id"), "id"),
|
||||
new StringColumn(L("account.username"), "name"),
|
||||
new StringColumn(L("account.full_name"), "fullName"),
|
||||
new StringColumn(L("account.email"), "email"),
|
||||
groupColumn,
|
||||
new BoolColumn(L("account.confirmed"), "confirmed", { align: "center" }),
|
||||
new ControlsColumn(L("general.controls"), [
|
||||
{ label: L("general.edit"), element: EditIcon, onClick: (entry) => navigate(`/admin/user/${entry.id}`) }
|
||||
]),
|
||||
];
|
||||
|
||||
return <div className={"content-header"}>
|
||||
<div className={"container-fluid"}>
|
||||
<ol className={"breadcrumb"}>
|
||||
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
||||
<li className="breadcrumb-item active">Users</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div className={"content"}>
|
||||
<div className={"container-fluid"}>
|
||||
<DataTable
|
||||
data={users}
|
||||
pagination={pagination}
|
||||
className={"table table-striped"}
|
||||
fetchData={onFetchUsers}
|
||||
placeholder={"No users to display"}
|
||||
title={L("account.users")}
|
||||
columns={columnDefinitions} />
|
||||
<Link to="/admin/user/new">
|
||||
<Button variant={"outlined"} startIcon={<AddIcon />} size={"small"}>
|
||||
{L("general.create_new")}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
Loading…
Reference in New Issue
Block a user