feat: show and hide quiz answers

This commit is contained in:
Jannat Patel
2023-07-04 19:42:12 +05:30
parent 1abb75a58e
commit b286daad16
10 changed files with 169 additions and 79 deletions

View File

@@ -24,7 +24,8 @@
<div id="start-banner" class="common-card-style column-card align-items-center">
<div class="text-center my-10">
<div class="bold-heading" id="quiz-title" data-name="{{ quiz.name }}" data-max-attempts="{{ quiz.max_attempts }}">
<div class="bold-heading" id="quiz-title" data-max-attempts="{{ quiz.max_attempts }}"
data-name="{{ quiz.name }}" data-show-answers="{{ quiz.show_answers }}">
{{ quiz.title }}
</div>
@@ -105,10 +106,13 @@
</div>
{% endif %}
{% if quiz.show_answers %}
<button class="btn btn-secondary btn-sm pull-right" id="check" disabled>
{{ _("Check") }}
</button>
<button class="btn btn-secondary btn-sm hide" id="next">
{% endif %}
<button class="btn btn-secondary btn-sm {% if quiz.show_answers %} hide {% endif %}" id="next" disabled>
{{ _("Next Question") }}
</button>
<button class="btn btn-secondary btn-sm hide" id="summary">
@@ -122,7 +126,7 @@
</div>
{% endif %}
{% if all_submissions | length %}
{% if quiz.show_submission_history and all_submissions | length %}
<article class="mt-8">
<div class="field-label">
{{ _("All Submissions") }}
@@ -131,9 +135,9 @@
<div class="grid-heading-row">
<div class="grid-row">
<div class="data-row row">
<div class="col grid-static-col">{{ _("No.") }}</div>
<div class="col grid-static-col">{{ _("Date") }}</div>
<div class="col grid-static-col col-xs-1">{{ _("No.") }}</div>
<div class="col grid-static-col text-right">{{ _("Score") }}</div>
<div class="col grid-static-col">{{ _("Date") }}</div>
</div>
</div>
</div>
@@ -141,9 +145,11 @@
{% for submission in all_submissions %}
<div class="grid-row">
<div class="data-row row">
<div class="col grid-static-col">{{ loop.index }}</div>
<div class="col grid-static-col">{{ frappe.utils.format_datetime(submission.creation, "medium") }}</div>
<div class="col grid-static-col col-xs-1">{{ loop.index }}</div>
<div class="col grid-static-col text-right">{{ submission.score }}</div>
<div class="col grid-static-col" title="{{ frappe.utils.format_datetime(submission.creation, "medium") }}">
{{ frappe.utils.pretty_date(submission.creation) }}
</div>
</div>
</div>
{% endfor %}

View File

@@ -1,8 +1,9 @@
frappe.ready(() => {
const self = this;
this.quiz_submitted = false;
this.answer = [];
this.is_correct = [];
const self = this;
this.show_answers = $("#quiz-title").data("show-answers");
localStorage.removeItem($("#quiz-title").data("name"));
$(".btn-start-quiz").click((e) => {
@@ -21,8 +22,11 @@ frappe.ready(() => {
$("#summary").click((e) => {
e.preventDefault();
add_to_local_storage();
quiz_summary(e);
if (!this.show_answers) check_answer();
setTimeout(() => {
quiz_summary(e);
}, 500);
});
$("#check").click((e) => {
@@ -32,7 +36,8 @@ frappe.ready(() => {
$("#next").click((e) => {
e.preventDefault();
add_to_local_storage();
if (!this.show_answers) check_answer();
mark_active_question(e);
});
@@ -42,21 +47,30 @@ frappe.ready(() => {
});
const mark_active_question = (e = undefined) => {
$(".timer").addClass("hide");
calculate_and_display_time(100);
$(".timer").removeClass("hide");
let total_questions = $(".question").length;
let current_index = $(".active-question").attr("data-qt-index") || 0;
let next_index = parseInt(current_index) + 1;
if (this.show_answers) {
$("#next").addClass("hide");
} else if (!this.show_answers && next_index == total_questions) {
$("#next").addClass("hide");
$("#summary").removeClass("hide");
}
$(".question").addClass("hide").removeClass("active-question");
$(`.question[data-qt-index='${next_index}']`)
.removeClass("hide")
.addClass("active-question");
$(".current-question").text(`${next_index}`);
$("#check").removeClass("hide").attr("disabled", true);
$("#next").addClass("hide");
$("#next").attr("disabled", true);
$(".explanation").addClass("hide");
$(".timer").addClass("hide");
calculate_and_display_time(100);
$(".timer").removeClass("hide");
initialize_timer();
};
@@ -95,6 +109,7 @@ const initialize_timer = () => {
const enable_check = (e) => {
if ($(".option:checked").length || $(".possibility").val().trim()) {
$("#check").removeAttr("disabled");
$("#next").removeAttr("disabled");
$(".custom-checkbox").removeClass("active-option");
$(".option:checked")
.closest(".custom-checkbox")
@@ -145,8 +160,10 @@ const try_quiz_again = (e) => {
const check_answer = (e = undefined) => {
e && e.preventDefault();
let answer = $(".active-question textarea");
let total_questions = $(".question").length;
let current_index = $(".active-question").attr("data-qt-index");
if (answer.length && !answer.val().trim()) {
frappe.throw(__("Please enter your answer"));
}
@@ -154,73 +171,77 @@ const check_answer = (e = undefined) => {
clearInterval(self.timer);
$(".timer").addClass("hide");
let total_questions = $(".question").length;
let current_index = $(".active-question").attr("data-qt-index");
$(".explanation").removeClass("hide");
$("#check").addClass("hide");
if (current_index == total_questions) {
$("#summary").removeClass("hide");
} else {
} else if (this.show_answers) {
$("#next").removeClass("hide");
}
parse_options();
};
const parse_options = () => {
let user_answers = [];
let element;
let type = $(".active-question").data("type");
if (type == "Choices") {
$(".active-question input").each((i, element) => {
is_answer_correct(type, element);
if ($(element).prop("checked")) {
user_answers.push(decodeURIComponent($(element).val()));
}
});
element = $(".active-question input");
} else {
is_answer_correct(type, $(".active-question textarea"));
user_answers.push($(".active-question textarea").val());
element = $(".active-question textarea");
}
is_answer_correct(type, user_answers, element);
};
const is_answer_correct = (type, element) => {
let answer = decodeURIComponent($(element).val());
const is_answer_correct = (type, user_answers, element) => {
frappe.call({
async: false,
method: "lms.lms.doctype.lms_quiz.lms_quiz.check_answer",
args: {
question: $(".active-question").data("name"),
type: type,
answer: answer,
answers: user_answers,
},
callback: (data) => {
type == "Choices"
? parse_choices(element, data.message)
: parse_possible_answers(element, data.message);
add_to_local_storage();
},
});
};
const parse_choices = (element, correct) => {
if ($(element).prop("checked")) {
self.answer.push(decodeURIComponent($(element).val()));
correct && self.is_correct.push(1);
correct ? add_icon(element, "check") : add_icon(element, "wrong");
} else {
correct && self.is_correct.push(0);
correct
? add_icon(element, "minus-circle-green")
: add_icon(element, "minus-circle");
}
const parse_choices = (element, is_correct) => {
element.each((i, elem) => {
if ($(elem).prop("checked")) {
self.answer.push(decodeURIComponent($(elem).val()));
self.is_correct.push(is_correct[i]);
if (this.show_answers)
is_correct[i]
? add_icon(elem, "check")
: add_icon(elem, "wrong");
} else {
add_icon(elem, "minus-circle");
}
});
};
const parse_possible_answers = (element, correct) => {
self.answer.push(decodeURIComponent($(element).val()));
if (correct) {
self.is_correct.push(1);
show_indicator("success", element);
} else {
self.is_correct.push(0);
show_indicator("failure", element);
}
self.is_correct.push(correct);
if (this.show_answers)
correct
? show_indicator("success", element)
: show_indicator("failure", element);
};
const show_indicator = (class_name, element) => {
@@ -253,7 +274,7 @@ const add_to_local_storage = () => {
let quiz_stored = JSON.parse(localStorage.getItem(quiz_name));
let quiz_obj = {
question_index: current_index,
question_index: current_index - 1,
answer: self.answer.join(),
is_correct: self.is_correct,
};