mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-02 21:32:42 +00:00
Add UI
This commit is contained in:
@@ -4,8 +4,9 @@ const createClass = require('create-react-class');
|
|||||||
|
|
||||||
const BrewUtils = require('./brewUtils/brewUtils.jsx');
|
const BrewUtils = require('./brewUtils/brewUtils.jsx');
|
||||||
const NotificationUtils = require('./notificationUtils/notificationUtils.jsx');
|
const NotificationUtils = require('./notificationUtils/notificationUtils.jsx');
|
||||||
|
import AuthorUtils from './authorUtils/authorUtils.jsx';
|
||||||
|
|
||||||
const tabGroups = ['brew', 'notifications'];
|
const tabGroups = ['brew', 'notifications', 'authors'];
|
||||||
|
|
||||||
const Admin = createClass({
|
const Admin = createClass({
|
||||||
getDefaultProps : function() {
|
getDefaultProps : function() {
|
||||||
@@ -39,6 +40,7 @@ const Admin = createClass({
|
|||||||
</nav>
|
</nav>
|
||||||
{this.state.currentTab==='brew' && <BrewUtils />}
|
{this.state.currentTab==='brew' && <BrewUtils />}
|
||||||
{this.state.currentTab==='notifications' && <NotificationUtils />}
|
{this.state.currentTab==='notifications' && <NotificationUtils />}
|
||||||
|
{this.state.currentTab==='authors' && <AuthorUtils />}
|
||||||
</main>
|
</main>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
90
client/admin/authorUtils/authorLookup/authorLookup.jsx
Normal file
90
client/admin/authorUtils/authorLookup/authorLookup.jsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import './authorLookup.less';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import request from 'superagent';
|
||||||
|
|
||||||
|
const authorLookup = ()=>{
|
||||||
|
const [author, setAuthor] = React.useState('');
|
||||||
|
const [searching, setSearching] = React.useState(false);
|
||||||
|
const [results, setResults] = React.useState([]);
|
||||||
|
|
||||||
|
const lookup = async ()=>{
|
||||||
|
if(!author) return;
|
||||||
|
|
||||||
|
setSearching(true);
|
||||||
|
setResults([]);
|
||||||
|
|
||||||
|
await request.get(`/admin/user/list/${author}`)
|
||||||
|
.then((brews)=>{
|
||||||
|
setResults(brews.body);
|
||||||
|
setSearching(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderResults = ()=>{
|
||||||
|
if(results.length == 0) return <>
|
||||||
|
<h2>Results</h2>
|
||||||
|
<p>None found.</p>
|
||||||
|
</>;
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<h2>{`Results - ${results.length}`}</h2>
|
||||||
|
<table className='resultsTable'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Share</th>
|
||||||
|
<th>Edit</th>
|
||||||
|
<th>Last Update</th>
|
||||||
|
<th>Storage</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{results
|
||||||
|
.sort((a, b)=>{ // Sort brews from most recently updated
|
||||||
|
if(a.updatedAt > b.updatedAt) return -1;
|
||||||
|
if(a.updatedAt < b.updatedAt) return 1;
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
.map((brew, idx)=>{
|
||||||
|
return <tr key={idx}>
|
||||||
|
<td>{brew.title}</td>
|
||||||
|
<td>{brew.shareId}</td>
|
||||||
|
<td>{brew.editId}</td>
|
||||||
|
<td>{brew.updatedAt}</td>
|
||||||
|
<td>{brew.googleId ? 'Google' : 'Homebrewery'}</td>
|
||||||
|
</tr>;
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyPress = (evt)=>{
|
||||||
|
if(evt.key === 'Enter') return lookup();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (evt)=>{
|
||||||
|
setAuthor(evt.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='authorLookup'>
|
||||||
|
<div className='authorLookupInputs'>
|
||||||
|
<h2>Author Lookup</h2>
|
||||||
|
<label className='field'>
|
||||||
|
Author Name:
|
||||||
|
<input className='fieldInput' value={author} onKeyDown={handleKeyPress} onChange={handleChange} />
|
||||||
|
<button onClick={lookup}>
|
||||||
|
<i className={`fas ${searching ? 'fa-spin fa-spinner' : 'fa-search'}`} />
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className='authorLookupResults'>
|
||||||
|
{renderResults()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = authorLookup;
|
||||||
48
client/admin/authorUtils/authorLookup/authorLookup.less
Normal file
48
client/admin/authorUtils/authorLookup/authorLookup.less
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
.authorLookup {
|
||||||
|
position : relative;
|
||||||
|
display : flex;
|
||||||
|
flex-direction : column;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
display : flex;
|
||||||
|
gap : 5px;
|
||||||
|
align-items : center;
|
||||||
|
justify-items : stretch;
|
||||||
|
width : 100%;
|
||||||
|
margin-bottom : 20px;
|
||||||
|
|
||||||
|
|
||||||
|
input {
|
||||||
|
height : 33px;
|
||||||
|
padding : 0px 10px;
|
||||||
|
margin-bottom : unset;
|
||||||
|
font-family : monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 50px;
|
||||||
|
|
||||||
|
i { margin-right : 10px; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.resultsTable {
|
||||||
|
* {
|
||||||
|
border: 1px solid black;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
client/admin/authorUtils/authorUtils.jsx
Normal file
13
client/admin/authorUtils/authorUtils.jsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import AuthorLookup from './authorLookup/authorLookup.jsx';
|
||||||
|
|
||||||
|
const authorUtils = ()=>{
|
||||||
|
return (
|
||||||
|
<section className='authorUtils'>
|
||||||
|
<AuthorLookup />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = authorUtils;
|
||||||
Reference in New Issue
Block a user