Skip to content
Snippets Groups Projects
Commit 05bda8ee authored by robinwilliam.hundt's avatar robinwilliam.hundt
Browse files

fixed #121 and made small changes to studentPage

Solution is no longer displayed on student page because it may contain grading information which has been changed during the grading process and would thus confuse the student
parent 4991cd34
Branches
Tags
1 merge request!120Bug fixes
Pipeline #325264 passed
Showing
with 65 additions and 59 deletions
...@@ -17,8 +17,14 @@ class SubmissionNoTextFieldsSerializer(DynamicFieldsModelSerializer): ...@@ -17,8 +17,14 @@ class SubmissionNoTextFieldsSerializer(DynamicFieldsModelSerializer):
fields = ('pk', 'type', 'score', 'final', 'full_score') fields = ('pk', 'type', 'score', 'final', 'full_score')
class SubmissionSerializer(DynamicFieldsModelSerializer): class StudentSubmissionSerializer(DynamicFieldsModelSerializer):
type = SubmissionTypeSerializer() type = SubmissionTypeSerializer(
# exclude solution from Type information
fields=(('pk',
'name',
'full_score',
'description',
'programming_language')))
feedback = VisibleCommentFeedbackSerializer() feedback = VisibleCommentFeedbackSerializer()
tests = TestSerializer(many=True) tests = TestSerializer(many=True)
......
...@@ -209,10 +209,8 @@ class StudentSelfSubmissionsTests(APITestCase): ...@@ -209,10 +209,8 @@ class StudentSelfSubmissionsTests(APITestCase):
self.submission_list_first_entry['type']['description'], self.submission_list_first_entry['type']['description'],
self.student_info.submissions.first().type.description) self.student_info.submissions.first().type.description)
def test_submission_data_contains_solution(self): def test_submission_data_not_contains_solution(self):
self.assertEqual( self.assertNotIn('solution', self.submission_list_first_entry['type'])
self.submission_list_first_entry['type']['solution'],
self.student_info.submissions.first().type.solution)
def test_submission_data_contains_final_status(self): def test_submission_data_contains_final_status(self):
self.assertEqual( self.assertEqual(
......
...@@ -22,7 +22,7 @@ from core.models import ExamType, StudentInfo, SubmissionType ...@@ -22,7 +22,7 @@ from core.models import ExamType, StudentInfo, SubmissionType
from core.permissions import IsReviewer, IsStudent, IsTutorOrReviewer from core.permissions import IsReviewer, IsStudent, IsTutorOrReviewer
from core.serializers import (ExamSerializer, StudentInfoSerializer, from core.serializers import (ExamSerializer, StudentInfoSerializer,
StudentInfoForListViewSerializer, StudentInfoForListViewSerializer,
SubmissionNoTypeSerializer, SubmissionSerializer, SubmissionNoTypeSerializer, StudentSubmissionSerializer,
SubmissionTypeSerializer, TutorSerializer, SubmissionTypeSerializer, TutorSerializer,
UserAccountSerializer) UserAccountSerializer)
...@@ -54,7 +54,7 @@ class StudentSelfApiView(generics.RetrieveAPIView): ...@@ -54,7 +54,7 @@ class StudentSelfApiView(generics.RetrieveAPIView):
class StudentSelfSubmissionsApiView(generics.ListAPIView): class StudentSelfSubmissionsApiView(generics.ListAPIView):
permission_classes = (IsStudent, ) permission_classes = (IsStudent, )
serializer_class = SubmissionSerializer serializer_class = StudentSubmissionSerializer
def get_queryset(self): def get_queryset(self):
return self.request.user.student.submissions return self.request.user.student.submissions
......
...@@ -68,7 +68,7 @@ export async function fetchAllStudents (): Promise<Array<StudentInfoForListView> ...@@ -68,7 +68,7 @@ export async function fetchAllStudents (): Promise<Array<StudentInfoForListView>
return (await ax.get(url)).data return (await ax.get(url)).data
} }
export async function fetchStudent ({pk, }: export async function fetchStudent ({pk}:
{pk: string}): Promise<StudentInfoForListView> { {pk: string}): Promise<StudentInfoForListView> {
const url = `/api/student/${pk}/` const url = `/api/student/${pk}/`
return (await ax.get(url)).data return (await ax.get(url)).data
......
...@@ -18,12 +18,12 @@ ...@@ -18,12 +18,12 @@
></span> ></span>
</v-card-text> </v-card-text>
</v-card> </v-card>
<v-flex v-else-if="item.title === 'Solution'"> <div v-else-if="item.title === 'Solution'">
<pre <pre
class="elevation-2 solution-code pl-2" class="elevation-2 solution-code pl-2"
:class="programmingLanguage" :class="programmingLanguage"
><span v-html="highlightedSolution"></span></pre> ><span v-html="highlightedSolution"></span></pre>
</v-flex> </div>
</v-expansion-panel-content> </v-expansion-panel-content>
</v-expansion-panel> </v-expansion-panel>
</v-card> </v-card>
...@@ -47,7 +47,8 @@ export default class SubmissionType extends Vue { ...@@ -47,7 +47,8 @@ export default class SubmissionType extends Vue {
}) description!: string }) description!: string
@Prop({ @Prop({
type: String, type: String,
required: true required: false,
default: ''
}) solution!: string }) solution!: string
@Prop({ @Prop({
type: Number, type: Number,
...@@ -80,12 +81,14 @@ export default class SubmissionType extends Vue { ...@@ -80,12 +81,14 @@ export default class SubmissionType extends Vue {
{ {
title: 'Description', title: 'Description',
text: this.description text: this.description
},
{
title: 'Solution',
text: this.solution
} }
] ]
if (this.solution) {
items.push({
title: 'Solution',
text: this.solution
})
}
if (this.reverse) { if (this.reverse) {
return items.reverse() return items.reverse()
} else { } else {
......
<template> <template>
<table class="table table-info rounded"> <table class="table table-info rounded exam-table">
<tbody> <tbody v-if="!exam">
No exam information present
</tbody>
<tbody v-else>
<tr> <tr>
<th>Module</th> <th>Module</th>
<td>{{ exam.moduleReference }}</td> <td>{{ exam.moduleReference }}</td>
...@@ -29,3 +32,9 @@ export default class ExamInformation extends Vue { ...@@ -29,3 +32,9 @@ export default class ExamInformation extends Vue {
@Prop(Object) exam!: Exam @Prop(Object) exam!: Exam
} }
</script> </script>
<style>
.exam-table {
width: 100%
}
</style>
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
hide-actions hide-actions
:headers="headers" :headers="headers"
:items="submissions" :items="submissions"
item-key="type" item-key="type.pk"
> >
<template slot="items" slot-scope="props"> <template slot="items" slot-scope="props">
<td>{{ props.item.type.name }}</td> <td>{{ props.item.type.name }}</td>
...@@ -32,7 +32,7 @@ export default { ...@@ -32,7 +32,7 @@ export default {
{ {
text: 'Task', text: 'Task',
align: 'left', align: 'left',
value: 'type', value: 'type.name',
sortable: false sortable: false
}, },
{ {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<script> <script>
import {activateAllStudentAccess, import {activateAllStudentAccess,
deactivateAllStudentAccess} from '@/api' deactivateAllStudentAccess} from '@/api'
import { actions } from '@/store/actions'; import { actions } from '@/store/actions'
export default { export default {
name: 'student-list-menu', name: 'student-list-menu',
......
...@@ -503,7 +503,7 @@ export interface SubmissionType { ...@@ -503,7 +503,7 @@ export interface SubmissionType {
* @type {string} * @type {string}
* @memberof SubmissionType * @memberof SubmissionType
*/ */
solution: string solution?: string
/** /**
* *
* @type {string} * @type {string}
......
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
route: '/home' route: '/home'
}, },
{ {
name: 'Feedback', name: 'Feedback History',
icon: 'feedback', icon: 'feedback',
route: '/feedback' route: '/feedback'
} }
......
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
<v-divider></v-divider> <v-divider></v-divider>
<exam-information <exam-information
:exam="exam" :exam="exam"
v-if="!mini" v-if="!mini"
class="elevation-1 exam-info ma-1" class="elevation-1 exam-info ma-1"
/> />
<v-list-tile exact v-for="item in submissionNavItems" :key="item.route" :to="item.route"> <v-list-tile exact v-for="item in submissionNavItems" :key="item.route" :to="item.route">
<v-list-tile-action> <v-list-tile-action>
<v-icon v-if="!visited[item.id]">assignment</v-icon> <v-icon v-if="!visited[item.id]">assignment</v-icon>
...@@ -60,10 +60,10 @@ export default { ...@@ -60,10 +60,10 @@ export default {
} }
}, },
computed: { computed: {
moduleReference () { return StudentPage.state.exam.moduleReference },
submissions () { return StudentPage.state.submissionsForList }, submissions () { return StudentPage.state.submissionsForList },
exam () { return StudentPage.state.exam }, exam () { return StudentPage.state.exam },
visited () { return StudentPage.state.visited }, visited () { return StudentPage.state.visited },
moduleReference () { return this.exam ? this.exam.moduleReference : 'No exam information' },
mini () { return UI.state.mini }, mini () { return UI.state.mini },
......
...@@ -12,17 +12,13 @@ ...@@ -12,17 +12,13 @@
</template> </template>
<script> <script>
import {mapState} from 'vuex'
import StudentLayout from './StudentLayout.vue'
import SubmissionList from '@/components/student/SubmissionList.vue' import SubmissionList from '@/components/student/SubmissionList.vue'
import ExamInformation from '@/components/student/ExamInformation.vue'
import { StudentPage } from '@/store/modules/student-page' import { StudentPage } from '@/store/modules/student-page'
export default { export default {
components: { components: {
ExamInformation, SubmissionList
SubmissionList, },
StudentLayout},
name: 'student-page', name: 'student-page',
created: function () { created: function () {
if (!this.loaded) { if (!this.loaded) {
...@@ -33,7 +29,6 @@ export default { ...@@ -33,7 +29,6 @@ export default {
}, },
computed: { computed: {
studentName () { return StudentPage.state.studentName }, studentName () { return StudentPage.state.studentName },
exam () { return StudentPage.state.exam },
submissions () { return StudentPage.state.submissionsForList }, submissions () { return StudentPage.state.submissionsForList },
loaded () { return StudentPage.state.loaded } loaded () { return StudentPage.state.loaded }
} }
......
...@@ -88,8 +88,7 @@ export default { ...@@ -88,8 +88,7 @@ export default {
methods: { methods: {
onRouteMountOrUpdate (routeId) { onRouteMountOrUpdate (routeId) {
StudentPage.SET_VISITED({ index: routeId, visited: true }) StudentPage.SET_VISITED({ index: routeId, visited: true })
// TODO this seems fishy and there probably is the student page bug in here SubmissionNotes.SET_SUBMISSION(StudentPage.state.submissionData[routeId])
SubmissionNotes.SET_SUBMISSION(this.$store.state.studentPage.submissionData[this.id])
} }
}, },
mounted () { mounted () {
......
...@@ -10,19 +10,19 @@ import { RootState } from '@/store/store' ...@@ -10,19 +10,19 @@ import { RootState } from '@/store/store'
import { FeedbackTable } from '@/store/modules/feedback_list/feedback-table' import { FeedbackTable } from '@/store/modules/feedback_list/feedback-table'
import { Subscriptions } from '@/store/modules/subscriptions' import { Subscriptions } from '@/store/modules/subscriptions'
async function getExamTypes(context: BareActionContext<RootState, RootState>) { async function getExamTypes (context: BareActionContext<RootState, RootState>) {
const examTypes = await api.fetchExamTypes({}) const examTypes = await api.fetchExamTypes()
mut.SET_EXAM_TYPES(examTypes) mut.SET_EXAM_TYPES(examTypes)
} }
async function updateSubmissionTypes( async function updateSubmissionTypes (
context: BareActionContext<RootState, RootState>, context: BareActionContext<RootState, RootState>
) { ) {
const submissionTypes = await api.fetchSubmissionTypes() const submissionTypes = await api.fetchSubmissionTypes()
submissionTypes.forEach(type => { submissionTypes.forEach(type => {
mut.UPDATE_SUBMISSION_TYPE(type) mut.UPDATE_SUBMISSION_TYPE(type)
}) })
} }
async function getStudents( async function getStudents (
context: BareActionContext<RootState, RootState>, context: BareActionContext<RootState, RootState>,
opt: { studentPks: Array<string>} = { opt: { studentPks: Array<string>} = {
studentPks: [] studentPks: []
...@@ -42,11 +42,11 @@ async function getStudents( ...@@ -42,11 +42,11 @@ async function getStudents(
return students return students
} }
} }
async function getTutors() { async function getTutors () {
const tutors = await api.fetchAllTutors() const tutors = await api.fetchAllTutors()
mut.SET_TUTORS(tutors) mut.SET_TUTORS(tutors)
} }
async function getFeedback( async function getFeedback (
context: BareActionContext<RootState, RootState>, context: BareActionContext<RootState, RootState>,
fetchFeedbackArg: { ofSubmission: string } fetchFeedbackArg: { ofSubmission: string }
) { ) {
...@@ -54,38 +54,34 @@ async function getFeedback( ...@@ -54,38 +54,34 @@ async function getFeedback(
mut.SET_FEEDBACK(feedback) mut.SET_FEEDBACK(feedback)
return feedback return feedback
} }
async function getSubmissionFeedbackTest( async function getSubmissionFeedbackTest (
context: BareActionContext<RootState, RootState>, context: BareActionContext<RootState, RootState>,
submissionPkObj: { pk: string } submissionPkObj: { pk: string }
) { ) {
const submission = await api.fetchSubmissionFeedbackTests(submissionPkObj) const submission = await api.fetchSubmissionFeedbackTests(submissionPkObj)
mut.SET_SUBMISSION(submission) mut.SET_SUBMISSION(submission)
} }
async function getStatistics() { async function getStatistics () {
const statistics = await api.fetchStatistics() const statistics = await api.fetchStatistics()
mut.SET_STATISTICS(statistics) mut.SET_STATISTICS(statistics)
} }
function logout( function logout (
context: BareActionContext<RootState, RootState>, context: BareActionContext<RootState, RootState>,
message = "" message = ''
) { ) {
// logout actually receives a normal ActionContext, but for some reason vuex-typex mandates a BareActionContext
// TODO there has to be a better way
const { commit, getters, state } = <ActionContext<RootState, RootState>>(
context
)
if (Authentication.isStudent) { if (Authentication.isStudent) {
// change active to false when user logs out // change active to false when user logs out
// TODO this should belong in auth module // TODO this should belong in auth module
api.changeActiveForUser(Authentication.state.user.pk, false) api.changeActiveForUser(Authentication.state.user.pk, false)
} }
router.push({ name: 'login' })
// there should be a better way to solve the issue of resetting the once() function used in subscription module
mut.RESET_STATE() mut.RESET_STATE()
FeedbackTable.RESET_STATE() FeedbackTable.RESET_STATE()
Authentication.RESET_STATE() Authentication.RESET_STATE()
Subscriptions.RESET_STATE() Subscriptions.RESET_STATE()
SubmissionNotes.RESET_STATE() SubmissionNotes.RESET_STATE()
Authentication.SET_MESSAGE(message) Authentication.SET_MESSAGE(message)
router.push({ name: "login" })
router.go(0) router.go(0)
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment