From 805e1a36dbbb856b1acae720cb632754be139d2e Mon Sep 17 00:00:00 2001 From: Roosted7 <thomasroos@live.nl> Date: Thu, 22 Mar 2018 17:40:48 +0100 Subject: [PATCH] Improve handeling of exam state in ui --- client/components/NavBar.jsx | 2 +- client/index.jsx | 54 ++++++++++++++++++++++-------------- client/views/Exam.jsx | 28 +++++++++---------- client/views/Fail.jsx | 23 +++++++++++++++ client/views/Loading.jsx | 23 +++++++++++++++ 5 files changed, 93 insertions(+), 37 deletions(-) create mode 100644 client/views/Fail.jsx create mode 100644 client/views/Loading.jsx diff --git a/client/components/NavBar.jsx b/client/components/NavBar.jsx index 0fa7f48d0..2ac80ca03 100644 --- a/client/components/NavBar.jsx +++ b/client/components/NavBar.jsx @@ -44,7 +44,7 @@ class NavBar extends React.Component { render() { - const examStyle = this.props.exam !== null ? {} : { pointerEvents: 'none', opacity: .65 } + const examStyle = this.props.exam && this.props.exam.submissions ? {} : { pointerEvents: 'none', opacity: .65 } return ( <nav className="navbar" role="navigation" aria-label="dropdown navigation"> diff --git a/client/index.jsx b/client/index.jsx index 16e57c3a0..dc605ac01 100644 --- a/client/index.jsx +++ b/client/index.jsx @@ -9,43 +9,44 @@ import * as api from './api.jsx' import NavBar from './components/NavBar.jsx'; import Footer from './components/Footer.jsx'; - -const Loading = () => <div>Loading...</div>; -const NotFound = () => <div>404 OMG NO.</div>; -const NoExams = () => <div>No exams found, please upload at least one and do not use this direct access :(</div>; +import Loading from './views/Loading.jsx'; const Home = Loadable({ loader: () => import('./views/Home.jsx'), - loading: Loading, + loading: Loading }); const AddExam = Loadable({ loader: () => import('./views/AddExam.jsx'), - loading: Loading, + loading: Loading }); const Exam = Loadable({ loader: () => import('./views/Exam.jsx'), - loading: Loading, + loading: Loading }); const Students = Loadable({ loader: () => import('./views/Students.jsx'), - loading: Loading, + loading: Loading }); const Grade = Loadable({ loader: () => import('./views/Grade.jsx'), - loading: Loading, + loading: Loading }); const Graders = Loadable({ loader: () => import('./views/Graders.jsx'), - loading: Loading, + loading: Loading }); const Statistics = Loadable({ loader: () => import('./views/Statistics.jsx'), - loading: Loading, + loading: Loading }); const Reset = Loadable({ loader: () => import('./views/Reset.jsx'), - loading: Loading, + loading: Loading }); +const Fail = Loadable({ + loader: () => import('./views/Fail.jsx'), + loading: Loading +}) class App extends React.Component { @@ -59,14 +60,20 @@ class App extends React.Component { this.updateExamList(); } - updateExamList = (callback) => { + updateExamList = (callback, onlyList) => { api.get('exams') .then(exams => { if (exams.length) { - this.setState({ - examIndex: exams.length - 1, - examList: exams - }, callback) + if (onlyList) { + this.setState({ + examList: exams + }) + } else { + this.setState({ + examIndex: exams.length - 1, + examList: exams + }, callback) + } } }) .catch(resp => { @@ -98,16 +105,21 @@ class App extends React.Component { <Switch> <Route exact path="/" component={Home} /> <Route path="/exams/:examID" render={({match}) => - <Exam exam={exam} urlID={match.params.examID} changeExam={this.changeExam} /> }/> + <Exam exam={exam} urlID={match.params.examID} changeExam={this.changeExam} updateList={this.updateExamList}/> }/> <Route path="/exams" render={({history}) => <AddExam updateExamList={this.updateExamList} changeURL={history.push} /> }/> <Route path="/students" render={() => <Students exam={exam} /> }/> - <Route path="/grade" component={exam ? Grade : NoExams} /> - <Route path="/statistics" component={exam ? Statistics : NoExams} /> + <Route path="/grade" render={() => ( + exam && exam.submissions ? <Grade /> : <Fail message="No exams uploaded. Please do not bookmark URLs" /> + )} /> + <Route path="/statistics" render={() => ( + exam && exam.submissions ? <Statistics /> : <Fail message="No exams uploaded. Please do not bookmark URLs" /> + )} /> <Route path="/graders" component={Graders} /> <Route path="/reset" component={Reset} /> - <Route component={NotFound} /> + <Route render={() => + <Fail message="404. Could not find that page :'(" /> }/> </Switch> <Footer /> </div> diff --git a/client/views/Exam.jsx b/client/views/Exam.jsx index 59d52185f..a51c0a146 100644 --- a/client/views/Exam.jsx +++ b/client/views/Exam.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import Dropzone from 'react-dropzone' +import Dropzone from 'react-dropzone'; import Hero from '../components/Hero.jsx'; import DropzoneContent from '../components/DropzoneContent.jsx'; @@ -36,7 +36,7 @@ class Exams extends React.Component { loadExam = (id) => { if (this.props.exam.id !== parseInt(id)) { - console.log('Changing exam id to ' + id) + console.log('Changing exam id to ' + id) this.props.changeExam(parseInt(id)); } @@ -65,11 +65,14 @@ class Exams extends React.Component { updatePDFs = () => { api.get('pdfs/' + this.props.urlID) - .then(pdfs => - this.setState({ + .then(pdfs => { + if (JSON.stringify(pdfs) != JSON.stringify(this.state.pdfs)) { + this.props.updateList(null, true) + this.setState({ pdfs: pdfs - }) - ) + }) + } + }) } onDropPDF = (accepted, rejected) => { @@ -82,12 +85,7 @@ class Exams extends React.Component { data.append('pdf', file) api.post('pdfs/' + this.props.urlID, data) .then(() => { - api.get('pdfs/' + this.props.urlID) - .then(pdfs => - this.setState({ - pdfs: pdfs - }) - ) + this.updatePDFs(); }) .catch(resp => { alert('failed to upload pdf (see javascript console for details)') @@ -98,12 +96,12 @@ class Exams extends React.Component { componentDidMount = () => { this.loadExam(this.props.urlID); - this.pdfUpdater = setInterval(this.updatePDFs, 1000) + this.pdfUpdater = setInterval(this.updatePDFs, 1000) } componentWillReceiveProps = (newProps) => { if (newProps.urlID !== this.props.urlID) { - this.loadExam(newProps.urlID) + this.loadExam(newProps.urlID) } } @@ -144,7 +142,7 @@ class Exams extends React.Component { disablePreview multiple > - <DropzoneContent/> + <DropzoneContent /> </Dropzone> <br /> diff --git a/client/views/Fail.jsx b/client/views/Fail.jsx new file mode 100644 index 000000000..8d1459db4 --- /dev/null +++ b/client/views/Fail.jsx @@ -0,0 +1,23 @@ +import React from 'react'; + +import Hero from '../components/Hero.jsx'; + +const Home = (props) => { + return ( + <div> + + <Hero title='Oops!' subtitle={props.message ? props.message : "Something went wrong :'("} /> + + <section className="section"> + + <div className="container"> + + </div> + + </section> + + </div> + ) +} + +export default Home; diff --git a/client/views/Loading.jsx b/client/views/Loading.jsx new file mode 100644 index 000000000..dbbdf9e26 --- /dev/null +++ b/client/views/Loading.jsx @@ -0,0 +1,23 @@ +import React from 'react'; + +import Hero from '../components/Hero.jsx'; + +const Home = () => { + return ( + <div> + + <Hero title='' subtitle='' /> + + <section className="section"> + + <div className="container"> + + </div> + + </section> + + </div> + ) +} + +export default Home; -- GitLab