feat [WIP]: Added multiple choice question component
This commit is contained in:
@@ -14,20 +14,20 @@ class Question(Document):
|
|||||||
self.check_minimum_one_correct_answer()
|
self.check_minimum_one_correct_answer()
|
||||||
|
|
||||||
def check_at_least_one_option(self):
|
def check_at_least_one_option(self):
|
||||||
if len(self.get_all_children()) <= 1:
|
if len(self.options) <= 1:
|
||||||
frappe.throw(_("A question must have more than one options"))
|
frappe.throw(_("A question must have more than one options"))
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def check_minimum_one_correct_answer(self):
|
def check_minimum_one_correct_answer(self):
|
||||||
correct_options = [question.is_correct for question in self.get_all_children()]
|
correct_options = [option.is_correct for option in self.options]
|
||||||
if bool(sum(correct_options)):
|
if bool(sum(correct_options)):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("A qustion must have at least one correct options"))
|
frappe.throw(_("A qustion must have at least one correct options"))
|
||||||
|
|
||||||
def get_answer(self):
|
def get_answer(self):
|
||||||
options = self.get_all_children()
|
options = self.options
|
||||||
answers = [item.name for item in options if item.is_correct == True]
|
answers = [item.name for item in options if item.is_correct == True]
|
||||||
if len(answers) == 0:
|
if len(answers) == 0:
|
||||||
frappe.throw("No correct answer is set for {0}".format(self.name))
|
frappe.throw("No correct answer is set for {0}".format(self.name))
|
||||||
|
|||||||
@@ -40,7 +40,13 @@ class Quiz(Document):
|
|||||||
def get_questions(self):
|
def get_questions(self):
|
||||||
quiz_question = self.get_all_children()
|
quiz_question = self.get_all_children()
|
||||||
if quiz_question:
|
if quiz_question:
|
||||||
questions = [frappe.get_doc('Question', question.question_link) for question in quiz_question]
|
questions = [frappe.get_doc('Question', question.question_link).as_dict() for question in quiz_question]
|
||||||
|
for question in questions:
|
||||||
|
correct_options = [option.is_correct for option in question.options]
|
||||||
|
if sum(correct_options) > 1:
|
||||||
|
question['type'] = "MultipleChoice"
|
||||||
|
else:
|
||||||
|
question['type'] = "SingleChoice"
|
||||||
return questions
|
return questions
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<hr>
|
<hr>
|
||||||
<div id="quiz" :name="content">
|
<div id="quiz" :name="content">
|
||||||
<div id="quiz-body">
|
<div id="quiz-body">
|
||||||
<QuizSingleChoice v-for="question in quizData" :key="question.name" :question="question" @updateResponse="updateResponse"/>
|
<component v-for="question in quizData" :key="question.name" v-bind:is="question.type" :question="question" @updateResponse="updateResponse"></component>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<div>
|
<div>
|
||||||
@@ -40,6 +40,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import QuizSingleChoice from "./Quiz/QuizSingleChoice.vue"
|
import QuizSingleChoice from "./Quiz/QuizSingleChoice.vue"
|
||||||
|
import QuizMultipleChoice from "./Quiz/QuizMultipleChoice.vue"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['content', 'type'],
|
props: ['content', 'type'],
|
||||||
name: 'Quiz',
|
name: 'Quiz',
|
||||||
@@ -57,7 +59,8 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
QuizSingleChoice,
|
'SingleChoice': QuizSingleChoice,
|
||||||
|
'MultipleChoice': QuizMultipleChoice
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getQuizWithoutAnswers() {
|
getQuizWithoutAnswers() {
|
||||||
@@ -68,7 +71,18 @@ export default {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
updateResponse(res) {
|
updateResponse(res) {
|
||||||
|
if (res.type == 'SingleChoice') {
|
||||||
this.quizResponse[res.question] = (res.option)
|
this.quizResponse[res.question] = (res.option)
|
||||||
|
}
|
||||||
|
if (res.type == 'MultipleChoice') {
|
||||||
|
if (!this.quizResponse[res.question]) {
|
||||||
|
this.quizResponse[res.question] = [res.option]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.quizResponse[res.question].push(res.option)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(this.quizResponse)
|
||||||
},
|
},
|
||||||
submitQuiz() {
|
submitQuiz() {
|
||||||
lms.call("evaluate_quiz",
|
lms.call("evaluate_quiz",
|
||||||
@@ -83,7 +97,17 @@ export default {
|
|||||||
this.quizResponse = null
|
this.quizResponse = null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentComponent: function() {
|
||||||
|
if(this.quizData.type === "MultipleChoice") {
|
||||||
|
return 'QuizMultipleChoice'
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return 'QuizSingleChoice'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<div class="question mt-4">
|
||||||
|
<h5>{{ question.question }}</h5>
|
||||||
|
<div class="options ml-2">
|
||||||
|
<div v-for="option in question.options" :key="option.name" class="form-check pb-1">
|
||||||
|
<input class="form-check-input" type="checkbox" :name="question.name" :id="option.name" :value="option.name" @change="emitResponse(question.name, option.name)">
|
||||||
|
<label class="form-check-label" :for="option.name">
|
||||||
|
{{ option.option }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ['question'],
|
||||||
|
name: 'QuizSingleChoice',
|
||||||
|
methods: {
|
||||||
|
emitResponse(q, o) {
|
||||||
|
this.$emit('updateResponse', {'question':q , 'option': o, 'type': this.question.type})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
</style>
|
||||||
@@ -18,7 +18,7 @@ export default {
|
|||||||
name: 'QuizSingleChoice',
|
name: 'QuizSingleChoice',
|
||||||
methods: {
|
methods: {
|
||||||
emitResponse(q, o) {
|
emitResponse(q, o) {
|
||||||
this.$emit('updateResponse', {'question':q , 'option': o})
|
this.$emit('updateResponse', {'question':q , 'option': o, 'type': this.question.type})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ def get_quiz_with_answers(quiz_name):
|
|||||||
def get_quiz_without_answers(quiz_name):
|
def get_quiz_without_answers(quiz_name):
|
||||||
try:
|
try:
|
||||||
quiz = frappe.get_doc("Quiz", quiz_name).get_questions()
|
quiz = frappe.get_doc("Quiz", quiz_name).get_questions()
|
||||||
quiz_output = [{'name':question.name, 'question':question.question, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in quiz]
|
quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in quiz]
|
||||||
return quiz_output
|
return quiz_output
|
||||||
except:
|
except:
|
||||||
frappe.throw("Quiz {0} does not exist".format(quiz_name))
|
frappe.throw("Quiz {0} does not exist".format(quiz_name))
|
||||||
|
|||||||
Reference in New Issue
Block a user