feat: quiz-creation-ui

This commit is contained in:
Jannat Patel
2022-08-18 19:52:27 +05:30
parent eb50f6fd8f
commit e1b16e9ae3
12 changed files with 246 additions and 17 deletions

View File

@@ -186,7 +186,7 @@
<div class="mt-4">
<button class="btn btn-primary btn-sm btn-lesson pull-right ml-2"> {{ _("Save") }} </button>
<button class="btn btn-secondary btn-sm pull-right btn-back ml-2"> {{ _("Back to Lesson") }} </button>
<a class="btn btn-secondary btn-sm pull-right" href="/courses/quiz-list"> {{ _("Create a Quiz") }} </a>
<a class="btn btn-secondary btn-sm pull-right" href="/quizzes"> {{ _("Create a Quiz") }} </a>
<div class="attachments-parent">
<div class="attachment-controls">

View File

@@ -0,0 +1,74 @@
{% extends "templates/base.html" %}
{% block title %}
{{ _("Quiz List") }}
{% endblock %}
{% block head_include %}
{% include "public/icons/symbol-defs.svg" %}
{% endblock %}
{% block content %}
<div class="common-page-style" style="background-color: var(--fg-color);">
<div class="container">
{{ BreadCrumb(quiz) }}
{{ QuizCard(quiz) }}
</div>
</div>
{% endblock %}
{% macro BreadCrumb(quiz) %}
<div class="breadcrumb">
<a class="dark-links" href="/courses">{{ _("Quizzes") }}</a>
<img class="ml-1 mr-1" src="/assets/lms/icons/chevron-right.svg">
<span class="breadcrumb-destination">{{ quiz.title if quiz.title else _("New Quiz") }}</span>
</div>
{% endmacro %}
{% macro QuizCard(quiz) %}
<div style="width: 60%;">
<div class="course-home-headings mb-2" data-placeholder="{{ _('Quiz Title') }}" id="quiz-title"
contenteditable="true">{% if quiz.title %}{{ quiz.title }}{% endif %}</div>
<div class="mt-4">
<button class="btn btn-secondary btn-sm btn-question"> {{ _("New Question") }} </button>
<button class="btn btn-primary btn-sm btn-save-question ml-2 hide"> {{ _("Save") }} </button>
</div>
{% if quiz.question %}
{% for question in quiz.questions %}
<div class="quiz-card">
<div contenteditable="true" data-placeholder="{{ _('Question') }}"
class="mb-4">{% if question.question %} {{ question.question }} {% endif %}</div>
{% for num in range(1,5) %}
{% set option = question["option_" + frappe.utils.cstr(num)] %}
{% set explanation = question["explanation_" + frappe.utils.cstr(num)] %}
<div class="mt-4">
<label class=""> {{ _("Option") }} {{ frappe.utils.cstr(num) }} </label>
<div class="d-flex justify-content-between">
<div contenteditable="true" data-placeholder="{{ _('Option') }}"
class="option-input">{% if option %}{{ option }}{% endif %}</div>
<div contenteditable="true" data-placeholder="{{ _('Explanation') }}"
class="option-input">{% if explanation %}{{ explanation }}{% endif %}</div>
<div class="option-checkbox">
<input type="checkbox" {% if question['is_correct_' + frappe.utils.cstr(num)] %} checked {% endif %}>
<label class="mb-0"> {{ _("Is Correct") }} </label>
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% endif %}
</div>
{% endmacro %}

91
lms/www/batch/quiz.js Normal file
View File

@@ -0,0 +1,91 @@
frappe.ready(() => {
$(".btn-question").click((e) => {
add_question(e);
});
$(".btn-save-question").click((e) => {
save_question(e);
});
});
const add_question = (e) => {
let add_after = $(".quiz-card").length ? $(".quiz-card") : $("#quiz-title");
let question_template = `<div class="quiz-card">
<div contenteditable="true" data-placeholder="${__("Question")}" class="question mb-4"></div>
</div>`;
$(question_template).insertAfter(add_after);
get_question_template();
$(".btn-save-question").removeClass("hide");
};
const get_question_template = () => {
Array.from({length: 4}, (x, num) => {
let option_template = get_option_template(num + 1);
let add_after = $(".quiz-card:last .option-group").length ? $(".quiz-card:last .option-group").last() : $(".question:last");
question_template = $(option_template).insertAfter(add_after);
});
};
const get_option_template = (num) => {
return `<div class="option-group mt-4">
<label class="">${__("Option")} ${num}</label>
<div class="d-flex justify-content-between option-${num}">
<div contenteditable="true" data-placeholder="${ __("Option") }"
class="option-input"></div>
<div contenteditable="true" data-placeholder="${ __('Explanation') }"
class="option-input"></div>
<div class="option-checkbox">
<input type="checkbox">
<label class="mb-0"> ${ __("Is Correct") } </label>
</div>
</div>
</div>`;
};
const save_question = (e) => {
if (!$("#quiz-title").text()) {
frappe.throw(__("Quiz Title is mandatory."));
}
console.log(get_questions());
debugger;
frappe.call({
method: lms.lms.doctype.lms_quiz.lms_quiz.save_quiz,
args: {
"quiz-title": $("#quiz-title"),
"questions": get_questions()
},
callback: (data) => {
}
});
};
const get_questions = () => {
let questions = [];
$(".quiz-card").each((i, elem) => {
if (!$(elem).find(".question").text())
return;
let question_details = {};
question_details["question"] = $(elem).find(".question").text();
Array.from({length: 4}, (x, i) => {
let num = i + 1;
question_details[`option_${num}`] = $(`.option-${num} .option-input:first`).text();
question_details[`explanation_${num}`] = $(`.option-${num} .option-input:last`).text();
question_details[`is_correct_${num}`] = $(`.option-${num} .option-checkbox`).find("input").prop("checked");
});
questions.push(question_details);
});
return questions
};

View File

@@ -0,0 +1,20 @@
import frappe
from frappe.utils import cstr
def get_context(context):
quizname = frappe.form_dict["quizname"]
if quizname == "new-quiz":
context.quiz = frappe._dict()
context.quiz.edit_mode = 1
else:
fields_arr = []
for num in range(1,5):
fields_arr.append("option_" + cstr(num))
fields_arr.append("is_correct_" + cstr(num))
fields_arr.append("explanation_" + cstr(num))
fields_arr.append("question")
context.quiz = frappe.db.get_value("LMS Quiz", quizname, ["title"], as_dict=1)
context.quiz.questions = frappe.get_all("LMS Quiz Question", {
"parent": quizname
}, fields_arr)

View File

@@ -12,7 +12,8 @@
{% block content %}
<div class="common-page-style">
<div class="container">
<a class="btn btn-primary btn-sm pull-right"> {{ _("Add Quiz") }} </a>
{% if quiz_list | length %}
<a class="btn btn-secondary btn-sm pull-right" href="/quizzes/new-quiz"> {{ _("Add Quiz") }} </a>
<div class="course-home-headings"> {{ _("Quiz List") }} </div>
<div class="common-card-style">
<table class="table">
@@ -24,12 +25,23 @@
<tr style="position: relative; color: var(--text-color);">
<td> {{ loop.index }} </td>
<td>
<a class="button-links" href="/courses/quiz/{{ quiz.name }}">{{ quiz.name }}</a>
<a class="button-links" href="/quizzes/{{ quiz.name }}">{{ quiz.name }}</a>
</td>
</tr>
{% endfor %}
</table>
</div>
{% else %}
<div class="empty-state">
<div class="empty-state-text">
<div class="empty-state-heading">{{ _("You have not created any quiz yet.") }}</div>
<div class="course-meta mb-6">{{ _("Create a quiz and add it to your course to engage users.") }}</div>
<a class="btn btn-secondary btn-sm"
href="{% if frappe.session.user == 'Guest' %} /login?redirect-to=/quizzes {% else %} /quizzes/new-quiz {% endif %}">
{{ _("Add Quiz") }} </a>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -336,7 +336,7 @@ const save_course = (e) => {
"video_link": $("#video-link").text(),
"image": $("#image").attr("href"),
"description": $("#description").text(),
"course": $("#title").data("course")
"course": $("#title").data("course") ? $("#title").data("course") : ""
},
callback: (data) => {
window.location.href = `/courses/${data.message}?edit=1`;
@@ -344,6 +344,7 @@ const save_course = (e) => {
});
};
const remove_tag = (e) => {
$(e.currentTarget).closest(".course-card-pills").remove();
};

View File

@@ -11,6 +11,8 @@ def get_context(context):
redirect_to_courses_list()
if course_name == "new-course":
if frappe.session.user == "Guest":
redirect_to_courses_list()
context.course = frappe._dict()
context.course.edit_mode = True
context.membership = None