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