From 67470b54b2041475f74c7c50e89fbf8e49e7a2da Mon Sep 17 00:00:00 2001
From: "robinwilliam.hundt" <robinwilliam.hundt@stud.uni-goettingen.de>
Date: Fri, 22 Dec 2017 22:02:18 +0100
Subject: [PATCH] Tutor Layout and SubmissioCorrectionPage

Basic TutorLayout and SubmissionCorrectionPage. Added new dependency v-clipboard. Run yarn install to update.
---
 core/serializers.py                           | 11 ++-
 frontend/package.json                         |  1 +
 frontend/src/components/SubmissionType.vue    | 34 ++++++--
 .../src/components/student/SubmissionList.vue |  2 +-
 .../submission_notes/AnnotatedSubmission.vue  | 64 ++++++++++-----
 .../submission_notes/CorrectionHelpCard.vue   | 38 +++++++++
 .../submission_notes/FeedbackComment.vue      |  2 +-
 .../submission_notes/FeedbackForm.vue         | 19 +++--
 .../AnnotatedSubmissionBottomToolbar.vue      | 64 +++++++++++++++
 .../AnnotatedSubmissionTopToolbar.vue         | 44 ++++++++++
 frontend/src/main.js                          |  2 +
 frontend/src/pages/Login.vue                  | 17 ++--
 .../src/pages/SubmissionCorrectionPage.vue    | 81 +++++++++++++++++++
 frontend/src/pages/student/StudentLayout.vue  |  1 +
 frontend/src/pages/tutor/TutorLayout.vue      | 57 +++++++++++++
 frontend/src/router/index.js                  | 15 +++-
 frontend/src/store/store.js                   | 14 +++-
 frontend/yarn.lock                            |  4 +
 18 files changed, 423 insertions(+), 47 deletions(-)
 create mode 100644 frontend/src/components/submission_notes/CorrectionHelpCard.vue
 create mode 100644 frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionBottomToolbar.vue
 create mode 100644 frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionTopToolbar.vue
 create mode 100644 frontend/src/pages/SubmissionCorrectionPage.vue
 create mode 100644 frontend/src/pages/tutor/TutorLayout.vue

diff --git a/core/serializers.py b/core/serializers.py
index 74db00cf..b64a4cf1 100644
--- a/core/serializers.py
+++ b/core/serializers.py
@@ -50,9 +50,16 @@ class TestSerializer(DynamicFieldsModelSerializer):
         fields = ('name', 'label', 'annotation')
 
 
-class SubmissionTypeSerializer(DynamicFieldsModelSerializer):
+class SubmissionTypeListSerializer(DynamicFieldsModelSerializer):
     fullScore = serializers.IntegerField(source='full_score')
 
+    class Meta:
+        model = SubmissionType
+        fields = ('id', 'name', 'fullScore')
+
+
+class SubmissionTypeSerializer(SubmissionTypeListSerializer):
+
     class Meta:
         model = SubmissionType
         fields = ('id', 'name', 'fullScore', 'description', 'solution')
@@ -69,7 +76,7 @@ class SubmissionSerializer(DynamicFieldsModelSerializer):
 
 
 class SubmissionListSerializer(DynamicFieldsModelSerializer):
-    type = SubmissionTypeSerializer(fields=('id', 'name', 'fullScore'))
+    type = SubmissionTypeListSerializer()
     # TODO change this according to new feedback model
     feedback = FeedbackSerializer(fields=('score',))
 
diff --git a/frontend/package.json b/frontend/package.json
index 9f4245d5..03ef1b1c 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -16,6 +16,7 @@
     "axios": "^0.17.0",
     "google-code-prettify": "^1.0.5",
     "material-design-icons": "^3.0.1",
+    "v-clipboard": "^1.0.4",
     "vue": "^2.5.2",
     "vue-router": "^3.0.1",
     "vuetify": "^0.17.3",
diff --git a/frontend/src/components/SubmissionType.vue b/frontend/src/components/SubmissionType.vue
index 5827cbb6..6cf35fce 100644
--- a/frontend/src/components/SubmissionType.vue
+++ b/frontend/src/components/SubmissionType.vue
@@ -3,13 +3,13 @@
     <h2 class="mb-2">{{ name }} - Full score: {{ fullScore }}</h2>
     <v-expansion-panel expand>
       <v-expansion-panel-content
-      v-for="(item, key, i) in {Description: description, Solution:solution}" 
+      v-for="(item, i) in typeItems"
       :key="i"
-      :value="expandedByDefault[key]">
-      <div slot="header">{{ key }}</div>
+      :value="expandedByDefault[item.title]">
+      <div slot="header">{{ item.title }}</div>
         <v-card color="grey lighten-4">
           <v-card-text>
-            {{ item }}
+            {{ item.text }}
           </v-card-text>
         </v-card>
       </v-expansion-panel-content>
@@ -38,6 +38,10 @@
         type: Number,
         required: true
       },
+      reverse: {
+        type: Boolean,
+        default: false
+      },
       expandedByDefault: {
         type: Object,
         default: function () {
@@ -45,8 +49,26 @@
             Description: true,
             Solution: true
           }
-        },
-        required: false
+        }
+      }
+    },
+    computed: {
+      typeItems () {
+        let items = [
+          {
+            title: 'Description',
+            text: this.description
+          },
+          {
+            title: 'Solution',
+            text: this.solution
+          }
+        ]
+        if (this.reverse) {
+          return items.reverse()
+        } else {
+          return items
+        }
       }
     }
   }
diff --git a/frontend/src/components/student/SubmissionList.vue b/frontend/src/components/student/SubmissionList.vue
index 7ef34f95..451404f9 100644
--- a/frontend/src/components/student/SubmissionList.vue
+++ b/frontend/src/components/student/SubmissionList.vue
@@ -10,7 +10,7 @@
         <td>{{ props.item.type.name }}</td>
         <td class="text-xs-right">{{ props.item.feedback.score }}</td>
         <td class="text-xs-right">{{ props.item.type.fullScore }}</td>
-        <td class="text-xs-right"><v-btn :to="`submission/${props.item.type.id}`" color="orange lighten-2"><v-icon>chevron_right</v-icon></v-btn></td>
+        <td class="text-xs-right"><v-btn :to="`/student/submission/${props.item.type.id}`" color="orange lighten-2"><v-icon>chevron_right</v-icon></v-btn></td>
       </template>
     </v-data-table>
     <v-alert color="info" value="true">
diff --git a/frontend/src/components/submission_notes/AnnotatedSubmission.vue b/frontend/src/components/submission_notes/AnnotatedSubmission.vue
index d5c24b1b..a3fdb504 100644
--- a/frontend/src/components/submission_notes/AnnotatedSubmission.vue
+++ b/frontend/src/components/submission_notes/AnnotatedSubmission.vue
@@ -1,33 +1,49 @@
 <template>
-  <table class="elevation-1">
-    <tr v-for="(code, index) in submission" :key="index">
-      <td class="line-number-cell">
-        <v-btn block class="line-number-btn" @click="toggleEditorOnLine(index)">{{ index }}</v-btn>
-      </td>
-      <td>
-        <pre class="prettyprint"><code class="lang-c"> {{ code }}</code></pre>
-        <feedback-comment
-          v-if="feedback[index] && !showEditorOnLine[index]"
-          @click="toggleEditorOnLine(index)">{{ feedback[index] }}
-        </feedback-comment>
-        <comment-form
-          v-if="showEditorOnLine[index] && editable"
-          @collapseFeedbackForm="showEditorOnLine[index] = false"
-          :feedback="feedback[index]"
-          :index="index">
-        </comment-form>
-      </td>
-    </tr>
-  </table>
+  <v-container>
+    <annotated-submission-top-toolbar
+      v-if="isTutor || isReviewer"
+      class="mb-1 elevation-1"
+      :submission="rawSubmission"
+    />
+    <table class="elevation-1">
+      <tr v-for="(code, index) in submission" :key="index">
+        <td class="line-number-cell">
+          <v-btn block class="line-number-btn" @click="toggleEditorOnLine(index)">{{ index }}</v-btn>
+        </td>
+        <td>
+          <pre class="prettyprint"><code class="lang-c"> {{ code }}</code></pre>
+          <feedback-comment
+            v-if="feedback[index] && !showEditorOnLine[index]"
+            @click.native="toggleEditorOnLine(index)">{{ feedback[index] }}
+          </feedback-comment>
+          <comment-form
+            v-if="showEditorOnLine[index] && editable"
+            @collapseFeedbackForm="showEditorOnLine[index] = false"
+            :feedback="feedback[index]"
+            :index="index">
+          </comment-form>
+        </td>
+      </tr>
+    </table>
+    <annotated-submission-bottom-toolbar
+      v-if="isTutor || isReviewer"
+      class="mt-1 elevation-1"
+    />
+  </v-container>
 </template>
 
 
 <script>
+  import { mapGetters } from 'vuex'
   import CommentForm from '@/components/submission_notes/FeedbackForm.vue'
   import FeedbackComment from '@/components/submission_notes/FeedbackComment.vue'
+  import AnnotatedSubmissionTopToolbar from '@/components/submission_notes/toolbars/AnnotatedSubmissionTopToolbar'
+  import AnnotatedSubmissionBottomToolbar from '@/components/submission_notes/toolbars/AnnotatedSubmissionBottomToolbar'
 
   export default {
     components: {
+      AnnotatedSubmissionBottomToolbar,
+      AnnotatedSubmissionTopToolbar,
       FeedbackComment,
       CommentForm},
     name: 'annotated-submission',
@@ -60,7 +76,12 @@
           acc[index + 1] = cur
           return acc
         }, {})
-      }
+      },
+      ...mapGetters([
+        'isStudent',
+        'isTutor',
+        'isReviewer'
+      ])
     },
     methods: {
       toggleEditorOnLine (lineIndex) {
@@ -79,6 +100,7 @@
   table {
     table-layout: auto;
     border-collapse: collapse;
+    width: 100%;
   }
 
 
diff --git a/frontend/src/components/submission_notes/CorrectionHelpCard.vue b/frontend/src/components/submission_notes/CorrectionHelpCard.vue
new file mode 100644
index 00000000..ae204d18
--- /dev/null
+++ b/frontend/src/components/submission_notes/CorrectionHelpCard.vue
@@ -0,0 +1,38 @@
+<template>
+    <v-card class="help-card">
+      <v-card-title>
+        <v-icon>help_outline</v-icon>
+        <h3>Tips on using the correction interface</h3>
+      </v-card-title>
+      <v-card-text>
+        Never trade an ale.
+        The sea-dog leads with yellow fever, crush the captain's quarters until it waves.<br>
+        Ho-ho-ho! malaria of life.<br>
+        Halitosis, adventure, and yellow fever.<br>
+        The girl drinks with halitosis, pull the galley before it laughs.<br>
+        The moon fires with life, vandalize the bikini atoll before it travels.<br>
+        The tuna blows with fight, haul the freighter before it whines.<br>
+        The cannibal robs with hunger, fire the lighthouse until it whines.<br>
+        The captain loves with death, vandalize the lighthouse before it whines.<br>
+        The anchor loots with treasure, raid the freighter before it grows.<br>
+        The reef commands with endurance, view the quarter-deck until it whines.<br>
+        The scallywag loots with passion, crush the bikini atoll before it falls.<br>
+        The sea leads with treasure, ransack the brig until it dies.<br>
+        The parrot robs with desolation, view the seychelles before it screams.<br>
+        The warm anchor quirky blows the landlubber.<br>
+
+      </v-card-text>
+    </v-card>
+</template>
+
+<script>
+  export default {
+    name: 'correction-help-card'
+  }
+</script>
+
+<style scoped>
+  .help-card {
+    width: fit-content;
+  }
+</style>
diff --git a/frontend/src/components/submission_notes/FeedbackComment.vue b/frontend/src/components/submission_notes/FeedbackComment.vue
index 637fce73..8af24d6e 100644
--- a/frontend/src/components/submission_notes/FeedbackComment.vue
+++ b/frontend/src/components/submission_notes/FeedbackComment.vue
@@ -27,7 +27,7 @@
   }
 
   .tip-up {
-    top: -25px; /* Same as body margin top + border */
+    top: -22px; /* Same as body margin top + border */
     left: 10px;
     border-right-color: transparent;
     border-left-color: transparent;
diff --git a/frontend/src/components/submission_notes/FeedbackForm.vue b/frontend/src/components/submission_notes/FeedbackForm.vue
index a9937662..403d0015 100644
--- a/frontend/src/components/submission_notes/FeedbackForm.vue
+++ b/frontend/src/components/submission_notes/FeedbackForm.vue
@@ -3,15 +3,16 @@
     <v-text-field
       name="feedback-input"
       label="Please provide your feedback here"
-      v-model="current_feedback"
+      v-model="currentFeedback"
       @keyup.enter.ctrl.exact="submitFeedback"
       @keyup.esc="collapseTextField"
+      @focus="selectInput($event)"
       rows="2"
       textarea
       autofocus
       auto-grow
       hide-details
-    ></v-text-field>
+    />
     <v-btn color="success" @click="submitFeedback">Submit</v-btn>
     <v-btn @click="discardFeedback">Discard changes</v-btn>
   </div>
@@ -23,27 +24,31 @@
     name: 'comment-form',
     props: {
       feedback: String,
-      index: Number
+      index: String
     },
     data () {
       return {
-        current_feedback: this.feedback
+        currentFeedback: this.feedback
       }
     },
     methods: {
-
+      selectInput (event) {
+        if (event) {
+          event.target.select()
+        }
+      },
       collapseTextField () {
         this.$emit('collapseFeedbackForm')
       },
       submitFeedback () {
         this.$store.dispatch('updateFeedback', {
           lineIndex: this.index,
-          content: this.current_feedback
+          content: this.currentFeedback
         })
         this.collapseTextField()
       },
       discardFeedback () {
-        this.current_feedback = this.feedback
+        this.currentFeedback = this.feedback
       }
     }
   }
diff --git a/frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionBottomToolbar.vue b/frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionBottomToolbar.vue
new file mode 100644
index 00000000..887661e2
--- /dev/null
+++ b/frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionBottomToolbar.vue
@@ -0,0 +1,64 @@
+<template>
+  <v-toolbar dense class="bottom-toolbar">
+    <v-spacer/>
+    <v-alert
+      class="score-alert ma-3"
+      color="error"
+      icon="warning"
+      :value="scoreError"
+    >{{ scoreError }}</v-alert>
+    <span class="mr-2">Score:</span>
+    <input
+      class="score-text-field"
+      type="number"
+      v-model="score"
+      @input="validateScore"
+      @change="validateScore"
+    />
+    <v-tooltip top>
+      <v-btn color="success" slot="activator">Submit<v-icon>chevron_right</v-icon></v-btn>
+      <span>Submit and continue</span>
+    </v-tooltip>
+  </v-toolbar>
+</template>
+
+<script>
+  export default {
+    name: 'annotated-submission-bottom-toolbar',
+    data () {
+      return {
+        score: 42,
+        mockMax: 50,
+        scoreError: ''
+
+      }
+    },
+    methods: {
+      validateScore () {
+        if (this.score < 0) {
+          this.score = 0
+          this.scoreError = 'Score must be 0 or greater.'
+        } else if (this.score > this.mockMax) {
+          this.score = this.mockMax
+          this.scoreError = `Score must be less or equal to ${this.mockMax}`
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped>
+  .bottom-toolbar {
+    font-size: large;
+  }
+  .score-text-field {
+    max-width: 50px;
+    box-sizing: border-box;
+    border: 1px solid grey;
+    border-radius: 2px;
+    padding: 3px;
+  }
+  .score-alert {
+    max-height: 40px;
+  }
+</style>
diff --git a/frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionTopToolbar.vue b/frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionTopToolbar.vue
new file mode 100644
index 00000000..845c6608
--- /dev/null
+++ b/frontend/src/components/submission_notes/toolbars/AnnotatedSubmissionTopToolbar.vue
@@ -0,0 +1,44 @@
+<template>
+  <v-toolbar
+    dense>
+    <v-toolbar-side-icon @click.stop="helpDialog=true">
+        <v-icon>help_outline</v-icon>
+    </v-toolbar-side-icon>
+    <v-dialog
+      scrollable
+      max-width="fit-content"
+      v-model="helpDialog"
+    >
+      <correction-help-card></correction-help-card>
+    </v-dialog>
+    <v-spacer></v-spacer>
+    <v-tooltip top>
+      <v-btn icon slot="activator" v-clipboard="submission"><v-icon>content_copy</v-icon></v-btn>
+      <span>Copy to clipboard</span>
+    </v-tooltip>
+  </v-toolbar>
+</template>
+
+<script>
+  import CorrectionHelpCard from '@/components/submission_notes/CorrectionHelpCard'
+
+  export default {
+    components: {CorrectionHelpCard},
+    name: 'annotated-submission-top-toolbar',
+    props: {
+      submission: {
+        type: String,
+        required: true
+      }
+    },
+    data () {
+      return {
+        helpDialog: false
+      }
+    }
+  }
+</script>
+
+<style scoped>
+
+</style>
diff --git a/frontend/src/main.js b/frontend/src/main.js
index d7cf28b7..a92f0660 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -5,6 +5,7 @@ import App from './App'
 import router from './router'
 import store from './store/store'
 import Vuetify from 'vuetify'
+import Cliboard from 'v-clipboard'
 
 import 'vuetify/dist/vuetify.min.css'
 import 'material-design-icons/iconfont/material-icons.css'
@@ -12,6 +13,7 @@ import 'google-code-prettify/bin/prettify.min'
 import 'google-code-prettify/bin/prettify.min.css'
 
 Vue.use(Vuetify)
+Vue.use(Cliboard)
 
 Vue.config.productionTip = false
 
diff --git a/frontend/src/pages/Login.vue b/frontend/src/pages/Login.vue
index 8822993b..a5b5d1b4 100644
--- a/frontend/src/pages/Login.vue
+++ b/frontend/src/pages/Login.vue
@@ -19,13 +19,13 @@
                 v-model="credentials.username"
                 required
                 autofocus
-                ></v-text-field>
+              />
               <v-text-field
                 label="Password"
                 v-model="credentials.password"
                 type="password"
                 required
-                ></v-text-field>
+                />
               <v-btn :loading="loading" type="submit" color="primary">Access</v-btn>
             </v-form>
           </v-flex>
@@ -49,7 +49,8 @@
     },
     computed: {
       ...mapState([
-        'error'
+        'error',
+        'userRole'
       ])
     },
     methods: {
@@ -62,10 +63,16 @@
       submit () {
         this.loading = true
         this.getJWTToken(this.credentials).then(() => {
-          this.getUserRole()
+          this.getUserRole().then(() => {
+            switch (this.userRole) {
+              case 'Student': this.$router.push('/student')
+                break
+              case 'Tutor': this.$router.push('/tutor')
+                break
+            }
+          })
           this.getJWTTimeDelta()
           this.loading = false
-          this.$router.push('/student/')
         }).catch(() => { this.loading = false })
       }
     }
diff --git a/frontend/src/pages/SubmissionCorrectionPage.vue b/frontend/src/pages/SubmissionCorrectionPage.vue
new file mode 100644
index 00000000..386e8210
--- /dev/null
+++ b/frontend/src/pages/SubmissionCorrectionPage.vue
@@ -0,0 +1,81 @@
+<template>
+  <v-layout row wrap>
+    <v-flex xs12 md6>
+      <annotated-submission
+        :rawSubmission="mockSubmission"
+        :feedback="mockFeedback"
+        :score="mockScore"
+        :editable="true"
+        class="ma-4 autofocus"
+      />
+    </v-flex>
+
+    <v-flex md6>
+      <submission-type
+        v-bind="mockSubType"
+        :reverse="true"
+        :expandedByDefault="{ Description: false, Solution: true }"
+      />
+    </v-flex>
+  </v-layout>
+</template>
+
+<script>
+  import AnnotatedSubmission from '@/components/submission_notes/AnnotatedSubmission'
+  import SubmissionType from '@/components/SubmissionType'
+
+  export default {
+    components: {
+      SubmissionType,
+      AnnotatedSubmission},
+    name: 'submission-correction-page',
+    data () {
+      return {
+        mockSubmission: '//Procedural Programming technique shows creation of Pascal\'s Triangl\n' +
+        '#include <iostream>\n' +
+        '#include <iomanip>\n' +
+        '\n' +
+        'using namespace std;\n' +
+        '\n' +
+        '\n' +
+        'int** comb(int** a , int row , int col)\n' +
+        '{\n' +
+        '   int mid = col/2;\n' +
+        '        //clear matrix\n' +
+        '         for( int i = 0 ; i < row ; i++)\n' +
+        '         for( int j = 0 ; j < col ; j++)\n' +
+        '                a[i][j] = 0;\n' +
+        '                a[0][mid] = 1; //put 1 in the middle of first row\n' +
+        '    //build up Pascal\'s Triangle matrix\n' +
+        '     for( int i = 1 ; i < row ; i++)\n' +
+        '        {\n' +
+        '          for( int j = 1 ; j < col - 1 ; j++)\n' +
+        '               a[i][j] = a[i-1][j-1] + a[i-1][j+1];\n' +
+        '        }\n' +
+        '   return a;\n' +
+        '}\n' +
+        'void disp(int** ptr, int row, int col)\n' +
+        '{\n' +
+        '  cout << endl << endl;\n' +
+        '    for ( int i = 0 ; i < row ; i++)\n' +
+        '        {\n' +
+        '        for ( int j = 0 ; j < col ; j++)\n',
+        mockFeedback: {
+          1: 'Youre STUPID',
+          4: 'Very much so'
+        },
+        mockScore: 42,
+        mockSubType: {
+          description: 'Space suits meet with devastation! The vogon dies disconnection like an intelligent dosi.',
+          solution: 'The volume is a remarkable sinner.',
+          name: 'Seas stutter from graces like wet clouds.',
+          fullScore: 42
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped>
+
+</style>
diff --git a/frontend/src/pages/student/StudentLayout.vue b/frontend/src/pages/student/StudentLayout.vue
index 28bcabe7..c20f0943 100644
--- a/frontend/src/pages/student/StudentLayout.vue
+++ b/frontend/src/pages/student/StudentLayout.vue
@@ -19,6 +19,7 @@
       </v-list-tile>
 
       <v-divider></v-divider>
+
         <v-card color="grey lighten-2" v-if="!mini">
           <v-card-title primary-title>
             <exam-information :exam="exam"></exam-information>
diff --git a/frontend/src/pages/tutor/TutorLayout.vue b/frontend/src/pages/tutor/TutorLayout.vue
new file mode 100644
index 00000000..b5641050
--- /dev/null
+++ b/frontend/src/pages/tutor/TutorLayout.vue
@@ -0,0 +1,57 @@
+<template>
+  <base-layout @sidebarMini="mini = $event">
+
+    <template slot="header">
+      Collapse
+    </template>
+
+    <v-list dense slot="sidebar-content">
+      <v-list-tile exact v-for="(item, i) in generalNavItems" :key="i" :to="item.route">
+        <v-list-tile-action>
+          <v-icon>{{ item.icon }}</v-icon>
+        </v-list-tile-action>
+        <v-list-tile-content>
+          <v-list-tile-title>
+            {{ item.name }}
+          </v-list-tile-title>
+        </v-list-tile-content>
+      </v-list-tile>
+
+      <v-divider></v-divider>
+
+
+    </v-list>
+  </base-layout>
+</template>
+
+
+<script>
+  import BaseLayout from '@/components/BaseLayout'
+
+  export default {
+    components: {BaseLayout},
+    name: 'tutor-layout',
+    data () {
+      return {
+        generalNavItems: [
+          {
+            name: 'Overview',
+            icon: 'home',
+            route: '/tutor'
+          },
+          {
+            name: 'Progress',
+            icon: 'trending_up',
+            route: '/tutor'
+          },
+          {
+            name: 'Assignments',
+            icon: 'assignment_turned_in',
+            route: '/tutor'
+          }
+        ]
+      }
+    }
+  }
+</script>
+
diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js
index 9ff1b839..babc257c 100644
--- a/frontend/src/router/index.js
+++ b/frontend/src/router/index.js
@@ -2,9 +2,11 @@ import Vue from 'vue'
 import Router from 'vue-router'
 import store from '../store/store'
 import Login from '@/pages/Login'
+import TutorLayout from '@/pages/tutor/TutorLayout'
 import StudentPage from '@/pages/student/StudentPage'
-import StudentSubmissionPage from '@/pages/student/StudentSubmissionPage'
 import StudentLayout from '@/pages/student/StudentLayout'
+import StudentSubmissionPage from '@/pages/student/StudentSubmissionPage'
+import SubmissionCorrectionPage from '@/pages/SubmissionCorrectionPage'
 import ReviewerPage from '@/pages/reviewer/ReviewerPage'
 import StudentListOverview from '@/pages/reviewer/StudentListOverview'
 
@@ -30,7 +32,16 @@ const router = new Router({
           component: StudentSubmissionPage
         }
       ]
-
+    },
+    {
+      path: '/tutor/',
+      component: TutorLayout,
+      children: [
+        {
+          path: 'assignment/',
+          component: SubmissionCorrectionPage
+        }
+      ]
     },
     {
       path: '/reviewer/',
diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js
index 0eb0f5fb..5b60e770 100644
--- a/frontend/src/store/store.js
+++ b/frontend/src/store/store.js
@@ -23,6 +23,15 @@ const store = new Vuex.Store({
   getters: {
     gradySpeak: () => {
       return gradySays[Math.floor(Math.random() * gradySays.length)]
+    },
+    isStudent: state => {
+      return state.userRole === 'Student'
+    },
+    isTutor: state => {
+      return state.userRole === 'Tutor'
+    },
+    isReviewer: state => {
+      return state.userRole === 'Reviewer'
     }
   },
   mutations: {
@@ -81,8 +90,9 @@ const store = new Vuex.Store({
         context.commit('SET_JWT_TIME_DELTA', response.data.timeDelta)
       })
     },
-    getUserRole (context) {
-      ax.get('api/user-role/').then(response => context.commit('SET_USER_ROLE', response.data.role))
+    async getUserRole (context) {
+      const response = await ax.get('api/user-role/')
+      context.commit('SET_USER_ROLE', response.data.role)
     },
     logout (store) {
       store.commit('LOGOUT')
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 1e43569c..1098822b 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -5782,6 +5782,10 @@ uuid@^3.0.0, uuid@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
 
+v-clipboard@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/v-clipboard/-/v-clipboard-1.0.4.tgz#ffd423484c61b81685d7ea23f2abd2c0e25a7de0"
+
 validate-npm-package-license@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
-- 
GitLab