feat: lesson editor youtube and quiz components
This commit is contained in:
@@ -140,6 +140,26 @@ textarea.field-input {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
.quiz-modal {
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.ce-block__content {
|
||||
max-width: 100%;
|
||||
padding: 0 0.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ce-toolbar__content {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.lesson-editor {
|
||||
border: 1px solid var(--gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
@@ -732,7 +752,7 @@ input[type=checkbox] {
|
||||
|
||||
.course-content-parent {
|
||||
display: grid;
|
||||
grid-gap: 2rem;
|
||||
grid-gap: 4rem;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="lesson-content"></div>
|
||||
<div class="field-group">
|
||||
<div>
|
||||
<div class="field-label">
|
||||
{{ _("Content") }}
|
||||
</div>
|
||||
<div class="field-description">
|
||||
{{ _("Add your lesson content here") }}
|
||||
</div>
|
||||
</div>
|
||||
<div id="lesson-content" class="lesson-editor"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</article>
|
||||
{% endmacro %}
|
||||
@@ -58,6 +69,21 @@
|
||||
|
||||
{%- block script %}
|
||||
{{ super() }}
|
||||
{% if is_moderator %}
|
||||
<script>
|
||||
frappe.boot.user = {
|
||||
"can_create": [],
|
||||
"can_select": ["LMS Quiz"],
|
||||
"can_read": ["LMS Quiz"]
|
||||
};
|
||||
|
||||
frappe.router = {
|
||||
slug (name) {
|
||||
return name.toLowerCase().replace(/ /g, "-");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
{{ include_script('controls.bundle.js') }}
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -20,10 +20,21 @@ const setup_editor = () => {
|
||||
|
||||
const save_lesson = (e) => {
|
||||
self.editor.save().then((outputData) => {
|
||||
console.log(outputData);
|
||||
parse_lesson(outputData);
|
||||
});
|
||||
};
|
||||
|
||||
const fetch_quiz_list = () => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_quiz.lms_quiz.get_user_quizzes",
|
||||
callback: (r) => {
|
||||
self.quiz_list = r.message;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const parse_lesson = (data) => {};
|
||||
|
||||
class YouTubeVideo {
|
||||
static get toolbox() {
|
||||
return {
|
||||
@@ -32,18 +43,39 @@ class YouTubeVideo {
|
||||
}
|
||||
|
||||
render() {
|
||||
let self = this;
|
||||
this.wrapper = document.createElement("div");
|
||||
$(this.wrapper).html(`<div class="field-group">
|
||||
<div class="">
|
||||
<input id="youtube" type="text" class="field-input">
|
||||
</div>
|
||||
</div>`);
|
||||
let youtubedialog = new frappe.ui.Dialog({
|
||||
title: __("YouTube Video"),
|
||||
fields: [
|
||||
{
|
||||
fieldname: "youtube",
|
||||
fieldtype: "Data",
|
||||
label: __("YouTube Video ID"),
|
||||
reqd: 1,
|
||||
},
|
||||
],
|
||||
primary_action_label: __("Insert"),
|
||||
primary_action(values) {
|
||||
youtubedialog.hide();
|
||||
self.youtube = values.youtube;
|
||||
$(self.wrapper).html(` <iframe width="100%" height="400"
|
||||
src="https://www.youtube.com/embed/${self.youtube}"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
style="border-radius: var(--border-radius-lg); margin: 1rem 0;"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen>
|
||||
</iframe>`);
|
||||
},
|
||||
});
|
||||
youtubedialog.show();
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
save(block_content) {
|
||||
return {
|
||||
youtube: $("#youtube").val(),
|
||||
youtube: this.youtube,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -57,28 +89,68 @@ class Quiz {
|
||||
|
||||
render() {
|
||||
this.wrapper = document.createElement("div");
|
||||
$(this.wrapper).html(
|
||||
`<div>
|
||||
<select id="quiz" class="field-input">
|
||||
<option value="">Select Quiz</option>
|
||||
</select>
|
||||
</div>`
|
||||
);
|
||||
self.quiz_list.forEach((quiz) => {
|
||||
$(this.wrapper)
|
||||
.find("#quiz")
|
||||
.append(`<option value="${quiz.name}">${quiz.title}</option>`);
|
||||
let self = this;
|
||||
let quizdialog = new frappe.ui.Dialog({
|
||||
title: __("Select a Quiz"),
|
||||
fields: [
|
||||
{
|
||||
fieldname: "quiz",
|
||||
fieldtype: "Link",
|
||||
label: __("Quiz"),
|
||||
reqd: 1,
|
||||
options: "LMS Quiz",
|
||||
},
|
||||
],
|
||||
primary_action_label: __("Insert"),
|
||||
primary_action(values) {
|
||||
self.quiz = values.quiz;
|
||||
quizdialog.hide();
|
||||
$(self.wrapper).html(
|
||||
`<div class="common-card-style p-2 my-2 bold-heading">
|
||||
Quiz: ${self.quiz}
|
||||
</div>`
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
quizdialog.show();
|
||||
setTimeout(() => {
|
||||
$(".modal-body").css("min-height", "300px");
|
||||
$(".modal-body input").focus();
|
||||
}, 1000);
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
save(block_content) {
|
||||
return {
|
||||
quiz: this.quiz,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const fetch_quiz_list = () => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_quiz.lms_quiz.get_user_quizzes",
|
||||
callback: (r) => {
|
||||
self.quiz_list = r.message;
|
||||
},
|
||||
});
|
||||
};
|
||||
class Video {
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
this.wrapper = document.createElement("div");
|
||||
let self = this;
|
||||
new frappe.ui.FileUploader({
|
||||
disable_file_browser: true,
|
||||
folder: "Home/Attachments",
|
||||
make_attachments_public: true,
|
||||
restrictions: {
|
||||
allowed_file_types: ["video/*"],
|
||||
},
|
||||
on_success: (file_doc) => {
|
||||
$(e.target)
|
||||
.parent()
|
||||
.siblings("img")
|
||||
.addClass("image-preview")
|
||||
.attr("src", file_doc.file_url);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import frappe
|
||||
from lms.www.utils import get_current_lesson_details, get_common_context
|
||||
from lms.lms.utils import is_instructor, has_course_moderator_role
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_context(context):
|
||||
@@ -8,3 +10,8 @@ def get_context(context):
|
||||
lesson_index = frappe.form_dict.get("lesson")
|
||||
lesson_number = f"{chapter_index}.{lesson_index}"
|
||||
context.lesson = get_current_lesson_details(lesson_number, context, True)
|
||||
context.is_moderator = has_course_moderator_role()
|
||||
instructor = is_instructor(context.course.name)
|
||||
|
||||
if not instructor and not has_course_moderator_role():
|
||||
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||
|
||||
Reference in New Issue
Block a user