forked from Navy.gif/webserver-framework-frontend
users page
This commit is contained in:
parent
ae24a41328
commit
c16b3cd047
@ -1,9 +1,209 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Route, Routes, useNavigate, useParams } from "react-router";
|
||||
import ErrorBoundary from "../util/ErrorBoundary";
|
||||
import { get } from '../util/Util';
|
||||
import '../css/pages/Users.css';
|
||||
|
||||
const Permission = ({name, value}) => {
|
||||
return <li className="flex is-vertical-align">
|
||||
<label>{name}</label>
|
||||
<input max={10} min={0} type='number' style={{maxWidth: '60px'}} defaultValue={value}></input>
|
||||
</li>;
|
||||
};
|
||||
|
||||
const PermissionGroup = ({ name, value }) => {
|
||||
const elements = [];
|
||||
|
||||
for (const [perm, val] of Object.entries(value)) {
|
||||
const props = { key: perm, name: perm, value: val };
|
||||
if(typeof val ==='object') elements.push(<PermissionGroup {...props} />);
|
||||
else elements.push(<Permission {...props} />);
|
||||
}
|
||||
return <li>
|
||||
<b>Group: {name}</b>
|
||||
<ul>
|
||||
{elements}
|
||||
</ul>
|
||||
</li>;
|
||||
};
|
||||
|
||||
const Permissions = ({ perms }) => {
|
||||
|
||||
const elements = [];
|
||||
const keys = Object.keys(perms);
|
||||
for (const perm of keys) {
|
||||
const props = { key: perm, name: perm, value: perms[perm] };
|
||||
let Elem = null;
|
||||
switch (typeof perms[perm]) {
|
||||
case 'number':
|
||||
Elem = Permission;
|
||||
break;
|
||||
case 'object':
|
||||
Elem = PermissionGroup;
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line react/display-name
|
||||
Elem = () => {
|
||||
return <p>Uknown permission structure</p>;
|
||||
};
|
||||
break;
|
||||
}
|
||||
elements.push(<Elem {...props} />);
|
||||
}
|
||||
|
||||
return <div>
|
||||
<h4>Permissions </h4>
|
||||
<ul>
|
||||
{elements}
|
||||
</ul>
|
||||
</div>;
|
||||
};
|
||||
|
||||
// TODO: Make generic table list component and use it here and the user list
|
||||
const ApplicationList = ({ apps }) => {
|
||||
|
||||
|
||||
};
|
||||
|
||||
const Application = ({ app }) => {
|
||||
|
||||
|
||||
};
|
||||
|
||||
const User = ({ user }) => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
const [apps, updateApps] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const response = await get(`/api/users/${user._id}/applications`);
|
||||
if(response.status === 200) updateApps(response.data);
|
||||
})();
|
||||
}, [user]);
|
||||
|
||||
return <div className='user-card'>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-6">
|
||||
<div className="flex">
|
||||
<button className="button primary" onClick={() => {
|
||||
navigate(-1);
|
||||
}}>Back</button>
|
||||
<h3>User {user._id}</h3>
|
||||
</div>
|
||||
<label htmlFor='username'>Username:</label>
|
||||
<input id='username' defaultValue={user.username} />
|
||||
|
||||
<label htmlFor='displayName'>Display Name:</label>
|
||||
<input id='displayName' placeholder='Name to display instead of username' defaultValue={user.displayName} />
|
||||
|
||||
<select>
|
||||
<option>User</option>
|
||||
<option>Bob</option>
|
||||
</select>
|
||||
|
||||
<h4>Applications</h4>
|
||||
<Routes>
|
||||
<Route path='/' element={<ApplicationList apps={apps} />} />
|
||||
</Routes>
|
||||
{apps.map(app => <Application key={app._id} app={app} />)}
|
||||
|
||||
</div>
|
||||
|
||||
<div className="col-6">
|
||||
<Permissions perms={user.permissions} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button className="button primary">
|
||||
Save
|
||||
</button>
|
||||
|
||||
</div>;
|
||||
};
|
||||
|
||||
const UserListEntry = ({ user }) => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onClick = () => {
|
||||
navigate(`/users/${user._id}`);
|
||||
};
|
||||
|
||||
return <tr onClick={onClick} style={{cursor: 'pointer'}}>
|
||||
<td>{user.username}</td>
|
||||
<td>{user._id}</td>
|
||||
</tr>;
|
||||
|
||||
};
|
||||
|
||||
// TODO: Make table list generic component
|
||||
const UserList = ({ users }) => {
|
||||
|
||||
return <table className="striped" style={{maxWidth: '30em', marginBottom: '10px'}}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{users.map(user => <UserListEntry key={user._id} user={user} />)}
|
||||
</tbody>
|
||||
</table>;
|
||||
|
||||
};
|
||||
|
||||
const Users = () => {
|
||||
|
||||
return <div>
|
||||
USERS
|
||||
const [users, setUsers] = useState([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const result = await get('/api/users', { page });
|
||||
if (result.success) {
|
||||
setError(null);
|
||||
setUsers(result.data);
|
||||
} else setError(result.message);
|
||||
})();
|
||||
}, [page]);
|
||||
|
||||
const UserWrapper = () => {
|
||||
const { id } = useParams();
|
||||
const user = users.find(u => u._id === id);
|
||||
if (!user) return null;
|
||||
return <User user={user} />;
|
||||
};
|
||||
|
||||
const UserListWrapper = () => {
|
||||
return <div className="user-list-wrapper">
|
||||
<UserList users={users} />
|
||||
<div className='flex is-vertical-align page-controls'>
|
||||
<button className="col-1 button dark" onClick={() => setPage(page - 1 || 1)}>Previous</button>
|
||||
<p>Page: {page}</p>
|
||||
<button className="col-1 button dark" onClick={() => {
|
||||
if (users.length === 10) setPage(page + 1);
|
||||
}}>Next</button>
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
|
||||
return <div className="user-page">
|
||||
<p>USERS</p>
|
||||
{error && <p>{error}</p>}
|
||||
|
||||
<div className='user-list card'>
|
||||
<ErrorBoundary>
|
||||
<Routes>
|
||||
<Route path='/:id/*' element={<UserWrapper />} />
|
||||
<Route path='/' element={<UserListWrapper />} />
|
||||
</Routes>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
</div>;
|
||||
|
||||
};
|
||||
|
Reference in New Issue
Block a user