Update #2 - Electric Boogaloo #2

Merged
D3vision merged 7 commits from Navy.gif/webserver-framework-frontend:master into master 2022-11-24 10:33:25 +01:00
3 changed files with 83 additions and 57 deletions
Showing only changes of commit 336428ed56 - Show all commits

View File

@ -1,29 +0,0 @@
import React from 'react';
import '../css/components/Sidebar.css';
import NavLink from '../structures/NavLink';
const Sidebar = ({children}) => {
return <div className='sidebar'>
{children}
</div>;
};
// Nav menu
const SidebarMenu = ({menuItems, children}) => {
let key = 0;
return <div className='sidebar-menu'>
{menuItems.map(link => {
const { label, ...rest } = link;
return <NavLink activeClassName='active' className='sidebar-menu-item' key={key++} {...rest}>{ label}</NavLink>;
})}
{children}
</div>;
};
export {SidebarMenu, Sidebar};
export default Sidebar;

24
src/components/Table.js Normal file
View File

@ -0,0 +1,24 @@
import React from "react";
export const TableListEntry = ({onClick, item, itemKeys}) => {
return <tr onClick={onClick} style={{cursor: 'pointer'}}>
{itemKeys.map(key => <td key={key}>{item[key]}</td>)}
</tr>;
};
export const Table = ({headerItems, children, items, itemKeys, maxWidth = '30em'}) => {
let i = 0;
return <table className="striped" style={{ maxWidth, marginBottom: '10px' }}>
<thead>
<tr>
{headerItems.map(item => <th key={item}>{item}</th>)}
</tr>
</thead>
<tbody>
{children ? children : items.map(item => <TableListEntry key={i++} item={item} itemKeys={itemKeys} />)}
</tbody>
</table>;
};

View File

@ -3,6 +3,7 @@ import { Route, Routes, useNavigate, useParams } from "react-router";
import ErrorBoundary from "../util/ErrorBoundary"; import ErrorBoundary from "../util/ErrorBoundary";
import { get } from '../util/Util'; import { get } from '../util/Util';
import '../css/pages/Users.css'; import '../css/pages/Users.css';
import { Table, TableListEntry } from "../components/Table";
const Permission = ({name, value}) => { const Permission = ({name, value}) => {
return <li className="flex is-vertical-align"> return <li className="flex is-vertical-align">
@ -59,9 +60,19 @@ const Permissions = ({ perms }) => {
</div>; </div>;
}; };
// TODO: Make generic table list component and use it here and the user list
const ApplicationList = ({ apps }) => { const ApplicationList = ({ apps }) => {
const navigate = useNavigate();
return <Table headerItems={['Name', 'ID']}>
{apps.map(app => <TableListEntry
onClick={() => {
navigate(`${window.location.pathname}/applications/${app.id}`);
}}
key={app.id}
item={app}
itemKeys={['name', 'id']}
/>)}
</Table>;
}; };
@ -80,7 +91,14 @@ const User = ({ user }) => {
const response = await get(`/api/users/${user._id}/applications`); const response = await get(`/api/users/${user._id}/applications`);
if(response.status === 200) updateApps(response.data); if(response.status === 200) updateApps(response.data);
})(); })();
}, [user]); }, []);
const ApplicationWrapper = () => {
const { appid } = useParams();
const app = apps.find(a => a._id === appid);
if (!app) return null;
return <Application app={app} />;
};
return <div className='user-card'> return <div className='user-card'>
@ -106,8 +124,9 @@ const User = ({ user }) => {
<h4>Applications</h4> <h4>Applications</h4>
<Routes> <Routes>
<Route path='/' element={<ApplicationList apps={apps} />} /> <Route path='/' element={<ApplicationList apps={apps} />} />
<Route path='/applications/:appid' element={<ApplicationWrapper />} />
</Routes> </Routes>
{apps.map(app => <Application key={app._id} app={app} />)} {/* {apps.map(app => <Application key={app._id} app={app} />)} */}
</div> </div>
@ -123,37 +142,37 @@ const User = ({ user }) => {
</div>; </div>;
}; };
const UserListEntry = ({ user }) => { // const UserListEntry = ({ user }) => {
const navigate = useNavigate(); // const navigate = useNavigate();
const onClick = () => { // const onClick = () => {
navigate(`/users/${user._id}`); // navigate(`/users/${user._id}`);
}; // };
return <tr onClick={onClick} style={{cursor: 'pointer'}}> // return <tr onClick={onClick} style={{cursor: 'pointer'}}>
<td>{user.username}</td> // <td>{user.username}</td>
<td>{user._id}</td> // <td>{user._id}</td>
</tr>; // </tr>;
}; // };
// TODO: Make table list generic component // // TODO: Make table list generic component
const UserList = ({ users }) => { // const UserList = ({ users }) => {
return <table className="striped" style={{maxWidth: '30em', marginBottom: '10px'}}> // return <table className="striped" style={{maxWidth: '30em', marginBottom: '10px'}}>
<thead> // <thead>
<tr> // <tr>
<th>Username</th> // <th>Username</th>
<th>ID</th> // <th>ID</th>
</tr> // </tr>
</thead> // </thead>
<tbody> // <tbody>
{users.map(user => <UserListEntry key={user._id} user={user} />)} // {users.map(user => <UserListEntry key={user._id} user={user} />)}
</tbody> // </tbody>
</table>; // </table>;
}; // };
const Users = () => { const Users = () => {
@ -178,9 +197,20 @@ const Users = () => {
return <User user={user} />; return <User user={user} />;
}; };
const navigate = useNavigate();
const UserListWrapper = () => { const UserListWrapper = () => {
return <div className="user-list-wrapper"> return <div className="user-list-wrapper">
<UserList users={users} />
<Table headerItems={['Username', 'ID']}>
{users.map(user => <TableListEntry
onClick={() => {
navigate(`/users/${user._id}`);
}}
key={user._id}
item={user}
itemKeys={['username', '_id']} />)}
</Table>
<div className='flex is-vertical-align page-controls'> <div className='flex is-vertical-align page-controls'>
<button className="col-1 button dark" onClick={() => setPage(page - 1 || 1)}>Previous</button> <button className="col-1 button dark" onClick={() => setPage(page - 1 || 1)}>Previous</button>
<p>Page: {page}</p> <p>Page: {page}</p>
@ -188,6 +218,7 @@ const Users = () => {
if (users.length === 10) setPage(page + 1); if (users.length === 10) setPage(page + 1);
}}>Next</button> }}>Next</button>
</div> </div>
</div>; </div>;
}; };