refactor: refactored quiz api and added quiz.js
This commit is contained in:
parent
46b3446da0
commit
d1a252190b
@ -35,7 +35,7 @@ class CourseEnrollment(Document):
|
||||
if enrollment:
|
||||
frappe.throw(_("Student is already enrolled."))
|
||||
|
||||
def add_quiz_activity(self, quiz_name, quiz_response,answers, score, status):
|
||||
def add_quiz_activity(self, quiz_name, quiz_response, answers, score, status):
|
||||
result = {k: ('Correct' if v else 'Wrong') for k,v in answers.items()}
|
||||
result_data = []
|
||||
for key in answers:
|
||||
@ -43,7 +43,9 @@ class CourseEnrollment(Document):
|
||||
item['question'] = key
|
||||
item['quiz_result'] = result[key]
|
||||
try:
|
||||
if isinstance(quiz_response[key], list):
|
||||
if not quiz_response[key]:
|
||||
item['selected_option'] = "Unattempted"
|
||||
elif isinstance(quiz_response[key], list):
|
||||
item['selected_option'] = ', '.join(frappe.get_value('Options', res, 'option') for res in quiz_response[key])
|
||||
else:
|
||||
item['selected_option'] = frappe.get_value('Options', quiz_response[key], 'option')
|
||||
@ -59,7 +61,7 @@ class CourseEnrollment(Document):
|
||||
"result": result_data,
|
||||
"score": score,
|
||||
"status": status
|
||||
}).insert()
|
||||
}).insert(ignore_permissions = True)
|
||||
|
||||
def add_activity(self, content_type, content):
|
||||
activity = check_activity_exists(self.name, content_type, content)
|
||||
|
@ -11,50 +11,43 @@ class Quiz(Document):
|
||||
if self.passing_score > 100:
|
||||
frappe.throw("Passing Score value should be between 0 and 100")
|
||||
|
||||
def validate_quiz_attempts(self, enrollment, quiz_name):
|
||||
if self.max_attempts > 0:
|
||||
try:
|
||||
if len(frappe.get_all("Quiz Activity", {'enrollment': enrollment.name, 'quiz': quiz_name})) >= self.max_attempts:
|
||||
frappe.throw('Maximum attempts reached!')
|
||||
except Exception as e:
|
||||
pass
|
||||
def allowed_attempt(self, enrollment, quiz_name):
|
||||
if self.max_attempts == 0:
|
||||
return True
|
||||
|
||||
try:
|
||||
if len(frappe.get_all("Quiz Activity", {'enrollment': enrollment.name, 'quiz': quiz_name})) >= self.max_attempts:
|
||||
frappe.msgprint("Maximum attempts for this quiz reached!")
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
|
||||
def evaluate(self, response_dict, quiz_name):
|
||||
# self.validate_quiz_attempts(enrollment, quiz_name)
|
||||
questions = [frappe.get_doc('Question', question.question_link) for question in self.question]
|
||||
answers = {q.name:q.get_answer() for q in questions}
|
||||
correct_answers = {}
|
||||
result = {}
|
||||
for key in answers:
|
||||
try:
|
||||
if isinstance(response_dict[key], list):
|
||||
result = compare_list_elementwise(response_dict[key], answers[key])
|
||||
is_correct = compare_list_elementwise(response_dict[key], answers[key])
|
||||
else:
|
||||
result = (response_dict[key] == answers[key])
|
||||
except:
|
||||
result = False
|
||||
correct_answers[key] = result
|
||||
score = (sum(correct_answers.values()) * 100 ) / len(answers)
|
||||
is_correct = (response_dict[key] == answers[key])
|
||||
except Exception as e:
|
||||
is_correct = False
|
||||
result[key] = is_correct
|
||||
score = (sum(result.values()) * 100 ) / len(answers)
|
||||
if score >= self.passing_score:
|
||||
status = "Pass"
|
||||
else:
|
||||
status = "Fail"
|
||||
return correct_answers, score, status
|
||||
return result, score, status
|
||||
|
||||
|
||||
def get_questions(self):
|
||||
quiz_question = self.get_all_children()
|
||||
if 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
|
||||
else:
|
||||
return None
|
||||
return [frappe.get_doc('Question', question.question_link) for question in self.question]
|
||||
|
||||
def compare_list_elementwise(*args):
|
||||
try:
|
||||
|
@ -1,145 +1,52 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-10-15 15:52:25.766374",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"creation": "2018-10-15 15:52:25.766374",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"question",
|
||||
"selected_option",
|
||||
"quiz_result"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "question",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Question",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Question",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "question",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Question",
|
||||
"options": "Question",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "selected_option",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Selected Option",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "selected_option",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Selected Option",
|
||||
"read_only": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "quiz_result",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Result",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nCorrect\nWrong",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "quiz_result",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Result",
|
||||
"options": "\nCorrect\nWrong",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-27 17:58:54.388848",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Quiz Result",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-06-03 12:52:32.267392",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Quiz Result",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies and contributors
|
||||
# For lice
|
||||
|
||||
from __future__ import unicode_literals, division
|
||||
import frappe
|
||||
@ -173,7 +172,7 @@ def has_super_access():
|
||||
"""Check if user has a role that allows full access to LMS
|
||||
|
||||
Returns:
|
||||
bool: true if user has access to all lms content
|
||||
bool: true if user has access to all lms content
|
||||
"""
|
||||
current_user = frappe.get_doc('User', frappe.session.user)
|
||||
roles = set([role.role for role in current_user.roles])
|
||||
@ -189,7 +188,6 @@ def add_activity(course, content_type, content):
|
||||
return frappe.throw("Student with email {0} does not exist".format(frappe.session.user), frappe.DoesNotExistError)
|
||||
|
||||
course_enrollment = get_enrollment("course", course, student.name)
|
||||
print(course_enrollment)
|
||||
if not course_enrollment:
|
||||
return None
|
||||
|
||||
@ -199,6 +197,56 @@ def add_activity(course, content_type, content):
|
||||
else:
|
||||
return enrollment.add_activity(content_type, content)
|
||||
|
||||
@frappe.whitelist()
|
||||
def evaluate_quiz(quiz_response, quiz_name, course):
|
||||
import json
|
||||
|
||||
student = get_current_student()
|
||||
|
||||
quiz_response = json.loads(quiz_response)
|
||||
quiz = frappe.get_doc("Quiz", quiz_name)
|
||||
result, score, status = quiz.evaluate(quiz_response, quiz_name)
|
||||
|
||||
if has_super_access():
|
||||
return {'result': result, 'score': score, 'status': status}
|
||||
|
||||
if student:
|
||||
course_enrollment = get_enrollment("course", course, student.name)
|
||||
if course_enrollment:
|
||||
enrollment = frappe.get_doc('Course Enrollment', course_enrollment)
|
||||
if quiz.allowed_attempt(enrollment, quiz_name):
|
||||
enrollment.add_quiz_activity(quiz_name, quiz_response, result, score, status)
|
||||
return {'result': result, 'score': score, 'status': status}
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
frappe.throw("Something went wrong. Pleae contact the administrator.")
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_quiz(quiz_name, course):
|
||||
try:
|
||||
quiz = frappe.get_doc("Quiz", quiz_name)
|
||||
questions = quiz.get_questions()
|
||||
except:
|
||||
frappe.throw("Quiz {0} does not exist".format(quiz_name))
|
||||
return None
|
||||
|
||||
questions = [{
|
||||
'name': question.name,
|
||||
'question': question.question,
|
||||
'type': question.question_type,
|
||||
'options': [{'name': option.name, 'option': option.option}
|
||||
for option in question.options],
|
||||
} for question in questions]
|
||||
|
||||
if has_super_access():
|
||||
return {'questions': questions, 'activity': None}
|
||||
|
||||
student = get_current_student()
|
||||
course_enrollment = get_enrollment("course", course, student.name)
|
||||
status, score, result = check_quiz_completion(quiz, course_enrollment)
|
||||
return {'questions': questions, 'activity': {'is_complete': status, 'score': score, 'result': result}}
|
||||
|
||||
def create_student_from_current_user():
|
||||
user = frappe.get_doc("User", frappe.session.user)
|
||||
|
||||
@ -226,7 +274,7 @@ def check_content_completion(content_name, content_type, enrollment_name):
|
||||
|
||||
def check_quiz_completion(quiz, enrollment_name):
|
||||
attempts = frappe.get_all("Quiz Activity", filters={'enrollment': enrollment_name, 'quiz': quiz.name}, fields=["name", "activity_date", "score", "status"])
|
||||
status = False if quiz.max_attempts == 0 else bool(len(attempts) == quiz.max_attempts)
|
||||
status = False if quiz.max_attempts == 0 else bool(len(attempts) >= quiz.max_attempts)
|
||||
score = None
|
||||
result = None
|
||||
if attempts:
|
||||
|
185
erpnext/public/js/education/lms/quiz.js
Normal file
185
erpnext/public/js/education/lms/quiz.js
Normal file
@ -0,0 +1,185 @@
|
||||
class Quiz {
|
||||
constructor(wrapper, options) {
|
||||
this.wrapper = wrapper;
|
||||
Object.assign(this, options);
|
||||
this.questions = []
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.get_quiz();
|
||||
}
|
||||
|
||||
get_quiz() {
|
||||
frappe.call('erpnext.education.utils.get_quiz', {
|
||||
quiz_name: this.name,
|
||||
course: this.course
|
||||
}).then(res => {
|
||||
this.make(res.message)
|
||||
});
|
||||
}
|
||||
|
||||
make(data) {
|
||||
data.questions.forEach(question_data => {
|
||||
let question_wrapper = document.createElement('div');
|
||||
let question = new Question({
|
||||
wrapper: question_wrapper,
|
||||
...question_data
|
||||
});
|
||||
this.questions.push(question)
|
||||
this.wrapper.appendChild(question_wrapper);
|
||||
})
|
||||
if (data.activity.is_complete) {
|
||||
this.disable()
|
||||
let indicator = 'red'
|
||||
let message = 'Your are not allowed to attempt the quiz again.'
|
||||
if (data.activity.result == 'Pass') {
|
||||
indicator = 'green'
|
||||
message = 'You have already cleared the quiz.'
|
||||
}
|
||||
|
||||
this.set_quiz_footer(message, indicator, data.activity.score)
|
||||
}
|
||||
else {
|
||||
this.make_actions();
|
||||
}
|
||||
}
|
||||
|
||||
make_actions() {
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("btn", "btn-primary", "mt-5", "mr-2");
|
||||
|
||||
button.id = 'submit-button';
|
||||
button.innerText = 'Submit';
|
||||
button.onclick = () => this.submit();
|
||||
this.submit_btn = button
|
||||
this.wrapper.appendChild(button);
|
||||
}
|
||||
|
||||
submit() {
|
||||
this.submit_btn.innerText = 'Evaluating..'
|
||||
this.submit_btn.disabled = true
|
||||
this.disable()
|
||||
frappe.call('erpnext.education.utils.evaluate_quiz', {
|
||||
quiz_name: this.name,
|
||||
quiz_response: this.get_selected(),
|
||||
course: this.course
|
||||
}).then(res => {
|
||||
this.submit_btn.remove()
|
||||
if (!res.message) {
|
||||
frappe.throw("Something went wrong while evaluating the quiz.")
|
||||
}
|
||||
|
||||
let indicator = 'red'
|
||||
let message = 'Fail'
|
||||
if (res.message.status == 'Pass') {
|
||||
indicator = 'green'
|
||||
message = 'Congratulations, you cleared the quiz.'
|
||||
}
|
||||
|
||||
this.set_quiz_footer(message, indicator, res.message.score)
|
||||
});
|
||||
}
|
||||
|
||||
set_quiz_footer(message, indicator, score) {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("mt-5");
|
||||
div.innerHTML = `<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4>${message}</h4>
|
||||
<h5 class="text-muted"><span class="indicator ${indicator}">Score: ${score}/100</span></h5>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a href="${this.next_url}" class="btn btn-primary pull-right">${this.quiz_exit_button}</a>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
this.wrapper.appendChild(div)
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.questions.forEach(que => que.disable())
|
||||
}
|
||||
|
||||
get_selected() {
|
||||
let que = {}
|
||||
this.questions.forEach(question => {
|
||||
que[question.name] = question.get_selected()
|
||||
})
|
||||
return que
|
||||
}
|
||||
}
|
||||
|
||||
class Question {
|
||||
constructor(opts) {
|
||||
Object.assign(this, opts);
|
||||
this.make();
|
||||
}
|
||||
|
||||
make() {
|
||||
this.make_question()
|
||||
this.make_options()
|
||||
}
|
||||
|
||||
get_selected() {
|
||||
let selected = this.options.filter(opt => opt.input.checked)
|
||||
if (this.type == 'Single Correct Answer') {
|
||||
if (selected[0]) return selected[0].name
|
||||
}
|
||||
if (this.type == 'Multiple Correct Answer') {
|
||||
return selected.map(opt => opt.name)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
disable() {
|
||||
let selected = this.options.forEach(opt => opt.input.disabled = true)
|
||||
}
|
||||
|
||||
make_question() {
|
||||
let question_wrapper = document.createElement('h5');
|
||||
question_wrapper.classList.add('mt-3');
|
||||
question_wrapper.innerText = this.question;
|
||||
this.wrapper.appendChild(question_wrapper);
|
||||
}
|
||||
|
||||
make_options() {
|
||||
let make_input = (name, value) => {
|
||||
let input = document.createElement('input');
|
||||
input.id = name;
|
||||
input.name = this.name;
|
||||
input.value = value;
|
||||
input.type = 'radio';
|
||||
if (this.type == 'Multiple Correct Answer')
|
||||
input.type = 'checkbox';
|
||||
input.classList.add('form-check-input');
|
||||
return input;
|
||||
}
|
||||
|
||||
let make_label = function(name, value) {
|
||||
let label = document.createElement('label');
|
||||
label.classList.add('form-check-label');
|
||||
label.htmlFor = name;
|
||||
label.innerText = value;
|
||||
return label
|
||||
}
|
||||
|
||||
let make_option = function (wrapper, option) {
|
||||
let option_div = document.createElement('div')
|
||||
option_div.classList.add('form-check', 'pb-1')
|
||||
let input = make_input(option.name, option.option);
|
||||
let label = make_label(option.name, option.option);
|
||||
option_div.appendChild(input)
|
||||
option_div.appendChild(label)
|
||||
wrapper.appendChild(option_div)
|
||||
return {input: input, ...option}
|
||||
}
|
||||
|
||||
let options_wrapper = document.createElement('div')
|
||||
options_wrapper.classList.add('ml-2')
|
||||
let option_list = []
|
||||
this.options.forEach(opt => option_list.push(make_option(options_wrapper, opt)))
|
||||
this.options = option_list
|
||||
this.wrapper.appendChild(options_wrapper)
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@
|
||||
<div class="col-md-7">
|
||||
<h1>{{ content.name }} <span class="small text-muted">({{ position + 1 }}/{{length}})</span></h1>
|
||||
</div>
|
||||
<div class="col-md-5 text-right">
|
||||
<div id="nav-buttons" class="col-md-5 text-right" {{ 'hidden' if content_type=='Quiz' }}>
|
||||
{% if previous %}
|
||||
<a href="/lms/content?program={{ program }}&course={{ course }}&topic={{ topic }}&type={{ previous.content_type }}&content={{ previous.content }}" class='btn btn-outline-secondary'>Previous</a>
|
||||
{% else %}
|
||||
@ -70,7 +70,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="player" data-plyr-provider="{{ content.provider|lower }}" data-plyr-embed-id="{{ content.url }}"></div>
|
||||
<div class="my-5">
|
||||
<div class="my-5" style="line-height: 1.8em;">
|
||||
{{ content.description }}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@ -95,6 +95,18 @@
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro quiz() %}
|
||||
<div class="mb-5">
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<h1>{{ content.name }} <span class="small text-muted">({{ position + 1 }}/{{length}})</span></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="quiz-wrapper">
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<section class="section">
|
||||
<div>
|
||||
@ -104,7 +116,7 @@
|
||||
{% elif content_type=='Article'%}
|
||||
{{ article() }}
|
||||
{% elif content_type=='Quiz' %}
|
||||
<h2>Quiz: {{ content.name }}</h2>
|
||||
{{ quiz() }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -113,20 +125,41 @@
|
||||
|
||||
{% block script %}
|
||||
{% if content_type=='Video' %}
|
||||
<script src="https://cdn.plyr.io/3.5.3/plyr.js"></script>
|
||||
<script src="https://cdn.plyr.io/3.5.3/plyr.js"></script>
|
||||
{% elif content_type == 'Quiz' %}
|
||||
<script src='/assets/erpnext/js/education/lms/quiz.js'></script>
|
||||
{% endif %}
|
||||
<script>
|
||||
{% if content_type=='Video' %}
|
||||
{% if content_type == 'Video' %}
|
||||
const player = new Plyr('#player');
|
||||
{% elif content_type == 'Quiz' %}
|
||||
{% if next %}
|
||||
const quiz_exit_button = 'Next'
|
||||
const next_url = '/lms/content?program={{ program }}&course={{ course }}&topic={{ topic }}&type={{ next.content_type }}&content={{ next.content }}'
|
||||
{% else %}
|
||||
const quiz_exit_button = 'Finish Course'
|
||||
const next_url = '/lms/course?name={{ course }}&program={{ program }}'
|
||||
{% endif %}
|
||||
frappe.ready(() => {
|
||||
const quiz = new Quiz(document.getElementById('quiz-wrapper'), {
|
||||
name: '{{ content.name }}',
|
||||
course: '{{ course }}',
|
||||
quiz_exit_button: quiz_exit_button,
|
||||
next_url: next_url
|
||||
})
|
||||
window.quiz = quiz;
|
||||
})
|
||||
{% endif %}
|
||||
|
||||
{% if content_type != 'Quiz' %}
|
||||
|
||||
frappe.ready(() => {
|
||||
next = document.getElementById('nextButton')
|
||||
next.disabled = false;
|
||||
})
|
||||
|
||||
function handle(url) {
|
||||
|
||||
function handle(url) {
|
||||
opts = {
|
||||
method: "erpnext.education.utils.add_activity",
|
||||
args: {
|
||||
@ -139,5 +172,7 @@
|
||||
window.location.href = url;
|
||||
})
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endblock %}
|
@ -27,7 +27,7 @@ def get_context(context):
|
||||
|
||||
|
||||
# Set context for content to be displayer
|
||||
context.content = frappe.get_doc(content_type, content)
|
||||
context.content = frappe.get_doc(content_type, content).as_dict()
|
||||
context.content_type = content_type
|
||||
context.program = program
|
||||
context.course = course
|
||||
|
Loading…
x
Reference in New Issue
Block a user