feat: add questions from LMS Portal

This commit is contained in:
Jannat Patel
2023-10-19 22:15:30 +05:30
parent 52cde329c1
commit 3f7d1b1e83
3 changed files with 92 additions and 30 deletions

View File

@@ -17,7 +17,7 @@ from lms.lms.utils import (
class LMSQuiz(Document): class LMSQuiz(Document):
def validate(self): def validate(self):
self.validate_duplicate_questions() self.validate_duplicate_questions()
self.set_total_marks() self.total_marks = set_total_marks(self.name, self.questions)
def validate_duplicate_questions(self): def validate_duplicate_questions(self):
questions = [row.question for row in self.questions] questions = [row.question for row in self.questions]
@@ -27,13 +27,6 @@ class LMSQuiz(Document):
_("Rows {0} have the duplicate questions.").format(frappe.bold(comma_and(rows))) _("Rows {0} have the duplicate questions.").format(frappe.bold(comma_and(rows)))
) )
def set_total_marks(self):
marks = 0
for question in self.questions:
marks += question.marks
self.total_marks = marks
def autoname(self): def autoname(self):
if not self.name: if not self.name:
self.name = generate_slug(self.title, "LMS Quiz") self.name = generate_slug(self.title, "LMS Quiz")
@@ -56,6 +49,13 @@ class LMSQuiz(Document):
return result[0] return result[0]
def set_total_marks(quiz, questions):
marks = 0
for question in questions:
marks += question.get("marks")
return marks
@frappe.whitelist() @frappe.whitelist()
def quiz_summary(quiz, results): def quiz_summary(quiz, results):
score = 0 score = 0
@@ -116,6 +116,7 @@ def quiz_summary(quiz, results):
def save_quiz( def save_quiz(
quiz_title, quiz_title,
passing_percentage, passing_percentage,
questions,
max_attempts=0, max_attempts=0,
quiz=None, quiz=None,
show_answers=1, show_answers=1,
@@ -134,18 +135,64 @@ def save_quiz(
if quiz: if quiz:
frappe.db.set_value("LMS Quiz", quiz, values) frappe.db.set_value("LMS Quiz", quiz, values)
update_questions(quiz, questions)
return quiz return quiz
else: else:
doc = frappe.new_doc("LMS Quiz") doc = frappe.new_doc("LMS Quiz")
doc.update(values) doc.update(values)
doc.save() doc.save()
update_questions(doc.name, questions)
return doc.name return doc.name
def update_questions(quiz, questions):
questions = json.loads(questions)
delete_questions(quiz, questions)
add_questions(quiz, questions)
frappe.db.set_value("LMS Quiz", quiz, "total_marks", set_total_marks(quiz, questions))
def delete_questions(quiz, questions):
existing_questions = frappe.get_all(
"LMS Quiz Question",
{
"parent": quiz,
},
pluck="name",
)
current_questions = [question.get("question_name") for question in questions]
for question in existing_questions:
if question not in current_questions:
frappe.db.delete("LMS Quiz Question", question)
def add_questions(quiz, questions):
for index, question in enumerate(questions):
question = frappe._dict(question)
if question.question_name:
doc = frappe.get_doc("LMS Quiz Question", question.question_name)
else:
doc = frappe.new_doc("LMS Quiz Question")
doc.update(
{
"parent": quiz,
"parenttype": "LMS Quiz",
"parentfield": "questions",
"idx": index + 1,
}
)
doc.update({"question": question.question, "marks": question.marks})
doc.save()
@frappe.whitelist() @frappe.whitelist()
def save_question(quiz, values, index): def save_question(quiz, values, index):
values = frappe._dict(json.loads(values)) values = frappe._dict(json.loads(values))
validate_correct_answers(values)
if values.get("name"): if values.get("name"):
doc = frappe.get_doc("LMS Question", values.get("name")) doc = frappe.get_doc("LMS Question", values.get("name"))
@@ -182,8 +229,7 @@ def save_question(quiz, values, index):
} }
) )
doc.save() doc.save()
return doc.name return doc.name

View File

@@ -16,18 +16,9 @@
{% macro QuizForm(quiz) %} {% macro QuizForm(quiz) %}
<div id="quiz-form" {% if quiz.name %} data-name="{{ quiz.name }}" data-index="{{ quiz.questions | length }}" {% endif %}> <div id="quiz-form" {% if quiz.name %} data-name="{{ quiz.name }}" data-index="{{ quiz.questions | length }}" {% endif %}>
{{ QuizDetails(quiz) }} {{ QuizDetails(quiz) }}
{% if quiz.questions %} <div class="field-group">
<div class="field-group"> <div class="questions-table"></div>
<div class="questions-table"></div> </div>
<!-- <button class="btn btn-secondary btn-sm btn-add-question mt-4">
{{ _("New Question") }}
</button> -->
</div>
{% endif %}
{% if quiz.name and not quiz.questions | length %}
{{ EmptyState() }}
{% endif %}
</div> </div>
{% endmacro %} {% endmacro %}
@@ -153,7 +144,7 @@
{{ super() }} {{ super() }}
{% if has_course_instructor_role() or has_course_moderator_role() %} {% if has_course_instructor_role() or has_course_moderator_role() %}
<script> <script>
const quiz_questions = {{ quiz.questions }} const quiz_questions = {{ quiz.questions or [] }}
</script> </script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@@ -13,10 +13,6 @@ frappe.ready(() => {
edit_question(e); edit_question(e);
}); });
/* $(".btn-add-question").click((e) => {
show_question_modal();
}); */
$(document).on("click", ".questions-table .link-btn", (e) => { $(document).on("click", ".questions-table .link-btn", (e) => {
e.preventDefault(); e.preventDefault();
fetch_question_data(e); fetch_question_data(e);
@@ -131,6 +127,8 @@ const edit_question = (e) => {
const save_quiz = (values) => { const save_quiz = (values) => {
validate_mandatory(); validate_mandatory();
validate_questions();
frappe.call({ frappe.call({
method: "lms.lms.doctype.lms_quiz.lms_quiz.save_quiz", method: "lms.lms.doctype.lms_quiz.lms_quiz.save_quiz",
args: { args: {
@@ -138,6 +136,7 @@ const save_quiz = (values) => {
max_attempts: $("#max-attempts").val(), max_attempts: $("#max-attempts").val(),
passing_percentage: $("#passing-percentage").val(), passing_percentage: $("#passing-percentage").val(),
quiz: $("#quiz-form").data("name") || "", quiz: $("#quiz-form").data("name") || "",
questions: this.table.get_value("questions"),
show_answers: $("#show-answers").is(":checked") ? 1 : 0, show_answers: $("#show-answers").is(":checked") ? 1 : 0,
show_submission_history: $("#show-submission-history").is( show_submission_history: $("#show-submission-history").is(
":checked" ":checked"
@@ -171,6 +170,24 @@ const validate_mandatory = () => {
}); });
}; };
const validate_questions = () => {
let questions = this.table.get_value("questions");
if (!questions.length) {
frappe.throw(__("Please add a question."));
}
questions.forEach((question, index) => {
if (!question.question) {
frappe.throw(__("Please add question in row ") + (index + 1));
}
if (!question.marks) {
frappe.throw(__("Please add marks in row ") + (index + 1));
}
});
};
const scroll_to_element = (element) => { const scroll_to_element = (element) => {
if ($(element).length) { if ($(element).length) {
$([document.documentElement, document.body]).animate( $([document.documentElement, document.body]).animate(
@@ -224,16 +241,24 @@ const create_questions_table = () => {
{ {
fieldname: "question", fieldname: "question",
fieldtype: "Link", fieldtype: "Link",
label: "Question", label: __("Question"),
options: "LMS Question", options: "LMS Question",
in_list_view: 1, in_list_view: 1,
only_select: 1, only_select: 1,
reqd: 1,
}, },
{ {
fieldname: "marks", fieldname: "marks",
fieldtype: "Int", fieldtype: "Int",
label: "Marks", label: __("Marks"),
in_list_view: 1, in_list_view: 1,
reqd: 1,
},
{
fieldname: "question_name",
fieldname: "Link",
options: "LMS Quiz Question",
label: __("Question Name"),
}, },
], ],
}, },