feat: quiz refactor
This commit is contained in:
@@ -98,7 +98,6 @@ override_doctype_class = {
|
|||||||
|
|
||||||
doc_events = {
|
doc_events = {
|
||||||
"Discussion Reply": {"after_insert": "lms.lms.utils.create_notification_log"},
|
"Discussion Reply": {"after_insert": "lms.lms.utils.create_notification_log"},
|
||||||
"Course Lesson": {"on_update": "lms.lms.doctype.lms_quiz.lms_quiz.update_lesson_info"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Scheduled Tasks
|
# Scheduled Tasks
|
||||||
|
|||||||
0
lms/lms/doctype/lms_question/__init__.py
Normal file
0
lms/lms/doctype/lms_question/__init__.py
Normal file
8
lms/lms/doctype/lms_question/lms_question.js
Normal file
8
lms/lms/doctype/lms_question/lms_question.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2023, Frappe and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
// frappe.ui.form.on("LMS Question", {
|
||||||
|
// refresh(frm) {
|
||||||
|
|
||||||
|
// },
|
||||||
|
// });
|
||||||
221
lms/lms/doctype/lms_question/lms_question.json
Normal file
221
lms/lms/doctype/lms_question/lms_question.json
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "format:QTS-{YYYY}-{#####}",
|
||||||
|
"creation": "2023-10-10 10:24:14.035772",
|
||||||
|
"default_view": "List",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"question",
|
||||||
|
"type",
|
||||||
|
"multiple",
|
||||||
|
"section_break_ytxi",
|
||||||
|
"option_1",
|
||||||
|
"is_correct_1",
|
||||||
|
"column_break_fpvl",
|
||||||
|
"explanation_1",
|
||||||
|
"section_break_eiaa",
|
||||||
|
"option_2",
|
||||||
|
"is_correct_2",
|
||||||
|
"column_break_akwy",
|
||||||
|
"explanation_2",
|
||||||
|
"section_break_cwqv",
|
||||||
|
"option_3",
|
||||||
|
"is_correct_3",
|
||||||
|
"column_break_atpl",
|
||||||
|
"explanation_3",
|
||||||
|
"section_break_yqel",
|
||||||
|
"option_4",
|
||||||
|
"is_correct_4",
|
||||||
|
"column_break_lknb",
|
||||||
|
"explanation_4",
|
||||||
|
"section_break_hkfe",
|
||||||
|
"possible_answer_1",
|
||||||
|
"possible_answer_3",
|
||||||
|
"column_break_wpjr",
|
||||||
|
"possible_answer_2",
|
||||||
|
"possible_answer_4"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "question",
|
||||||
|
"fieldtype": "Text Editor",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Question"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Type",
|
||||||
|
"options": "Choices\nUser Input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.type == \"Choices\";",
|
||||||
|
"fieldname": "section_break_ytxi",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "option_1",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Option 1",
|
||||||
|
"mandatory_depends_on": "eval: doc.type == 'Choices'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_correct_1",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Correct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_fpvl",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "explanation_1",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Explanation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.type == \"Choices\";",
|
||||||
|
"fieldname": "section_break_eiaa",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "option_2",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Option 2",
|
||||||
|
"mandatory_depends_on": "eval: doc.type == 'Choices'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_correct_2",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Correct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_akwy",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "explanation_2",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Explanation "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: doc.type == 'Choices'",
|
||||||
|
"fieldname": "section_break_cwqv",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "option_3",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Option 3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_correct_3",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Correct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_atpl",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "explanation_3",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Explanation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: doc.type == 'Choices'",
|
||||||
|
"fieldname": "section_break_yqel",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "option_4",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Option 4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_correct_4",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Correct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_lknb",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "explanation_4",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Explanation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "multiple",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Multiple Correct Answers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: doc.type == 'User Input'",
|
||||||
|
"fieldname": "section_break_hkfe",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "possible_answer_1",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Possible Answer 1",
|
||||||
|
"mandatory_depends_on": "eval: doc.type == 'User Input'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "possible_answer_3",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Possible Answer 3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_wpjr",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "possible_answer_2",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Possible Answer 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "possible_answer_4",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Possible Answer 4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2023-10-10 16:03:38.776125",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "LMS Question",
|
||||||
|
"naming_rule": "Expression",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"title_field": "question"
|
||||||
|
}
|
||||||
48
lms/lms/doctype/lms_question/lms_question.py
Normal file
48
lms/lms/doctype/lms_question/lms_question.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Copyright (c) 2023, Frappe and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class LMSQuestion(Document):
|
||||||
|
def validate(self):
|
||||||
|
self.validate_correct_answers()
|
||||||
|
|
||||||
|
|
||||||
|
def validate_correct_answers(question):
|
||||||
|
if question.type == "Choices":
|
||||||
|
validate_duplicate_options(question)
|
||||||
|
validate_correct_options(question)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_duplicate_options(question):
|
||||||
|
options = []
|
||||||
|
|
||||||
|
for num in range(1, 5):
|
||||||
|
if question.get(f"option_{num}"):
|
||||||
|
options.append(question.get(f"option_{num}"))
|
||||||
|
|
||||||
|
if len(set(options)) != len(options):
|
||||||
|
frappe.throw(_("Duplicate options found for this question."))
|
||||||
|
|
||||||
|
|
||||||
|
def validate_correct_options(question):
|
||||||
|
correct_options = get_correct_options(question)
|
||||||
|
|
||||||
|
if len(correct_options) > 1:
|
||||||
|
question.multiple = 1
|
||||||
|
|
||||||
|
if not len(correct_options):
|
||||||
|
frappe.throw(_("At least one option must be correct for this question."))
|
||||||
|
|
||||||
|
|
||||||
|
def get_correct_options(question):
|
||||||
|
correct_option_fields = [
|
||||||
|
"is_correct_1",
|
||||||
|
"is_correct_2",
|
||||||
|
"is_correct_3",
|
||||||
|
"is_correct_4",
|
||||||
|
]
|
||||||
|
return list(filter(lambda x: question.get(x) == 1, correct_option_fields))
|
||||||
9
lms/lms/doctype/lms_question/test_lms_question.py
Normal file
9
lms/lms/doctype/lms_question/test_lms_question.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2023, Frappe and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestLMSQuestion(FrappeTestCase):
|
||||||
|
pass
|
||||||
@@ -7,6 +7,7 @@ from frappe import _
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cstr
|
from frappe.utils import cstr
|
||||||
from lms.lms.utils import generate_slug, has_course_moderator_role, can_create_courses
|
from lms.lms.utils import generate_slug, has_course_moderator_role, can_create_courses
|
||||||
|
from lms.lms.doctype.lms_question.lms_question import validate_correct_answers
|
||||||
|
|
||||||
|
|
||||||
class LMSQuiz(Document):
|
class LMSQuiz(Document):
|
||||||
@@ -14,9 +15,6 @@ class LMSQuiz(Document):
|
|||||||
if not self.name:
|
if not self.name:
|
||||||
self.name = generate_slug(self.title, "LMS Quiz")
|
self.name = generate_slug(self.title, "LMS Quiz")
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
validate_correct_answers(self.questions)
|
|
||||||
|
|
||||||
def get_last_submission_details(self):
|
def get_last_submission_details(self):
|
||||||
"""Returns the latest submission for this user."""
|
"""Returns the latest submission for this user."""
|
||||||
user = frappe.session.user
|
user = frappe.session.user
|
||||||
@@ -35,78 +33,6 @@ class LMSQuiz(Document):
|
|||||||
return result[0]
|
return result[0]
|
||||||
|
|
||||||
|
|
||||||
def get_correct_options(question):
|
|
||||||
correct_option_fields = [
|
|
||||||
"is_correct_1",
|
|
||||||
"is_correct_2",
|
|
||||||
"is_correct_3",
|
|
||||||
"is_correct_4",
|
|
||||||
]
|
|
||||||
return list(filter(lambda x: question.get(x) == 1, correct_option_fields))
|
|
||||||
|
|
||||||
|
|
||||||
def validate_correct_answers(questions):
|
|
||||||
for question in questions:
|
|
||||||
if question.type == "Choices":
|
|
||||||
validate_duplicate_options(question)
|
|
||||||
validate_correct_options(question)
|
|
||||||
else:
|
|
||||||
validate_possible_answer(question)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_duplicate_options(question):
|
|
||||||
options = []
|
|
||||||
|
|
||||||
for num in range(1, 5):
|
|
||||||
if question.get(f"option_{num}"):
|
|
||||||
options.append(question.get(f"option_{num}"))
|
|
||||||
|
|
||||||
if len(set(options)) != len(options):
|
|
||||||
frappe.throw(
|
|
||||||
_("Duplicate options found for this question: {0}").format(
|
|
||||||
frappe.bold(question.question)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_correct_options(question):
|
|
||||||
correct_options = get_correct_options(question)
|
|
||||||
|
|
||||||
if len(correct_options) > 1:
|
|
||||||
question.multiple = 1
|
|
||||||
|
|
||||||
if not len(correct_options):
|
|
||||||
frappe.throw(
|
|
||||||
_("At least one option must be correct for this question: {0}").format(
|
|
||||||
frappe.bold(question.question)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_possible_answer(question):
|
|
||||||
possible_answers_fields = [
|
|
||||||
"possibility_1",
|
|
||||||
"possibility_2",
|
|
||||||
"possibility_3",
|
|
||||||
"possibility_4",
|
|
||||||
]
|
|
||||||
possible_answers = list(filter(lambda x: question.get(x), possible_answers_fields))
|
|
||||||
|
|
||||||
if not len(possible_answers):
|
|
||||||
frappe.throw(
|
|
||||||
_("Add at least one possible answer for this question: {0}").format(
|
|
||||||
frappe.bold(question.question)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def update_lesson_info(doc, method):
|
|
||||||
if doc.quiz_id:
|
|
||||||
frappe.db.set_value(
|
|
||||||
"LMS Quiz", doc.quiz_id, {"lesson": doc.name, "course": doc.course}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def quiz_summary(quiz, results):
|
def quiz_summary(quiz, results):
|
||||||
score = 0
|
score = 0
|
||||||
@@ -171,7 +97,8 @@ def save_quiz(
|
|||||||
@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])
|
for value in values:
|
||||||
|
validate_correct_answers(value)
|
||||||
|
|
||||||
if values.get("name"):
|
if values.get("name"):
|
||||||
doc = frappe.get_doc("LMS Quiz Question", values.get("name"))
|
doc = frappe.get_doc("LMS Quiz Question", values.get("name"))
|
||||||
|
|||||||
@@ -5,209 +5,22 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"question",
|
"question"
|
||||||
"type",
|
|
||||||
"options_section",
|
|
||||||
"option_1",
|
|
||||||
"is_correct_1",
|
|
||||||
"column_break_5",
|
|
||||||
"explanation_1",
|
|
||||||
"section_break_5",
|
|
||||||
"option_2",
|
|
||||||
"is_correct_2",
|
|
||||||
"column_break_10",
|
|
||||||
"explanation_2",
|
|
||||||
"column_break_4",
|
|
||||||
"option_3",
|
|
||||||
"is_correct_3",
|
|
||||||
"column_break_15",
|
|
||||||
"explanation_3",
|
|
||||||
"section_break_11",
|
|
||||||
"option_4",
|
|
||||||
"is_correct_4",
|
|
||||||
"column_break_20",
|
|
||||||
"explanation_4",
|
|
||||||
"section_break_mnhr",
|
|
||||||
"possibility_1",
|
|
||||||
"possibility_3",
|
|
||||||
"column_break_vnaj",
|
|
||||||
"possibility_2",
|
|
||||||
"possibility_4",
|
|
||||||
"section_break_c1lf",
|
|
||||||
"multiple"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "question",
|
"fieldname": "question",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Question",
|
"label": "Question",
|
||||||
|
"options": "LMS Question",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "option_1",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Option 1",
|
|
||||||
"mandatory_depends_on": "eval: doc.type == 'Choices'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "option_2",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Option 2",
|
|
||||||
"mandatory_depends_on": "eval: doc.type == 'Choices'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "option_3",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Option 3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "option_4",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Option 4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "option_1",
|
|
||||||
"fieldname": "is_correct_1",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Is Correct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "option_2",
|
|
||||||
"fieldname": "is_correct_2",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Is Correct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "option_3",
|
|
||||||
"fieldname": "is_correct_3",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Is Correct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "option_4",
|
|
||||||
"fieldname": "is_correct_4",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Is Correct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "multiple",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "Multiple Correct Answers",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval: doc.type == 'Choices'",
|
|
||||||
"fieldname": "options_section",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval: doc.type == 'Choices'",
|
|
||||||
"fieldname": "column_break_4",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval: doc.type == 'Choices'",
|
|
||||||
"fieldname": "section_break_5",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval: doc.type == 'Choices'",
|
|
||||||
"fieldname": "section_break_11",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "option_1",
|
|
||||||
"fieldname": "explanation_1",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Explanation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "option_2",
|
|
||||||
"fieldname": "explanation_2",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Explanation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "option_3",
|
|
||||||
"fieldname": "explanation_3",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Explanation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "option_4",
|
|
||||||
"fieldname": "explanation_4",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Explanation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_5",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_10",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_15",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_20",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "type",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Type",
|
|
||||||
"options": "Choices\nUser Input"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval: doc.type == 'User Input'",
|
|
||||||
"fieldname": "section_break_mnhr",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "possibility_1",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Possible Answer 1",
|
|
||||||
"mandatory_depends_on": "eval: doc.type == 'User Input'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "possibility_2",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Possible Answer 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "possibility_3",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Possible Answer 3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "possibility_4",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Possible Answer 4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_c1lf",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_vnaj",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-07-04 16:43:49.837134",
|
"modified": "2023-10-10 15:42:51.791902",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz Question",
|
"name": "LMS Quiz Question",
|
||||||
|
|||||||
@@ -72,3 +72,5 @@ lms.patches.v1_0.publish_certificates
|
|||||||
lms.patches.v1_0.change_naming_for_batch_course #14-09-2023
|
lms.patches.v1_0.change_naming_for_batch_course #14-09-2023
|
||||||
execute:frappe.permissions.reset_perms("LMS Enrollment")
|
execute:frappe.permissions.reset_perms("LMS Enrollment")
|
||||||
lms.patches.v1_0.create_student_role
|
lms.patches.v1_0.create_student_role
|
||||||
|
lms.patches.v1_0.mark_confirmation_for_batch_students
|
||||||
|
lms.patches.v1_0.create_quiz_questions
|
||||||
52
lms/patches/v1_0/create_quiz_questions.py
Normal file
52
lms/patches/v1_0/create_quiz_questions.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("lms", "doctype", "lms_question")
|
||||||
|
frappe.reload_doc("lms", "doctype", "lms_quiz_question")
|
||||||
|
|
||||||
|
questions = frappe.get_all(
|
||||||
|
"LMS Quiz Question",
|
||||||
|
fields=[
|
||||||
|
"name",
|
||||||
|
"question",
|
||||||
|
"type",
|
||||||
|
"multiple",
|
||||||
|
"option_1",
|
||||||
|
"is_correct_1",
|
||||||
|
"explanation_1",
|
||||||
|
"option_2",
|
||||||
|
"is_correct_2",
|
||||||
|
"explanation_2",
|
||||||
|
"option_3",
|
||||||
|
"is_correct_3",
|
||||||
|
"explanation_3",
|
||||||
|
"option_4",
|
||||||
|
"is_correct_4",
|
||||||
|
"explanation_4",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
for question in questions:
|
||||||
|
doc = frappe.new_doc("LMS Question")
|
||||||
|
doc.update(
|
||||||
|
{
|
||||||
|
"question": question.question,
|
||||||
|
"type": question.type,
|
||||||
|
"multiple": question.multiple,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
for num in range(1, 5):
|
||||||
|
if question.get(f"option_{num}"):
|
||||||
|
doc.update(
|
||||||
|
{
|
||||||
|
f"option_{num}": question[f"option_{num}"],
|
||||||
|
f"is_correct_{num}": question[f"is_correct_{num}"],
|
||||||
|
f"explanation_{num}": question[f"explanation_{num}"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
doc.save()
|
||||||
|
|
||||||
|
frappe.db.set_value("LMS Quiz Question", question.name, "question", doc.name)
|
||||||
9
lms/patches/v1_0/mark_confirmation_for_batch_students.py
Normal file
9
lms/patches/v1_0/mark_confirmation_for_batch_students.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("lms", "doctype", "batch_student")
|
||||||
|
students = frappe.get_all("Batch Student", pluck="name")
|
||||||
|
|
||||||
|
for student in students:
|
||||||
|
frappe.db.set_value("Batch Student", student, "confirmation_email_sent", 1)
|
||||||
@@ -653,7 +653,7 @@ const setup_calendar = (events) => {
|
|||||||
const options = get_calendar_options(element, calendar_id);
|
const options = get_calendar_options(element, calendar_id);
|
||||||
const calendar = new Calendar(container, options);
|
const calendar = new Calendar(container, options);
|
||||||
this.calendar_ = calendar;
|
this.calendar_ = calendar;
|
||||||
console.log(options);
|
|
||||||
create_events(calendar, events);
|
create_events(calendar, events);
|
||||||
add_links_to_events(calendar, events);
|
add_links_to_events(calendar, events);
|
||||||
scroll_to_date(calendar, events);
|
scroll_to_date(calendar, events);
|
||||||
|
|||||||
Reference in New Issue
Block a user