Skip to content

Commit ceee4e5

Browse files
authored
Merge pull request #226 from CodeForPhilly/ui-admin-improvement
improve Admin UI (issue-213)
2 parents 35a4b27 + 6e8efb2 commit ceee4e5

File tree

2 files changed

+122
-187
lines changed

2 files changed

+122
-187
lines changed

src/client/src/components/Forms.js

Lines changed: 0 additions & 68 deletions
This file was deleted.

src/client/src/pages/Admin.js

Lines changed: 122 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
1-
import React, { Component } from 'react';
2-
import {Tabs, Tab, Paper } from "@material-ui/core";
3-
import TabPanel from '../components/TabPanel';
4-
import Grid from '@material-ui/core/Grid';
5-
import Table from '@material-ui/core/Table';
6-
import TableBody from '@material-ui/core/TableBody';
7-
import TableCell from '@material-ui/core/TableCell';
8-
import TableContainer from '@material-ui/core/TableContainer';
9-
import TableRow from '@material-ui/core/TableRow';
10-
import { withStyles } from '@material-ui/core/styles';
11-
import LinearProgress from '@material-ui/core/LinearProgress';
12-
import CircularProgress from '@material-ui/core/CircularProgress';
13-
import { UploadForm, ExecuteForm } from '../components/Forms';
1+
import React, {Component} from 'react';
2+
import {
3+
Grid,
4+
Paper,
5+
Button,
6+
TableHead,
7+
Backdrop,
8+
CircularProgress,
9+
CardContent,
10+
TableRow,
11+
TableContainer,
12+
TableCell,
13+
TableBody,
14+
Table
15+
} from "@material-ui/core";
16+
17+
import {withStyles} from '@material-ui/core/styles';
1418
import _ from 'lodash';
15-
19+
import moment from "moment";
1620

1721
const styles = theme => ({
18-
loader: {
19-
marginTop: "40px"
20-
},
21-
spinner: {
22-
display: 'flex',
23-
marginLeft: theme.spacing(2)
22+
backdrop: {
23+
zIndex: theme.zIndex.drawer + 1,
24+
color: '#fff',
2425
}
2526
});
2627

28+
2729
class Admin extends Component {
2830
constructor(props) {
2931
super(props);
3032
this.state = {
3133
activeIndex: 0,
32-
loading: false,
33-
loadingCurrentFiles: false,
34-
loadingStatistics: false,
34+
isLoading: false,
3535
statistics: [],
3636
filesInput: undefined,
3737
fileListHtml: undefined,
@@ -50,50 +50,50 @@ class Admin extends Component {
5050
this.handleGetStatistics();
5151
}
5252

53-
componentDidMount(){
53+
componentDidMount() {
5454
this.refreshPage();
5555
}
5656

57-
handleIndexChange(event, newIndex){
57+
handleIndexChange(event, newIndex) {
5858
this.setState({activeIndex: newIndex});
5959
};
6060

61-
async handleUpload(event){
61+
async handleUpload(event) {
6262
event.preventDefault();
6363

64-
this.setState({loading: true});
64+
this.setState({isLoading: true});
6565

66-
var formData = new FormData();
66+
let formData = new FormData();
6767

6868
let files = _.get(event, 'target.[0].files');
6969
_.forEach(files, element => {
70-
formData.append('file', element, element.name)
70+
formData.append('file', element, element.name)
7171
})
7272

73-
await fetch("/api/file", { method:'POST', body:formData })
73+
await fetch("/api/file", {method: 'POST', body: formData})
7474

7575
await this.handleGetFileList();
7676

77-
this.setState({loading: false});
77+
this.setState({isLoading: false});
7878
};
7979

8080
async handleExecute(event) {
8181
event.preventDefault();
82-
// TODO: it looks like it handles it, but may want to tie events into stats too (like set loadingStatistics: true)
83-
this.setState({loading: true});
82+
83+
this.setState({isLoading: true});
8484

8585
const response = await fetch('/api/execute');
8686
const result = await response.json();
8787

88-
this.setState({loading: false});
88+
this.setState({isLoading: false});
8989

9090
this.refreshPage();
9191

9292
return result
9393
}
9494

9595
async handleGetStatistics() {
96-
this.setState({loadingStatistics: true})
96+
this.setState({isLoading: true})
9797

9898
try {
9999
const statsData = await fetch("/api/statistics");
@@ -104,110 +104,113 @@ class Admin extends Component {
104104
lastExecution: statsResponse.executionTime
105105
});
106106

107-
console.log("statisticsListHtml", this.state.statistics);
108-
// this.setState({statisticsListHtml: stats});
109-
this.setState({loadingStatistics: false})
110-
}
111-
finally {
112-
this.setState({loadingStatistics: false})
107+
this.setState({isLoading: false})
108+
} finally {
109+
this.setState({isLoading: false})
113110
}
114111

115112
}
116113

117114
async handleGetFileList() {
118-
this.setState({loadingCurrentFiles: true})
115+
this.setState({isLoading: true})
119116

120-
try{
117+
try {
121118
const filesData = await fetch("/api/listCurrentFiles");
122119
const filesResponse = await filesData.json();
123120

124-
// this.setState({fileList: filesResponse});
125-
126-
this.setState({fileListHtml: _.map(filesResponse, (fileName) => {
127-
return (<li key={fileName}> {fileName}</li>)
128-
})});
129-
130-
console.log("fileListHtml", this.state.fileListHtml);
131-
//just a UX indication that a new list has been loaded
132-
//await new Promise(resolve => setTimeout(resolve, 1000));
133-
}
121+
this.setState({fileListHtml: filesResponse});
134122

135-
finally {
136-
this.setState({loadingCurrentFiles: false})
123+
} finally {
124+
this.setState({isLoading: false})
137125
}
138-
139126
}
140127

141128
render() {
142-
const { classes } = this.props;
143-
144-
let currentTabWithState = this.state.loading === true ?
145-
<div className={classes.loader}>
146-
<LinearProgress />
147-
</div>
148-
:
149-
<div>
150-
<TabPanel value={this.state.activeIndex} index={0}>
151-
<UploadForm filesInput={this.state.filesInput} handleUpload={this.handleUpload}/>
152-
</TabPanel>
153-
<TabPanel value={this.state.activeIndex} index={1}>
154-
<ExecuteForm handleExecute={this.handleExecute}/>
155-
</TabPanel>
156-
</div>
157-
158-
let currentListWithState = this.state.loadingCurrentFiles === true ?
159-
<div className={classes.spinner}>
160-
<CircularProgress />
161-
</div>
162-
:
163-
<Paper style={{padding: 5}}>
164-
<ul>{this.state.fileListHtml}</ul>
165-
</Paper>
166-
167-
let currentStatistics = this.state.loadingStatistics === true ?
168-
<div className={classes.spinner}>
169-
<CircularProgress />
170-
</div>
171-
: _.isEmpty(this.state.statistics) !== true &&
172-
<TableContainer component={Paper} className="statisticsData">
173-
<Table aria-label="simple table" className={classes.table}>
174-
<TableBody>
175-
{this.state.statistics.map((row, index) => (
176-
<TableRow key={index}>
177-
<TableCell align="left" component="th" scope="row">
178-
{row[0]}
179-
</TableCell>
180-
<TableCell align="left">{row[1]}</TableCell>
181-
</TableRow>
182-
))}
183-
</TableBody>
184-
</Table>
185-
</TableContainer>
129+
const {classes} = this.props;
186130

187131
return (
188132
<div style={{paddingLeft: 20}}>
189-
<h2>Admin Portal</h2>
190-
<Grid container spacing={3} direction="column" style={{padding:30}}>
133+
<h1>Admin Portal</h1>
134+
<Backdrop className={classes.backdrop} open={this.state.isLoading === true}>
135+
<CircularProgress size={60}/>
136+
</Backdrop>
137+
<Grid container spacing={3} direction="column" style={{padding: 30}}>
191138
<Grid container spacing={3} direction="row">
192-
<Grid item sm={5} >
193-
<h3>Options</h3>
194-
<Paper style={{padding: 5}}>
195-
<Tabs value={this.state.activeIndex} onChange={this.handleIndexChange}>
196-
<Tab label="Upload" />
197-
<Tab label="Execute" />
198-
</Tabs>
199-
{currentTabWithState}
139+
<Grid item sm={6}>
140+
<h2>Latest Files</h2>
141+
{_.isEmpty(this.state.fileListHtml) !== true &&
142+
<TableContainer component={Paper} className="statisticsData">
143+
<Table aria-label="simple table" className={classes.table}>
144+
<TableHead>
145+
<TableRow>
146+
<TableCell><b>File Type</b></TableCell>
147+
<TableCell><b>Last Updated</b></TableCell>
148+
</TableRow>
149+
</TableHead>
150+
<TableBody>
151+
{_.map(this.state.fileListHtml, file => {
152+
const fileName = file.split("-")[0];
153+
let fileDate = file.split("-").slice(1).join().split(".")[0];
154+
let fileDateOnlyNumbers = fileDate.replaceAll(",", "");
155+
let fileDateFormatted = moment(fileDateOnlyNumbers, "YYYYMMDDhmmss").local().format("MMMM Do YYYY, h:mm:ss a");
156+
157+
return (
158+
<TableRow>
159+
<TableCell>{fileName}</TableCell>
160+
<TableCell>{fileDateFormatted}</TableCell>
161+
</TableRow>
162+
)
163+
})
164+
}
165+
</TableBody>
166+
</Table>
167+
</TableContainer>}
168+
169+
<Paper style={{padding: 5, marginTop: 10}}>
170+
<CardContent>
171+
<h3 style={{marginTop: 0}}>Upload Files</h3>
172+
<form onSubmit={this.handleUpload}>
173+
<input type="file" value={this.state.filesInput} multiple/>
174+
<Button type="submit" variant="contained" color="primary">Upload</Button>
175+
</form>
176+
</CardContent>
200177
</Paper>
201178
</Grid>
202-
<Grid item sm={4}>
203-
<h3>Current Files</h3>
204-
{currentListWithState}
205-
</Grid>
206-
</Grid>
207-
<Grid container spacing={3} direction="row">
208-
<Grid item sm={4}>
209-
<h3>Matching Stats from last Execution: {this.state.lastExecution}</h3>
210-
{currentStatistics}
179+
180+
<Grid item sm={6}>
181+
<h2> Last Match Analysis </h2>
182+
{_.isEmpty(this.state.statistics) !== true &&
183+
<TableContainer component={Paper} className="statisticsData">
184+
<Table aria-label="simple table" className={classes.table}>
185+
<TableBody>
186+
<TableRow key='time'>
187+
<TableCell align="left" component="th" scope="row">
188+
<b>Last Analysis</b>
189+
</TableCell>
190+
<TableCell align="left">
191+
<b>{moment(this.state.lastExecution, "dddd MMMM Do h:mm:ss YYYY").local().format("MMMM Do YYYY, h:mm:ss a")}</b>
192+
</TableCell>
193+
</TableRow>
194+
{this.state.statistics.map((row, index) => (
195+
<TableRow key={index}>
196+
<TableCell align="left" component="th" scope="row">
197+
{row[0]}
198+
</TableCell>
199+
<TableCell align="left">{row[1]}</TableCell>
200+
</TableRow>
201+
))}
202+
</TableBody>
203+
</Table>
204+
</TableContainer>}
205+
<Paper style={{padding: 5, marginTop: 10}}>
206+
<CardContent>
207+
<h3 style={{marginTop: 0}}>Run New Analysis</h3>
208+
<form onSubmit={this.handleExecute}>
209+
<Button type="submit" variant="contained"
210+
color="primary">Run Data Analysis</Button>
211+
</form>
212+
</CardContent>
213+
</Paper>
211214
</Grid>
212215
</Grid>
213216
</Grid>

0 commit comments

Comments
 (0)