Merge pull request #607 from pateljannat/lesson-embed
feat: embeds in lesson
This commit is contained in:
@@ -295,6 +295,7 @@ lms_markdown_macro_renderers = {
|
|||||||
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
|
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
|
||||||
"Video": "lms.plugins.video_renderer",
|
"Video": "lms.plugins.video_renderer",
|
||||||
"Assignment": "lms.plugins.assignment_renderer",
|
"Assignment": "lms.plugins.assignment_renderer",
|
||||||
|
"Embed": "lms.plugins.embed_renderer",
|
||||||
}
|
}
|
||||||
|
|
||||||
# page_renderer to manage profile pages
|
# page_renderer to manage profile pages
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
"column_break_15",
|
"column_break_15",
|
||||||
"file_type",
|
"file_type",
|
||||||
"section_break_11",
|
"section_break_11",
|
||||||
"instructor_notes",
|
|
||||||
"body",
|
"body",
|
||||||
|
"instructor_notes",
|
||||||
"help_section",
|
"help_section",
|
||||||
"help"
|
"help"
|
||||||
],
|
],
|
||||||
@@ -135,13 +135,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "instructor_notes",
|
"fieldname": "instructor_notes",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text",
|
||||||
"label": "Instructor Notes"
|
"label": "Instructor Notes"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-08-31 11:11:22.034553",
|
"modified": "2023-08-31 21:47:06.314995",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Course Lesson",
|
"name": "Course Lesson",
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ def get_lesson_details(chapter):
|
|||||||
)
|
)
|
||||||
lesson_details.number = flt(f"{chapter.idx}.{row.idx}")
|
lesson_details.number = flt(f"{chapter.idx}.{row.idx}")
|
||||||
lesson_details.icon = get_lesson_icon(lesson_details.body)
|
lesson_details.icon = get_lesson_icon(lesson_details.body)
|
||||||
|
if lesson_details.instructor_notes:
|
||||||
|
lesson_details.instructor_notes = markdown_to_html(lesson_details.instructor_notes)
|
||||||
|
|
||||||
lessons.append(lesson_details)
|
lessons.append(lesson_details)
|
||||||
return lessons
|
return lessons
|
||||||
|
|||||||
@@ -155,6 +155,28 @@ def youtube_video_renderer(video_id):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def embed_renderer(details):
|
||||||
|
type = details.split("|||")[0]
|
||||||
|
src = details.split("|||")[1]
|
||||||
|
width = "100%"
|
||||||
|
height = "400"
|
||||||
|
|
||||||
|
if type == "pdf":
|
||||||
|
width = "75%"
|
||||||
|
height = "600"
|
||||||
|
|
||||||
|
return f"""
|
||||||
|
<iframe width={width} height={height}
|
||||||
|
src={src}
|
||||||
|
title="Embedded Content"
|
||||||
|
frameborder="0"
|
||||||
|
style="border-radius: var(--border-radius-lg)"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen>
|
||||||
|
</iframe>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def video_renderer(src):
|
def video_renderer(src):
|
||||||
return (
|
return (
|
||||||
f"<video controls width='100%'><source src={quote(src)} type='video/mp4'></video>"
|
f"<video controls width='100%'><source src={quote(src)} type='video/mp4'></video>"
|
||||||
|
|||||||
@@ -2345,3 +2345,7 @@ select {
|
|||||||
grid-gap: 0.5rem;
|
grid-gap: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.embed-tool__caption {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@@ -128,5 +128,6 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph@latest"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,27 @@ const setup_editor = () => {
|
|||||||
self.editor = new EditorJS({
|
self.editor = new EditorJS({
|
||||||
holder: "lesson-content",
|
holder: "lesson-content",
|
||||||
tools: {
|
tools: {
|
||||||
|
embed: {
|
||||||
|
class: Embed,
|
||||||
|
config: {
|
||||||
|
services: {
|
||||||
|
youtube: true,
|
||||||
|
vimeo: true,
|
||||||
|
codepen: true,
|
||||||
|
slides: {
|
||||||
|
regex: /https:\/\/docs\.google\.com\/presentation\/d\/e\/([A-Za-z0-9_-]+)\/pub/,
|
||||||
|
embedUrl:
|
||||||
|
"https://docs.google.com/presentation/d/e/<%= remote_id %>/embed",
|
||||||
|
html: "<iframe width='100%' height='300' frameborder='0' allowfullscreen='true'></iframe>",
|
||||||
|
},
|
||||||
|
pdf: {
|
||||||
|
regex: /(https?:\/\/.*\.pdf)/,
|
||||||
|
embedUrl: "<%= remote_id %>",
|
||||||
|
html: "<iframe width='100%' height='600px' frameborder='0'></iframe>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
header: {
|
header: {
|
||||||
class: Header,
|
class: Header,
|
||||||
inlineToolbar: ["bold", "italic", "link"],
|
inlineToolbar: ["bold", "italic", "link"],
|
||||||
@@ -84,6 +105,15 @@ const parse_string_to_lesson = () => {
|
|||||||
file_url: video,
|
file_url: video,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else if (block.includes("{{ Embed")) {
|
||||||
|
let embed = block.match(/'([^']+)'/)[1];
|
||||||
|
lesson_blocks.push({
|
||||||
|
type: "embed",
|
||||||
|
data: {
|
||||||
|
service: embed.split("|||")[0],
|
||||||
|
embed: embed.split("|||")[1],
|
||||||
|
},
|
||||||
|
});
|
||||||
} else if (block.includes("![]")) {
|
} else if (block.includes("![]")) {
|
||||||
let image = block.match(/\((.*?)\)/)[1];
|
let image = block.match(/\((.*?)\)/)[1];
|
||||||
lesson_blocks.push({
|
lesson_blocks.push({
|
||||||
@@ -139,6 +169,15 @@ const parse_lesson_to_string = (data) => {
|
|||||||
"#".repeat(block.data.level) + ` ${block.data.text}\n`;
|
"#".repeat(block.data.level) + ` ${block.data.text}\n`;
|
||||||
} else if (block.type == "paragraph") {
|
} else if (block.type == "paragraph") {
|
||||||
lesson_content += `${block.data.text}\n`;
|
lesson_content += `${block.data.text}\n`;
|
||||||
|
} else if (block.type == "embed") {
|
||||||
|
if (block.data.service == "pdf") {
|
||||||
|
if (!block.data.embed.startsWith(window.location.origin)) {
|
||||||
|
frappe.throw(__("Invalid PDF URL"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lesson_content += `{{ Embed("${
|
||||||
|
block.data.service
|
||||||
|
}|||${block.data.embed.replace(/&/g, "&")}") }}\n`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
save(lesson_content);
|
save(lesson_content);
|
||||||
|
|||||||
@@ -157,7 +157,7 @@
|
|||||||
|
|
||||||
{% if lesson.instructor_notes and (is_moderator or instructor or is_evaluator) %}
|
{% if lesson.instructor_notes and (is_moderator or instructor or is_evaluator) %}
|
||||||
<div class="alert alert-info mb-4">
|
<div class="alert alert-info mb-4">
|
||||||
<div class="bold-heading">
|
<div class="bold-heading mb-2">
|
||||||
{{ _("Instructor Notes") }}
|
{{ _("Instructor Notes") }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user