feat: record lesson progress
This commit is contained in:
@@ -5,6 +5,7 @@ import json
|
||||
import frappe
|
||||
import zipfile
|
||||
import os
|
||||
import shutil
|
||||
import xml.etree.ElementTree as ET
|
||||
from frappe.translate import get_all_translations
|
||||
from frappe import _
|
||||
@@ -883,38 +884,47 @@ def give_dicussions_permission():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_chapter(title, course, is_scorm_package, scorm_package):
|
||||
def upsert_chapter(title, course, is_scorm_package, scorm_package, name=None):
|
||||
values = frappe._dict(
|
||||
{"title": title, "course": course, "is_scorm_package": is_scorm_package}
|
||||
)
|
||||
|
||||
scorm_package = frappe._dict(scorm_package)
|
||||
if is_scorm_package:
|
||||
package = frappe.get_doc("File", scorm_package.name)
|
||||
zip_path = package.get_full_path()
|
||||
|
||||
# Extract the zip file
|
||||
extract_path = frappe.get_site_path("public", "files", "scorm", course, title)
|
||||
zipfile.ZipFile(zip_path).extractall(extract_path)
|
||||
scorm_package = frappe._dict(scorm_package)
|
||||
extract_path = extract_package(course, title, scorm_package)
|
||||
|
||||
values.update(
|
||||
{
|
||||
"scorm_package": scorm_package.name,
|
||||
"scorm_package_path": extract_path,
|
||||
"manifest_file": get_manifest_file(extract_path),
|
||||
"launch_file": get_launch_file(extract_path),
|
||||
"scorm_package_path": extract_path.split("public")[1],
|
||||
"manifest_file": get_manifest_file(extract_path).split("public")[1],
|
||||
"launch_file": get_launch_file(extract_path).split("public")[1],
|
||||
}
|
||||
)
|
||||
|
||||
chapter = frappe.new_doc("Course Chapter")
|
||||
print(values.title)
|
||||
if name:
|
||||
chapter = frappe.get_doc("Course Chapter", name)
|
||||
else:
|
||||
chapter = frappe.new_doc("Course Chapter")
|
||||
|
||||
chapter.update(values)
|
||||
print(chapter.title)
|
||||
chapter.insert()
|
||||
chapter.save()
|
||||
|
||||
if is_scorm_package and not len(chapter.lessons):
|
||||
add_lesson(title, chapter.name, course)
|
||||
|
||||
return chapter
|
||||
|
||||
|
||||
def extract_package(course, title, scorm_package):
|
||||
package = frappe.get_doc("File", scorm_package.name)
|
||||
zip_path = package.get_full_path()
|
||||
|
||||
extract_path = frappe.get_site_path("public", "files", "scorm", course, title)
|
||||
zipfile.ZipFile(zip_path).extractall(extract_path)
|
||||
return extract_path
|
||||
|
||||
|
||||
def get_manifest_file(extract_path):
|
||||
manifest_file = None
|
||||
for root, dirs, files in os.walk(extract_path):
|
||||
@@ -930,16 +940,17 @@ def get_manifest_file(extract_path):
|
||||
def get_launch_file(extract_path):
|
||||
launch_file = None
|
||||
manifest_file = get_manifest_file(extract_path)
|
||||
print(extract_path)
|
||||
|
||||
if manifest_file:
|
||||
with open(manifest_file) as file:
|
||||
data = file.read()
|
||||
print(data)
|
||||
dom = parseString(data)
|
||||
resource = dom.getElementsByTagName("resource")
|
||||
for res in resource:
|
||||
if res.getAttribute("adlcp:scormtype") == "sco":
|
||||
if (
|
||||
res.getAttribute("adlcp:scormtype") == "sco"
|
||||
or res.getAttribute("adlcp:scormType") == "sco"
|
||||
):
|
||||
launch_file = res.getAttribute("href")
|
||||
break
|
||||
|
||||
@@ -947,3 +958,47 @@ def get_launch_file(extract_path):
|
||||
launch_file = os.path.join(os.path.dirname(manifest_file), launch_file)
|
||||
|
||||
return launch_file
|
||||
|
||||
|
||||
def add_lesson(title, chapter, course):
|
||||
lesson = frappe.new_doc("Course Lesson")
|
||||
lesson.update(
|
||||
{
|
||||
"title": title,
|
||||
"chapter": chapter,
|
||||
"course": course,
|
||||
}
|
||||
)
|
||||
lesson.insert()
|
||||
|
||||
lesson_reference = frappe.new_doc("Lesson Reference")
|
||||
lesson_reference.update(
|
||||
{
|
||||
"lesson": lesson.name,
|
||||
"parent": chapter,
|
||||
"parenttype": "Course Chapter",
|
||||
"parentfield": "lessons",
|
||||
}
|
||||
)
|
||||
lesson_reference.insert()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def delete_chapter(chapter):
|
||||
chapterInfo = frappe.db.get_value(
|
||||
"Course Chapter", chapter, ["is_scorm_package", "scorm_package_path"], as_dict=True
|
||||
)
|
||||
|
||||
if chapterInfo.is_scorm_package:
|
||||
delete_scorm_package(chapterInfo.scorm_package_path)
|
||||
|
||||
frappe.db.delete("Chapter Reference", {"chapter": chapter})
|
||||
frappe.db.delete("Lesson Reference", {"parent": chapter})
|
||||
frappe.db.delete("Course Lesson", {"chapter": chapter})
|
||||
frappe.db.delete("Course Chapter", chapter)
|
||||
|
||||
|
||||
def delete_scorm_package(scorm_package_path):
|
||||
scorm_package_path = frappe.get_site_path("public", scorm_package_path)
|
||||
if os.path.exists(scorm_package_path):
|
||||
shutil.rmtree(scorm_package_path)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"title",
|
||||
"column_break_3",
|
||||
"course",
|
||||
"course_title",
|
||||
"scorm_section",
|
||||
"is_scorm_package",
|
||||
"scorm_package",
|
||||
@@ -93,6 +94,13 @@
|
||||
"fieldtype": "Code",
|
||||
"label": "SCORM Package Path",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "course.title",
|
||||
"fieldname": "course_title",
|
||||
"fieldtype": "Data",
|
||||
"label": "Course Title",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
@@ -103,7 +111,7 @@
|
||||
"link_fieldname": "chapter"
|
||||
}
|
||||
],
|
||||
"modified": "2024-11-11 16:25:45.586160",
|
||||
"modified": "2024-11-15 12:03:31.370943",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "Course Chapter",
|
||||
@@ -123,17 +131,14 @@
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "LMS Student",
|
||||
"select": 1,
|
||||
"share": 1,
|
||||
"write": 1
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"search_fields": "title",
|
||||
|
||||
@@ -8,12 +8,18 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"chapter",
|
||||
"course",
|
||||
"column_break_4",
|
||||
"title",
|
||||
"include_in_preview",
|
||||
"index_label",
|
||||
"column_break_4",
|
||||
"chapter",
|
||||
"is_scorm_package",
|
||||
"course",
|
||||
"section_break_11",
|
||||
"content",
|
||||
"body",
|
||||
"column_break_cjmf",
|
||||
"instructor_content",
|
||||
"instructor_notes",
|
||||
"section_break_6",
|
||||
"youtube",
|
||||
"column_break_9",
|
||||
@@ -22,13 +28,7 @@
|
||||
"question",
|
||||
"column_break_15",
|
||||
"file_type",
|
||||
"section_break_11",
|
||||
"content",
|
||||
"body",
|
||||
"column_break_cjmf",
|
||||
"instructor_content",
|
||||
"instructor_notes",
|
||||
"help_section",
|
||||
"column_break_syza",
|
||||
"help"
|
||||
],
|
||||
"fields": [
|
||||
@@ -59,12 +59,6 @@
|
||||
"label": "Title",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "index_label",
|
||||
"fieldtype": "Data",
|
||||
"label": "Index Label",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -74,14 +68,7 @@
|
||||
"fieldname": "body",
|
||||
"fieldtype": "Markdown Editor",
|
||||
"ignore_xss_filter": 1,
|
||||
"label": "Body",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "help_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 1,
|
||||
"label": "Help"
|
||||
"label": "Body"
|
||||
},
|
||||
{
|
||||
"fieldname": "help",
|
||||
@@ -158,11 +145,23 @@
|
||||
"fieldname": "instructor_content",
|
||||
"fieldtype": "Text",
|
||||
"label": "Instructor Content"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_syza",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fetch_from": "chapter.is_scorm_package",
|
||||
"fieldname": "is_scorm_package",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is SCORM Package",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-10-08 11:04:54.748773",
|
||||
"modified": "2024-11-14 13:46:56.838659",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "Course Lesson",
|
||||
|
||||
@@ -52,7 +52,6 @@ class CourseLesson(Document):
|
||||
ex.lesson = None
|
||||
ex.course = None
|
||||
ex.index_ = 0
|
||||
ex.index_label = ""
|
||||
ex.save(ignore_permissions=True)
|
||||
|
||||
def check_and_create_folder(self):
|
||||
|
||||
@@ -1128,11 +1128,20 @@ def get_course_outline(course, progress=False):
|
||||
chapter_details = frappe.db.get_value(
|
||||
"Course Chapter",
|
||||
chapter.chapter,
|
||||
["name", "title", "is_scorm_package", "launch_file"],
|
||||
["name", "title", "is_scorm_package", "launch_file", "scorm_package"],
|
||||
as_dict=True,
|
||||
)
|
||||
chapter_details["idx"] = chapter.idx
|
||||
chapter_details.lessons = get_lessons(course, chapter_details, progress=progress)
|
||||
|
||||
if chapter_details.is_scorm_package:
|
||||
chapter_details.scorm_package = frappe.db.get_value(
|
||||
"File",
|
||||
chapter_details.scorm_package,
|
||||
["file_name", "file_size", "file_url"],
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
outline.append(chapter_details)
|
||||
return outline
|
||||
|
||||
@@ -1146,9 +1155,12 @@ def get_lesson(course, chapter, lesson):
|
||||
"Lesson Reference", {"parent": chapter_name, "idx": lesson}, "lesson"
|
||||
)
|
||||
lesson_details = frappe.db.get_value(
|
||||
"Course Lesson", lesson_name, ["include_in_preview", "title"], as_dict=1
|
||||
"Course Lesson",
|
||||
lesson_name,
|
||||
["include_in_preview", "title", "is_scorm_package"],
|
||||
as_dict=1,
|
||||
)
|
||||
if not lesson_details:
|
||||
if not lesson_details or lesson_details.is_scorm_package:
|
||||
return {}
|
||||
|
||||
membership = get_membership(course)
|
||||
|
||||
Reference in New Issue
Block a user