test: fixed course creation test
This commit is contained in:
@@ -59,12 +59,6 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</header>
|
||||
{% endmacro %}
|
||||
|
||||
+36
-1
@@ -122,7 +122,6 @@ const parse_lesson_to_string = (data) => {
|
||||
? `{{ Video("${url}") }}\n`
|
||||
: ``;
|
||||
} else if (block.type == "header") {
|
||||
console.log(block);
|
||||
lesson_content +=
|
||||
"#".repeat(block.data.level) + ` ${block.data.text}\n`;
|
||||
} else if (block.type == "paragraph") {
|
||||
@@ -133,6 +132,7 @@ const parse_lesson_to_string = (data) => {
|
||||
};
|
||||
|
||||
const save = (lesson_content) => {
|
||||
validate_mandatory(lesson_content);
|
||||
let lesson = $("#lesson-title").data("lesson");
|
||||
|
||||
frappe.call({
|
||||
@@ -157,6 +157,28 @@ const save = (lesson_content) => {
|
||||
});
|
||||
};
|
||||
|
||||
const validate_mandatory = (lesson_content) => {
|
||||
if (!$("#lesson-title").val()) {
|
||||
let error = $("p")
|
||||
.addClass("error-message")
|
||||
.text(__("Please enter a Lesson Title"));
|
||||
$(error).insertAfter("#lesson-title");
|
||||
$("#lesson-title").focus();
|
||||
throw "Title is mandatory";
|
||||
}
|
||||
|
||||
if (!lesson_content.trim()) {
|
||||
let error = $("p")
|
||||
.addClass("error-message")
|
||||
.text(__("Please enter some content for the lesson"));
|
||||
$(error).insertAfter("#lesson-content");
|
||||
document
|
||||
.getElementById("lesson-content")
|
||||
.scrollIntoView({ block: "start" });
|
||||
throw "Lesson Content is mandatory";
|
||||
}
|
||||
};
|
||||
|
||||
const fetch_quiz_list = () => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_quiz.lms_quiz.get_user_quizzes",
|
||||
@@ -205,6 +227,19 @@ class YouTubeVideo {
|
||||
label: __("YouTube Video ID"),
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "instructions_section_break",
|
||||
fieldtype: "Section Break",
|
||||
label: __("Instructions:"),
|
||||
},
|
||||
{
|
||||
fieldname: "instructions",
|
||||
fieldtype: "HTML",
|
||||
label: __("Instructions"),
|
||||
options: __(
|
||||
"Enter the YouTube Video ID. The ID is the part of the URL after <code>watch?v=</code>. For example, if the URL is <code>https://www.youtube.com/watch?v=QH2-TGUlwu4</code>, the ID is <code>QH2-TGUlwu4</code>"
|
||||
),
|
||||
},
|
||||
],
|
||||
primary_action_label: __("Insert"),
|
||||
primary_action(values) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
frappe.ready(() => {
|
||||
this.marked_as_complete = false;
|
||||
this.quiz_submitted = false;
|
||||
this.file_type;
|
||||
this.answer = [];
|
||||
this.is_correct = [];
|
||||
let self = this;
|
||||
@@ -12,8 +11,6 @@ frappe.ready(() => {
|
||||
|
||||
save_current_lesson();
|
||||
|
||||
set_file_type();
|
||||
|
||||
$(".option").click((e) => {
|
||||
enable_check(e);
|
||||
});
|
||||
@@ -64,14 +61,6 @@ frappe.ready(() => {
|
||||
clear_work(e);
|
||||
});
|
||||
|
||||
$(".btn-lesson").click((e) => {
|
||||
save_lesson(e);
|
||||
});
|
||||
|
||||
$(".add-attachment").click((e) => {
|
||||
show_upload_modal();
|
||||
});
|
||||
|
||||
$(".btn-start-quiz").click((e) => {
|
||||
$("#start-banner").addClass("hide");
|
||||
$("#quiz-form").removeClass("hide");
|
||||
@@ -95,16 +84,6 @@ frappe.ready(() => {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($("#body").length) {
|
||||
make_editor();
|
||||
}
|
||||
|
||||
$("#file-type").change((e) => {
|
||||
$("#file-type option:selected").each(function () {
|
||||
self.file_type = $(this).val();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const save_current_lesson = () => {
|
||||
@@ -522,98 +501,3 @@ const calculate_and_display_time = (percent_time) => {
|
||||
let progress_color = percent_time < 20 ? "red" : "var(--primary-color)";
|
||||
$(".timer .progress-bar").css("background-color", progress_color);
|
||||
};
|
||||
|
||||
const save_lesson = (e) => {
|
||||
let lesson = $("#title").data("lesson");
|
||||
let self = this;
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.save_lesson",
|
||||
args: {
|
||||
title: $("#title").text(),
|
||||
body: this.code_field_group.fields_dict["code_md"].value,
|
||||
youtube: $("#youtube").text(),
|
||||
quiz_id: $("#quiz-id").text(),
|
||||
chapter: $("#title").data("chapter"),
|
||||
preview: $("#preview").prop("checked") ? 1 : 0,
|
||||
idx: $("#title").data("index"),
|
||||
lesson: lesson ? lesson : "",
|
||||
question: $("#assignment-question").text(),
|
||||
file_type: self.file_type,
|
||||
},
|
||||
callback: (data) => {
|
||||
frappe.show_alert({
|
||||
message: __("Saved"),
|
||||
indicator: "green",
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = window.location.href.split("?")[0];
|
||||
}, 1000);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const show_upload_modal = () => {
|
||||
new frappe.ui.FileUploader({
|
||||
folder: "Home/Attachments",
|
||||
restrictions: {
|
||||
allowed_file_types: ["image/*", "video/*"],
|
||||
},
|
||||
on_success: (file_doc) => {
|
||||
$(".attachments").append(build_attachment_table(file_doc));
|
||||
let count = $(".attachment-count").data("count") + 1;
|
||||
$(".attachment-count").data("count", count);
|
||||
$(".attachment-count").html(__(`${count} attachments`));
|
||||
$(".attachments").removeClass("hide");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const build_attachment_table = (file_doc) => {
|
||||
let video_types = ["mov", "mp4", "mkv"];
|
||||
let video_extension = file_doc.file_url.split(".").pop();
|
||||
let is_video = video_types.indexOf(video_extension) >= 0;
|
||||
let link = is_video
|
||||
? `{{ Video('${file_doc.file_url}') }}`
|
||||
: ``;
|
||||
|
||||
return $(`
|
||||
<tr class="attachment-row">
|
||||
<td>${file_doc.file_name}</td>
|
||||
<td class="">
|
||||
<a class="button is-secondary button-links copy-link" data-link="${link}"
|
||||
data-name="${file_doc.file_name}" > ${__("Copy Link")}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
};
|
||||
|
||||
const make_editor = () => {
|
||||
/* this.code_field_group = new frappe.ui.FieldGroup({
|
||||
fields: [
|
||||
{
|
||||
fieldname: "code_md",
|
||||
fieldtype: "Text Editor",
|
||||
default: $(".body-data").html(),
|
||||
},
|
||||
],
|
||||
body: $("#body").get(0),
|
||||
});
|
||||
this.code_field_group.make();
|
||||
$("#body .form-section:last").removeClass("empty-section");
|
||||
$("#body .frappe-control").removeClass("hide-control");
|
||||
$("#body .form-column").addClass("p-0"); */
|
||||
};
|
||||
|
||||
const set_file_type = () => {
|
||||
let self = this;
|
||||
let file_type = $("#file-type").data("type");
|
||||
if (file_type) {
|
||||
$("#file-type option").each((i, elem) => {
|
||||
if ($(elem).val() == file_type) {
|
||||
$(elem).attr("selected", true);
|
||||
self.file_type = file_type;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
+99
-88
@@ -1,6 +1,6 @@
|
||||
{% extends "templates/base.html" %}
|
||||
{% block title %}
|
||||
{{ _("Quiz List") }}
|
||||
{{ quiz.title if quiz.name else _("Quiz Details") }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -8,11 +8,25 @@
|
||||
<div class="common-page-style">
|
||||
{{ Header() }}
|
||||
<div class="container form-width">
|
||||
{{ QuizCard(quiz) }}
|
||||
{{ QuizForm(quiz) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% macro QuizForm(quiz) %}
|
||||
<div>
|
||||
{{ QuizDetails(quiz) }}
|
||||
{% if quiz.questions %}
|
||||
{% for question in quiz.questions %}
|
||||
{{ Question(question, loop.index) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<div id="question-template" class="hide">
|
||||
{{ Question({}, 0) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro Header() %}
|
||||
<header class="sticky">
|
||||
<div class="container form-width">
|
||||
@@ -30,104 +44,101 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary btn-sm btn-save-question align-self-center">
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<div class="align-self-center">
|
||||
<button class="btn btn-default btn-sm btn-add-question">
|
||||
{{ _("Add Question") }}
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm btn-save-question">
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro QuizCard(quiz) %}
|
||||
<div>
|
||||
|
||||
<div class="field-parent">
|
||||
<div class="field-group">
|
||||
<div>
|
||||
<div class="field-label">
|
||||
{{ _("Title") }}
|
||||
</div>
|
||||
<div class="field-description">
|
||||
{{ _("Give your quiz a title") }}
|
||||
</div>
|
||||
{% macro QuizDetails(quiz) %}
|
||||
<div class="field-parent">
|
||||
<div class="field-group">
|
||||
<div>
|
||||
<div class="field-label">
|
||||
{{ _("Title") }}
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="text" class="field-input" id="quiz-title" {% if quiz.name %} value="{{ quiz.title }}" data-name="{{ quiz.name }}" {% endif %}>
|
||||
<div class="field-description">
|
||||
{{ _("Give your quiz a title") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if quiz.questions %}
|
||||
{% for question in quiz.questions %}
|
||||
<div class="common-card-style column-card field-parent">
|
||||
<div class="field-group">
|
||||
<div>
|
||||
<div class="field-label">
|
||||
{{ _("Question") }} {{ loop.index }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="text" class="field-input question" {% if question.name %} value="{{ question.question }}" data-question="{{ question.name }}" {% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-group">
|
||||
<div class="vertically-center justify-content-between">
|
||||
<div class="field-label">
|
||||
{{ _("Question Type") }}
|
||||
</div>
|
||||
<div class="btn-group btn-group-toggle type align-self-center" data-toggle="buttons">
|
||||
<label class="btn btn-default btn-sm active question-type">
|
||||
<input type="radio" name="type-{{ loop.index }}" data-type="Choices" {% if question.type == "Choices" %} checked {% endif %}>
|
||||
{{ _("Choices") }}
|
||||
</label>
|
||||
<label class="btn btn-default btn-sm question-type">
|
||||
<input type="radio" name="type-{{ loop.index }}" data-type="User Input" {% if question.type == "User Input" %} checked {% endif %}>
|
||||
{{ _("User Input") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
|
||||
{% for i in range(1,5) %}
|
||||
{% set num = frappe.utils.cstr(i) %}
|
||||
|
||||
{% set option = question["option_" + num] %}
|
||||
{% set explanation = question["explanation_" + num] %}
|
||||
{% set possible_answer = question["possibility_" + num] %}
|
||||
|
||||
<div class="field-group">
|
||||
|
||||
<div class="options-group {% if question.type == 'User Input' %} hide {% endif %}">
|
||||
<input type="text" placeholder="Option" class="field-input option-{{ num }}" {% if option %} value="{{ option }}" {% endif %}>
|
||||
<input type="text" placeholder="Explanation" class="field-input explanation-{{ num }}" {% if explanation %} value="{{ explanation }}" {% endif %}>
|
||||
<label class="vertically-center mt-1">
|
||||
<input type="checkbox" class="correct-{{ num }}" {% if question['is_correct_' + num] %} checked {% endif %}>
|
||||
{{ _("Is Correct") }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="answers-group {% if question.type == 'Choices' %} hide {% endif %}">
|
||||
<div class="field-label">
|
||||
{{ _("Possible Answers") }} {{ num }}
|
||||
</div>
|
||||
<textarea class="field-input possibility-{{ num }}"
|
||||
style="height: 100px;">{% if possible_answer %}{{ possible_answer }}{% endif %}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
<input type="text" class="field-input" id="quiz-title" {% if quiz.name %} value="{{ quiz.title }}" data-name="{{ quiz.name }}" {% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro Question(question, index) %}
|
||||
{% set type = question.type if question.type else "Choices" %}
|
||||
<div class="common-card-style column-card field-parent question-card" data-index="{{ index }}">
|
||||
<div class="field-group">
|
||||
<div>
|
||||
<div class="field-label question-label">
|
||||
{{ _("Question") }} {{ index }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<input type="text" class="field-input question" {% if question.name %} value="{{ question.question }}" data-question="{{ question.name }}" {% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-group">
|
||||
<div class="vertically-center justify-content-between">
|
||||
<div class="field-label">
|
||||
{{ _("Question Type") }}
|
||||
</div>
|
||||
<div class="btn-group btn-group-toggle type align-self-center" data-toggle="buttons">
|
||||
<label class="btn btn-default btn-sm active question-type">
|
||||
<input type="radio" name="type-{{ index }}" data-type="Choices" {% if type == "Choices" %} checked {% endif %}>
|
||||
{{ _("Choices") }}
|
||||
</label>
|
||||
<label class="btn btn-default btn-sm question-type">
|
||||
<input type="radio" name="type-{{ index }}" data-type="User Input" {% if type == "User Input" %} checked {% endif %}>
|
||||
{{ _("User Input") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
|
||||
{% for i in range(1,5) %}
|
||||
{% set num = frappe.utils.cstr(i) %}
|
||||
|
||||
{% set option = question["option_" + num] %}
|
||||
{% set explanation = question["explanation_" + num] %}
|
||||
{% set possible_answer = question["possibility_" + num] %}
|
||||
|
||||
<div class="field-group">
|
||||
|
||||
<div class="options-group {% if type == 'User Input' %} hide {% endif %}">
|
||||
<input type="text" placeholder="Option" class="field-input option-{{ num }}" {% if option %} value="{{ option }}" {% endif %}>
|
||||
<input type="text" placeholder="Explanation" class="field-input explanation-{{ num }}" {% if explanation %} value="{{ explanation }}" {% endif %}>
|
||||
<label class="vertically-center mt-1">
|
||||
<input type="checkbox" class="correct-{{ num }}" {% if question['is_correct_' + num] %} checked {% endif %}>
|
||||
{{ _("Is Correct") }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="answers-group {% if type == 'Choices' %} hide {% endif %}">
|
||||
<div class="field-label">
|
||||
{{ _("Possible Answers") }} {{ num }}
|
||||
</div>
|
||||
<textarea class="field-input possibility-{{ num }}"
|
||||
style="height: 100px;">{% if possible_answer %}{{ possible_answer }}{% endif %}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
+23
-70
@@ -1,6 +1,10 @@
|
||||
frappe.ready(() => {
|
||||
$(".btn-question").click((e) => {
|
||||
if ($(".question-card").length <= 1) {
|
||||
add_question();
|
||||
}
|
||||
|
||||
$(".btn-add-question").click((e) => {
|
||||
add_question(true);
|
||||
});
|
||||
|
||||
$(".btn-save-question").click((e) => {
|
||||
@@ -11,7 +15,7 @@ frappe.ready(() => {
|
||||
frappe.utils.copy_to_clipboard($(e.currentTarget).data("name"));
|
||||
});
|
||||
|
||||
$(".question-type").click((e) => {
|
||||
$(document).on("click", ".question-type", (e) => {
|
||||
toggle_form($(e.currentTarget));
|
||||
});
|
||||
|
||||
@@ -43,72 +47,21 @@ const toggle_form = (el) => {
|
||||
}
|
||||
};
|
||||
|
||||
const add_question = () => {
|
||||
let add_after = $(".quiz-card").length
|
||||
? $(".quiz-card:last")
|
||||
: $("#quiz-title");
|
||||
let question_template = `<div class="quiz-card new-quiz-card">
|
||||
<div contenteditable="true" data-placeholder="${__(
|
||||
"Question"
|
||||
)}" class="question mb-4"></div>
|
||||
<select value="{{ question.type }}" class="input-with-feedback form-control ellipsis type" maxlength="140" data-fieldtype="Select" data-fieldname="type" placeholder="" data-doctype="LMS Quiz Question">
|
||||
<option value="Choices"> ${__("Choices")} </option>
|
||||
<option value="User Input"> ${__("User Input")} </option>
|
||||
</select>
|
||||
</div>`;
|
||||
$(question_template).insertAfter(add_after);
|
||||
get_question_template();
|
||||
$(".btn-save-question").removeClass("hide");
|
||||
const add_question = (scroll = false) => {
|
||||
let template = $("#question-template").html();
|
||||
let index = $(".question-card:nth-last-child(2)").data("index") + 1 || 1;
|
||||
template = update_index(template, index);
|
||||
|
||||
$(template).insertBefore($("#question-template"));
|
||||
scroll && scroll_to_question_container();
|
||||
};
|
||||
|
||||
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()
|
||||
: $(".type:last");
|
||||
question_template = $(option_template).insertAfter(add_after);
|
||||
});
|
||||
|
||||
Array.from({ length: 4 }, (x, num) => {
|
||||
let possibility_template = get_possibility_template(num + 1);
|
||||
let add_after = $(".quiz-card:last .possibility-group").length
|
||||
? $(".quiz-card:last .possibility-group").last()
|
||||
: $(".quiz-card:last .option-group:last");
|
||||
question_template = $(possibility_template).insertAfter(add_after);
|
||||
});
|
||||
};
|
||||
|
||||
const get_possibility_template = (num) => {
|
||||
return `<div class="possibility-group mt-4 hide">
|
||||
<label class=""> ${__("Possible Answer")} ${num} </label>
|
||||
<div class="control-input-wrapper">
|
||||
<div class="control-input">
|
||||
<div contenteditable="true" class="input-with-feedback form-control bold possibility-{{ num }}" style="height: 100px;" spellcheck="false"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
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 update_index = (template, index) => {
|
||||
const $template = $(template);
|
||||
$template.attr("data-index", index);
|
||||
$template.find(".question-label").text("Question " + index);
|
||||
$template.find(".question-type input").attr("name", "type-" + index);
|
||||
return $template.prop("outerHTML");
|
||||
};
|
||||
|
||||
const save_question = (e) => {
|
||||
@@ -124,7 +77,7 @@ const save_question = (e) => {
|
||||
quiz: $("#quiz-title").data("name") || "",
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.reload();
|
||||
window.location.href = `/quizzes/${data.message}`;
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -203,15 +156,15 @@ const validate_mandatory = (details, correct_options, possibilities) => {
|
||||
};
|
||||
|
||||
const scroll_to_question_container = () => {
|
||||
scroll_to_element(".new-quiz-card:last");
|
||||
$(".new-quiz-card").find(".question").focus();
|
||||
scroll_to_element(".question-card:nth-last-child(2)");
|
||||
$(".question-card:nth-last-child(2)").find(".question").focus();
|
||||
};
|
||||
|
||||
const scroll_to_element = (element) => {
|
||||
if ($(element).length)
|
||||
$([document.documentElement, document.body]).animate(
|
||||
{
|
||||
scrollTop: $(element).offset().top,
|
||||
scrollTop: $(element).offset().top - 100,
|
||||
},
|
||||
1000
|
||||
);
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="mt-5">
|
||||
<ul class="list-unstyled">
|
||||
{% for quiz in quiz_list %}
|
||||
<li>
|
||||
<li class="mt-2">
|
||||
<a class="clickable" href="/quizzes/{{ quiz.name }}">
|
||||
{{ quiz.title }}
|
||||
</a>
|
||||
@@ -58,22 +58,3 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
frappe.ready(() => {
|
||||
|
||||
$(".copy-quiz-id").click((e) => {
|
||||
e.preventDefault();
|
||||
frappe.utils.copy_to_clipboard($(e.currentTarget).data("name"));
|
||||
});
|
||||
|
||||
$(".quiz-row").click((e) => {
|
||||
if (!$(e.target).hasClass("copy-quiz-id")) {
|
||||
window.location.href = `/quizzes/${$(e.currentTarget).data('name')}`;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user