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' ;
14
18
import _ from 'lodash' ;
15
-
19
+ import moment from "moment" ;
16
20
17
21
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' ,
24
25
}
25
26
} ) ;
26
27
28
+
27
29
class Admin extends Component {
28
30
constructor ( props ) {
29
31
super ( props ) ;
30
32
this . state = {
31
33
activeIndex : 0 ,
32
- loading : false ,
33
- loadingCurrentFiles : false ,
34
- loadingStatistics : false ,
34
+ isLoading : false ,
35
35
statistics : [ ] ,
36
36
filesInput : undefined ,
37
37
fileListHtml : undefined ,
@@ -50,50 +50,50 @@ class Admin extends Component {
50
50
this . handleGetStatistics ( ) ;
51
51
}
52
52
53
- componentDidMount ( ) {
53
+ componentDidMount ( ) {
54
54
this . refreshPage ( ) ;
55
55
}
56
56
57
- handleIndexChange ( event , newIndex ) {
57
+ handleIndexChange ( event , newIndex ) {
58
58
this . setState ( { activeIndex : newIndex } ) ;
59
59
} ;
60
60
61
- async handleUpload ( event ) {
61
+ async handleUpload ( event ) {
62
62
event . preventDefault ( ) ;
63
63
64
- this . setState ( { loading : true } ) ;
64
+ this . setState ( { isLoading : true } ) ;
65
65
66
- var formData = new FormData ( ) ;
66
+ let formData = new FormData ( ) ;
67
67
68
68
let files = _ . get ( event , 'target.[0].files' ) ;
69
69
_ . forEach ( files , element => {
70
- formData . append ( 'file' , element , element . name )
70
+ formData . append ( 'file' , element , element . name )
71
71
} )
72
72
73
- await fetch ( "/api/file" , { method :'POST' , body :formData } )
73
+ await fetch ( "/api/file" , { method : 'POST' , body : formData } )
74
74
75
75
await this . handleGetFileList ( ) ;
76
76
77
- this . setState ( { loading : false } ) ;
77
+ this . setState ( { isLoading : false } ) ;
78
78
} ;
79
79
80
80
async handleExecute ( event ) {
81
81
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 } ) ;
84
84
85
85
const response = await fetch ( '/api/execute' ) ;
86
86
const result = await response . json ( ) ;
87
87
88
- this . setState ( { loading : false } ) ;
88
+ this . setState ( { isLoading : false } ) ;
89
89
90
90
this . refreshPage ( ) ;
91
91
92
92
return result
93
93
}
94
94
95
95
async handleGetStatistics ( ) {
96
- this . setState ( { loadingStatistics : true } )
96
+ this . setState ( { isLoading : true } )
97
97
98
98
try {
99
99
const statsData = await fetch ( "/api/statistics" ) ;
@@ -104,110 +104,113 @@ class Admin extends Component {
104
104
lastExecution : statsResponse . executionTime
105
105
} ) ;
106
106
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 } )
113
110
}
114
111
115
112
}
116
113
117
114
async handleGetFileList ( ) {
118
- this . setState ( { loadingCurrentFiles : true } )
115
+ this . setState ( { isLoading : true } )
119
116
120
- try {
117
+ try {
121
118
const filesData = await fetch ( "/api/listCurrentFiles" ) ;
122
119
const filesResponse = await filesData . json ( ) ;
123
120
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 } ) ;
134
122
135
- finally {
136
- this . setState ( { loadingCurrentFiles : false } )
123
+ } finally {
124
+ this . setState ( { isLoading : false } )
137
125
}
138
-
139
126
}
140
127
141
128
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 ;
186
130
187
131
return (
188
132
< 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 } } >
191
138
< 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 >
200
177
</ Paper >
201
178
</ 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 >
211
214
</ Grid >
212
215
</ Grid >
213
216
</ Grid >
0 commit comments