Refactor: layout
This commit is contained in:
@@ -52,7 +52,7 @@ import { collection, doc, addDoc, writeBatch } from 'firebase/firestore'
|
|||||||
// https://vee-validate.logaretm.com/v3/guide/basics.html
|
// https://vee-validate.logaretm.com/v3/guide/basics.html
|
||||||
import { ValidationProvider, ValidationObserver, extend } from 'vee-validate'
|
import { ValidationProvider, ValidationObserver, extend } from 'vee-validate'
|
||||||
import { required } from 'vee-validate/dist/rules'
|
import { required } from 'vee-validate/dist/rules'
|
||||||
import { ClosedEndedQuestion, ClosedEndedQuestionConverter } from '~/plugins/closed-ended-question'
|
import { ClosedEndedQuestion, ClosedEndedQuestionConverter, states } from '~/plugins/closed-ended-question'
|
||||||
|
|
||||||
// Override the default error message of required fields
|
// Override the default error message of required fields
|
||||||
extend('required', {
|
extend('required', {
|
||||||
@@ -75,6 +75,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
isAuthorized () {
|
||||||
|
const isTutor = this.$auth.currentUser.email.endsWith('@iu.org')
|
||||||
|
const isAdmin = this.$store.getters.isAdmin
|
||||||
|
return isTutor || isAdmin
|
||||||
|
},
|
||||||
submit () {
|
submit () {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
@@ -86,14 +91,17 @@ export default {
|
|||||||
this.$auth.currentUser.uid, // Ref: https://firebase.google.com/docs/reference/js/v8/firebase.User
|
this.$auth.currentUser.uid, // Ref: https://firebase.google.com/docs/reference/js/v8/firebase.User
|
||||||
Date.now() / 1000, // Current UNIX timestamp in seconds
|
Date.now() / 1000, // Current UNIX timestamp in seconds
|
||||||
this.comment ? [this.comment] : [],
|
this.comment ? [this.comment] : [],
|
||||||
'neu'
|
this.isAuthorized() ? states.approved : states.new
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add a new document with a generated id
|
// Add a new document with a generated id
|
||||||
addDoc(collection(this.$db, `kurse/${this.$store.state.selectedCourse}/fragenGeschlossen`).withConverter(ClosedEndedQuestionConverter), q)
|
addDoc(collection(this.$db, `kurse/${this.$store.state.selectedCourse}/fragenGeschlossen`).withConverter(ClosedEndedQuestionConverter), q)
|
||||||
.then((docRef) => {
|
.then((docRef) => {
|
||||||
// Successfully added new question to database
|
// Successfully added new question to database
|
||||||
this.$toast({ content: 'Deine Frage wurde eingereicht!', color: 'success' })
|
const content = this.isAuthorized()
|
||||||
|
? 'Die Frage wurde hinzugefügt!'
|
||||||
|
: 'Deine Frage wurde eingereicht und wartet auf Bestätigung durch den Tutor!'
|
||||||
|
this.$toast({ content, color: 'success' })
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
// Failed to add question to database; display error message
|
// Failed to add question to database; display error message
|
||||||
@@ -131,7 +139,7 @@ export default {
|
|||||||
this.$auth.currentUser.uid, // Ref: https://firebase.google.com/docs/reference/js/v8/firebase.User
|
this.$auth.currentUser.uid, // Ref: https://firebase.google.com/docs/reference/js/v8/firebase.User
|
||||||
Date.now() / 1000, // Current UNIX timestamp in seconds
|
Date.now() / 1000, // Current UNIX timestamp in seconds
|
||||||
[],
|
[],
|
||||||
'genehmigt'
|
states.approved
|
||||||
)
|
)
|
||||||
|
|
||||||
const questionRef = doc(collection(this.$db, `kurse/${this.$store.state.selectedCourse}/fragenGeschlossen`).withConverter(ClosedEndedQuestionConverter))
|
const questionRef = doc(collection(this.$db, `kurse/${this.$store.state.selectedCourse}/fragenGeschlossen`).withConverter(ClosedEndedQuestionConverter))
|
||||||
|
|||||||
35
components/Challenge.vue
Normal file
35
components/Challenge.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<v-container fluid>
|
||||||
|
<v-subheader class="text-h5 text--primary">Challenge</v-subheader>
|
||||||
|
<v-divider></v-divider>
|
||||||
|
<v-btn depressed color="success" class="my-3" @click="playVersus">
|
||||||
|
<v-icon left>mdi-play</v-icon>
|
||||||
|
Quiz Spielen
|
||||||
|
</v-btn>
|
||||||
|
<AddClosedEndedQuestion />
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ChallengeComponent',
|
||||||
|
props: {
|
||||||
|
courseId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
playVersus () {
|
||||||
|
// TODO
|
||||||
|
this.$router.push(`${this.$route.path}/play`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-expansion-panels>
|
<v-container fluid>
|
||||||
|
<v-subheader class="text-h5 text--primary">Offene Fragen</v-subheader>
|
||||||
|
<v-divider></v-divider>
|
||||||
|
<v-expansion-panels focusable class="my-3">
|
||||||
<v-expansion-panel
|
<v-expansion-panel
|
||||||
v-for="(item, i) in questions"
|
v-for="(item, i) in questions"
|
||||||
:key="i"
|
:key="i"
|
||||||
@@ -12,6 +15,8 @@
|
|||||||
</v-expansion-panel-content>
|
</v-expansion-panel-content>
|
||||||
</v-expansion-panel>
|
</v-expansion-panel>
|
||||||
</v-expansion-panels>
|
</v-expansion-panels>
|
||||||
|
<AddOpenEndedQuestion />
|
||||||
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -21,7 +26,7 @@ import { OpenEndedQuestionConverter } from '~/plugins/open-ended-question'
|
|||||||
export default {
|
export default {
|
||||||
name: 'CoopComponent',
|
name: 'CoopComponent',
|
||||||
props: {
|
props: {
|
||||||
courseID: {
|
courseId: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
@@ -37,7 +42,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
getQuestions () {
|
getQuestions () {
|
||||||
// Create a reference to the open-ended questions collection of the currently selected course
|
// Create a reference to the open-ended questions collection of the currently selected course
|
||||||
const questionsRef = collection(this.$db, `kurse/${this.courseID}/fragenOffen`).withConverter(OpenEndedQuestionConverter)
|
const questionsRef = collection(this.$db, `kurse/${this.courseId}/fragenOffen`).withConverter(OpenEndedQuestionConverter)
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
getDocs(questionsRef).then((querySnapshot) => {
|
getDocs(questionsRef).then((querySnapshot) => {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog v-model="show" width="500">
|
<v-dialog v-model="show" width="500">
|
||||||
<template #activator="{ on, attrs }">
|
<template #activator="{ on, attrs }">
|
||||||
<v-btn fixed top left dark color="red lighten-2" v-bind="attrs" v-on="on">
|
<v-btn fixed top dark color="red lighten-2" :style="{left: '50%', transform:'translateX(-50%)'}" v-bind="attrs" v-on="on">
|
||||||
<v-icon left>mdi-alert-circle-outline</v-icon>
|
<v-icon left>mdi-alert-circle-outline</v-icon>
|
||||||
Demo-Account Info
|
Mit Demo-Account Anmelden
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-card elevation="12" class="mx-auto">
|
<v-card elevation="12" class="mx-auto">
|
||||||
@@ -44,7 +44,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { signInWithEmailAndPassword } from 'firebase/auth'
|
import { signInWithEmailAndPassword } from 'firebase/auth'
|
||||||
export const demoAccounts = ['max.muster.test@iubh-fernstudium.de', 'tutor.test@iu.org', 'admin.test@iu.org']
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container fluid fill-height>
|
<v-container fluid fill-height>
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<span class="text-h4">{{ title }}</span>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
<NuxtChild />
|
<NuxtChild />
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
@@ -16,20 +11,8 @@ export default {
|
|||||||
courseID: undefined
|
courseID: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
title () {
|
|
||||||
const courseName = this.$store.getters.getCourseByID(this.courseID).name
|
|
||||||
return `${this.courseID.toUpperCase()} - ${courseName}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
created () {
|
||||||
this.courseID = this.$route.params.course
|
this.courseID = this.$route.params.course
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.tete {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,20 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<v-container fluid class="pa-0">
|
||||||
|
<v-sheet class="rounded-lg pa-2">
|
||||||
|
<span class="text-h4 text--secondary">{{ courseID.toUpperCase() }}</span>
|
||||||
|
<span class="text-h4">{{ $store.getters.getCourseByID(courseID).name }}</span>
|
||||||
|
</v-sheet>
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="auto">
|
<v-col v-if="isAuthorized" cols="12">
|
||||||
<v-btn depressed color="primary" @click="playVersus">Challenge Mode</v-btn>
|
<TutorPanel :course-id="courseID" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<Coop :courseID="courseID" />
|
<Challenge :course-id="courseID" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<AddClosedEndedQuestion />
|
<Coop :course-id="courseID" />
|
||||||
</v-col>
|
|
||||||
<v-col cols="12">
|
|
||||||
<AddOpenEndedQuestion />
|
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -26,15 +29,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isAuthorized () {
|
||||||
|
const isTutor = this.$auth.currentUser.email.endsWith('@iu.org')
|
||||||
|
const isAdmin = this.$store.getters.isAdmin
|
||||||
|
return isTutor || isAdmin
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.courseID = this.$route.params.course
|
this.courseID = this.$route.params.course
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
playVersus () {
|
|
||||||
// TODO
|
|
||||||
this.$router.push(`${this.$route.path}/play`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import {
|
|||||||
import _sampleSize from 'lodash-es/sampleSize'
|
import _sampleSize from 'lodash-es/sampleSize'
|
||||||
import _shuffle from 'lodash-es/shuffle'
|
import _shuffle from 'lodash-es/shuffle'
|
||||||
import _capitalize from 'lodash-es/capitalize'
|
import _capitalize from 'lodash-es/capitalize'
|
||||||
import { ClosedEndedQuestionConverter } from '~/plugins/closed-ended-question'
|
import { ClosedEndedQuestionConverter, states } from '~/plugins/closed-ended-question'
|
||||||
import { Game, GameConverter } from '~/plugins/game'
|
import { Game, GameConverter } from '~/plugins/game'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -101,7 +101,7 @@ export default {
|
|||||||
|
|
||||||
// Create a query against the collection.
|
// Create a query against the collection.
|
||||||
// Only questions with the status "approved" (=genehmigt) should be fetched from the database
|
// Only questions with the status "approved" (=genehmigt) should be fetched from the database
|
||||||
const q = query(questionsRef, where('status', '==', 'genehmigt'))
|
const q = query(questionsRef, where('status', '==', states.approved))
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
return getDocs(q).then((querySnapshot) => {
|
return getDocs(q).then((querySnapshot) => {
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ export class ClosedEndedQuestion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const states = {
|
||||||
|
new: 'neu',
|
||||||
|
approved: 'genehmigt',
|
||||||
|
declined: 'abgelehnt'
|
||||||
|
}
|
||||||
|
|
||||||
// Firestore data converter
|
// Firestore data converter
|
||||||
export const ClosedEndedQuestionConverter = {
|
export const ClosedEndedQuestionConverter = {
|
||||||
toFirestore: (closedEndedQuestion) => {
|
toFirestore: (closedEndedQuestion) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user