forked from Navy.gif/webserver-framework-frontend
Get updated framework #1
@ -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 = () => {
|
const Users = () => {
|
||||||
|
|
||||||
return <div>
|
const [users, setUsers] = useState([]);
|
||||||
USERS
|
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>;
|
</div>;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user