Skip to content

Commit 74a6c97

Browse files
submit exercise layout
1 parent 0f1407e commit 74a6c97

File tree

6 files changed

+190
-4
lines changed

6 files changed

+190
-4
lines changed

src/interfaces/classroom.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@ export declare interface ReadingSubmissionResult {
1919
is_correct: boolean;
2020
}
2121

22+
declare interface _ReadingExercise {
23+
pk: number;
24+
url: string;
25+
identifier: string;
26+
}
27+
2228
export declare interface ReadingExerciseReport {
23-
exercise: string;
29+
exercise: _ReadingExercise;
2430
passage_1_total: number;
2531
passage_2_total: number;
2632
passage_3_total: number;

src/interfaces/reading-question.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,15 @@ export declare interface ReadingQuestion {
88
choices: string[];
99
answers: string[];
1010
}
11+
12+
declare interface _AnswerChoice {
13+
text: string;
14+
value: string;
15+
}
16+
17+
export declare interface ReadingAnswer {
18+
question_number: ReadingQuestion['number'];
19+
content: string;
20+
question_type?: ReadingQuestion['question_type'];
21+
choices?: _AnswerChoice[];
22+
}

src/router/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import ReadingExerciseDetail from '../views/reading-exercise/ReadingExerciseDeta
2121
import ReadingExerciseCreate from '../views/reading-exercise/ReadingExerciseCreate.vue'
2222
import ReadingExerciseUpdate from '../views/reading-exercise/ReadingExerciseUpdate.vue'
2323
import ReadingExerciseEditAnswers from '../views/reading-exercise/ReadingExerciseEditAnswers.vue'
24+
import ReadingExerciseSubmit from '../views/reading-exercise/ReadingExerciseSubmit.vue'
2425

2526
import { castToNumber, prefixWith } from './utils'
2627

@@ -115,6 +116,12 @@ const routes: Array<RouteConfig> = [
115116
component: ReadingExerciseEditAnswers,
116117
props: castToNumber('pk')
117118
},
119+
{
120+
path: '/:pk/submit',
121+
name: 'ReadingExerciseSubmit',
122+
component: ReadingExerciseSubmit,
123+
props: castToNumber('pk')
124+
},
118125
{
119126
path: '/:pk',
120127
name: 'ReadingExerciseDetail',

src/utils/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export function snakeCaseToCamelCase (text: string): string {
2323
return words.join('')
2424
}
2525

26-
export function toTitleCase (text: string, separator?: string): string {
26+
export function toTitleCase (text: string | undefined, separator?: string): string {
27+
if (text === undefined) return ''
2728
if (separator === undefined) separator = ' '
2829
let words = text.split(separator)
2930
words = words.map(word => {

src/views/classroom/ClassroomExercisesReadingStudent.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,20 @@
2828
v-for="report of reports"
2929
:key="report.pk"
3030
>
31-
<td>{{ report.exercise }}</td>
31+
<td>{{ report.exercise.identifier }}</td>
3232
<template v-if="!report.submitted">
3333
<td colspan="5">
3434
Not submitted
3535
</td>
3636
<td class="text-center">
37-
Start
37+
<router-link
38+
:to="{
39+
name: 'ReadingExerciseSubmit',
40+
params: { pk: report.exercise.pk }
41+
}"
42+
>
43+
Start
44+
</router-link>
3845
</td>
3946
</template>
4047
<template v-else>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<template>
2+
<v-container>
3+
<v-progress-circular
4+
v-if="loading"
5+
indeterminate
6+
color="primary"
7+
></v-progress-circular>
8+
9+
<div v-else>
10+
<h1>{{ exercise.identifier }}</h1>
11+
<v-divider></v-divider>
12+
13+
<v-row class="mt-0">
14+
<v-col cols="6" class="exercise-col">
15+
<div v-html="exercise.content"></div>
16+
</v-col>
17+
<v-col cols="6" class="exercise-col">
18+
<p class="mb-0">Your answers</p>
19+
<v-row>
20+
<v-col
21+
v-for="(answers, index) of [answersCol1, answersCol2]"
22+
:key="index"
23+
cols="6"
24+
>
25+
<v-simple-table>
26+
<tbody>
27+
<tr
28+
v-for="answer of answers"
29+
:key="answer.question_number"
30+
>
31+
<th>{{ answer.question_number }}</th>
32+
<td>
33+
<v-select
34+
v-if="answer.question_type !== 'fill_blank'"
35+
v-model="answer.content"
36+
:items="answer.choices"
37+
hide-details
38+
></v-select>
39+
<v-text-field
40+
v-else
41+
v-model="answer.content"
42+
hide-details
43+
></v-text-field>
44+
</td>
45+
</tr>
46+
</tbody>
47+
</v-simple-table>
48+
</v-col>
49+
</v-row>
50+
</v-col>
51+
</v-row>
52+
</div>
53+
</v-container>
54+
</template>
55+
56+
<script lang="ts">
57+
import { ReadingExercise } from '@/interfaces/reading-exercise'
58+
import { ReadingAnswer, ReadingQuestion } from '@/interfaces/reading-question'
59+
import { unexpectedExc } from '@/utils'
60+
import { Vue, Component, Prop } from 'vue-property-decorator'
61+
import { mapState } from 'vuex'
62+
63+
@Component({
64+
computed: {
65+
...mapState('readingExercise', {
66+
exercise: 'currentReadingExercise'
67+
}),
68+
...mapState('readingExercise', {
69+
questions: 'currentQuestions'
70+
})
71+
}
72+
})
73+
export default class ReadingExerciseSubmit extends Vue {
74+
@Prop(Number) readonly pk!: number
75+
76+
async created (): Promise<void> {
77+
await this.setQuestions()
78+
this.setAnswers()
79+
}
80+
81+
/**
82+
* Questions
83+
*/
84+
exercise!: ReadingExercise
85+
questions!: ReadingQuestion[]
86+
loading = false
87+
88+
async setQuestions (): Promise<void> {
89+
this.loading = true
90+
91+
try {
92+
await this.$store.dispatch('readingExercise/detail', this.pk)
93+
await this.$store.dispatch('readingExercise/getQuestions')
94+
} catch (error) {
95+
unexpectedExc(error)
96+
} finally {
97+
this.loading = false
98+
}
99+
}
100+
101+
/**
102+
* Answers
103+
*/
104+
answers: ReadingAnswer[] = []
105+
106+
setAnswers (): void {
107+
this.answers = this.questions.map(question => {
108+
let choices: ReadingAnswer['choices'] = []
109+
110+
if (question.question_type === 'true_false') {
111+
choices = [
112+
{ text: 'TRUE', value: 'TRUE' },
113+
{ text: 'FALSE', value: 'FALSE' },
114+
{ text: 'NOT GIVEN', value: 'NOT_GIVEN' }
115+
]
116+
} else if (question.question_type === 'yes_no') {
117+
choices = [
118+
{ text: 'YES', value: 'YES' },
119+
{ text: 'NO', value: 'NO' },
120+
{ text: 'NOT GIVEN', value: 'NOT_GIVEN' }
121+
]
122+
} else {
123+
choices = question.choices.map(choice => (
124+
{ text: choice, value: choice }
125+
))
126+
}
127+
128+
return {
129+
question_number: question.number,
130+
content: '',
131+
question_type: question.question_type,
132+
choices
133+
}
134+
})
135+
}
136+
137+
get answersCol1 (): ReadingAnswer[] {
138+
return this.answers.filter(answer => answer.question_number <= 20)
139+
}
140+
141+
get answersCol2 (): ReadingAnswer[] {
142+
return this.answers.filter(answer => answer.question_number > 20)
143+
}
144+
}
145+
</script>
146+
147+
<style scoped lang="scss">
148+
.exercise-col {
149+
height: 80vh;
150+
overflow-y: auto;
151+
overflow-x: hidden;
152+
}
153+
</style>

0 commit comments

Comments
 (0)