diff --git a/community/lms/doctype/chapter/chapter.py b/community/lms/doctype/chapter/chapter.py index fb201a4c..b616de2c 100644 --- a/community/lms/doctype/chapter/chapter.py +++ b/community/lms/doctype/chapter/chapter.py @@ -10,6 +10,6 @@ class Chapter(Document): def get_lessons(self): rows = frappe.db.get_all("Lesson", filters={"chapter": self.name}, - fields='*', + fields='name', order_by="index_") - return [frappe.get_doc(dict(row, doctype='Lesson')) for row in rows] + return [frappe.get_doc('Lesson', row['name']) for row in rows] diff --git a/community/lms/doctype/exercise/exercise.json b/community/lms/doctype/exercise/exercise.json index 33c7151e..e7f0ea7c 100644 --- a/community/lms/doctype/exercise/exercise.json +++ b/community/lms/doctype/exercise/exercise.json @@ -15,7 +15,9 @@ "hints", "tests", "image", - "lesson" + "lesson", + "index_", + "index_label" ], "fields": [ { @@ -27,6 +29,7 @@ { "fieldname": "course", "fieldtype": "Link", + "in_list_view": 1, "label": "Course", "options": "LMS Course" }, @@ -73,13 +76,27 @@ { "fieldname": "lesson", "fieldtype": "Link", + "in_list_view": 1, "label": "Lesson", "options": "Lesson" + }, + { + "fieldname": "index_", + "fieldtype": "Int", + "label": "Index", + "read_only": 1 + }, + { + "fieldname": "index_label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Index Label", + "read_only": 1 } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-05-20 13:23:12.340928", + "modified": "2021-06-01 05:22:15.656013", "modified_by": "Administrator", "module": "LMS", "name": "Exercise", @@ -99,8 +116,8 @@ } ], "search_fields": "title", - "sort_field": "modified", - "sort_order": "DESC", + "sort_field": "index_label", + "sort_order": "ASC", "title_field": "title", "track_changes": 1 } \ No newline at end of file diff --git a/community/lms/doctype/exercise/exercise.py b/community/lms/doctype/exercise/exercise.py index 151b993a..dde6b273 100644 --- a/community/lms/doctype/exercise/exercise.py +++ b/community/lms/doctype/exercise/exercise.py @@ -25,7 +25,6 @@ class Exercise(Document): order_by="creation desc", page_length=1) - print("get_user_submission", result) if result: return result[0] diff --git a/community/lms/doctype/lesson/lesson.json b/community/lms/doctype/lesson/lesson.json index 2dbe6c92..4772b255 100644 --- a/community/lms/doctype/lesson/lesson.json +++ b/community/lms/doctype/lesson/lesson.json @@ -10,6 +10,7 @@ "lesson_type", "title", "index_", + "index_label", "body", "sections" ], @@ -51,11 +52,18 @@ "fieldtype": "Table", "label": "Sections", "options": "LMS Section" + }, + { + "fieldname": "index_label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Index Label", + "read_only": 1 } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-05-13 20:03:51.510605", + "modified": "2021-06-01 05:30:48.127494", "modified_by": "Administrator", "module": "LMS", "name": "Lesson", diff --git a/community/lms/doctype/lesson/lesson.py b/community/lms/doctype/lesson/lesson.py index 979515ea..3358dbe0 100644 --- a/community/lms/doctype/lesson/lesson.py +++ b/community/lms/doctype/lesson/lesson.py @@ -16,10 +16,28 @@ class Lesson(Document): e = s.get_exercise() e.lesson = self.name e.save() + self.update_orphan_exercises() + + def update_orphan_exercises(self): + """Updates the exercises that were previously part of this lesson, + but not any more. + """ + linked_exercises = {row['name'] for row in frappe.get_all('Exercise', {"lesson": self.name})} + active_exercises = {s.id for s in self.get("sections") if s.type=="exercise"} + orphan_exercises = linked_exercises - active_exercises + for name in orphan_exercises: + ex = frappe.get_doc("Exercise", name) + ex.lesson = None + ex.index_ = 0 + ex.index_label = "" + ex.save() def get_sections(self): return sorted(self.get('sections'), key=lambda s: s.index) + def get_exercises(self): + return [frappe.get_doc("Exercise", s.id) for s in self.get("sections") if s.type=="exercise"] + def make_lms_section(self, index, section): s = frappe.new_doc('LMS Section', parent_doc=self, parentfield='sections') s.type = section.type diff --git a/community/lms/doctype/lms_course/lms_course.json b/community/lms/doctype/lms_course/lms_course.json index 41f4de73..187a24e1 100644 --- a/community/lms/doctype/lms_course/lms_course.json +++ b/community/lms/doctype/lms_course/lms_course.json @@ -1,5 +1,18 @@ { - "actions": [], + "actions": [ + { + "action": "community.lms.doctype.lms_course.lms_course.reindex_lessons", + "action_type": "Server Action", + "group": "Reindex", + "label": "Reindex Lessons" + }, + { + "action": "community.lms.doctype.lms_course.lms_course.reindex_exercises", + "action_type": "Server Action", + "group": "Reindex", + "label": "Reindex Exercises" + } + ], "allow_guest_to_view": 1, "allow_rename": 1, "creation": "2021-03-01 16:49:33.622422", @@ -86,7 +99,7 @@ "link_fieldname": "course" } ], - "modified": "2021-05-23 18:14:32.602647", + "modified": "2021-06-01 04:36:45.696776", "modified_by": "Administrator", "module": "LMS", "name": "LMS Course", diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index f72264ba..b3d08ef9 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +import json from ...utils import slugify from community.query import find, find_all @@ -157,6 +158,35 @@ class LMSCourse(Document): chapter = frappe.get_doc("Chapter", lesson.chapter) return f"{chapter.index_}.{lesson.index_}" + def reindex_lessons(self): + for i, c in enumerate(self.get_chapters(), start=1): + c.index_ = i + c.save() + self._reindex_lessons_in_chapter(c) + + def _reindex_lessons_in_chapter(self, c): + for i, lesson in enumerate(c.get_lessons(), start=1): + lesson.index = i + lesson.index_label = f"{c.index_}.{i}" + lesson.save() + + def reindex_exercises(self): + for i, c in enumerate(self.get_chapters(), start=1): + if c.index_ != i: + c.index_ = i + c.save() + self._reindex_exercises_in_chapter(c) + + def _reindex_exercises_in_chapter(self, c): + i = 1 + for lesson in c.get_lessons(): + for exercise in lesson.get_exercises(): + exercise.index_ = i + exercise.index_label = f"{c.index_}.{i}" + exercise.save() + i += 1 + + def get_outline(self): return CourseOutline(self) @@ -187,7 +217,8 @@ class CourseOutline: def get_chapters(self): return frappe.db.get_all("Chapter", filters={"course": self.course.name}, - fields=["name", "title", "index_"]) + fields=["name", "title", "index_"], + order_by="index_") def get_lessons(self): chapters = [c['name'] for c in self.chapters] @@ -199,3 +230,17 @@ class CourseOutline: for lesson in lessons: lesson['number'] = "{}.{}".format(chapter_numbers[lesson['chapter']], lesson['index_']) return lessons + +@frappe.whitelist() +def reindex_lessons(doc): + course_data = json.loads(doc) + course = frappe.get_doc("LMS Course", course_data['name']) + course.reindex_lessons() + frappe.msgprint("All lessons in this course have been re-indexed.") + +@frappe.whitelist() +def reindex_exercises(doc): + course_data = json.loads(doc) + course = frappe.get_doc("LMS Course", course_data['name']) + course.reindex_exercises() + frappe.msgprint("All exercises in this course have been re-indexed.") diff --git a/community/lms/widgets/Exercise.html b/community/lms/widgets/Exercise.html index 1dbaecfa..04361609 100644 --- a/community/lms/widgets/Exercise.html +++ b/community/lms/widgets/Exercise.html @@ -1,7 +1,7 @@ {% from "www/macros/livecode.html" import LiveCodeEditorJS, LiveCodeEditor with context %}
-

{{ exercise.title }}

+

Exercise {{exercise.index_label}}: {{ exercise.title }}

{{frappe.utils.md_to_html(exercise.description)}}
{% if exercise.image %} diff --git a/community/www/batch/progress.html b/community/www/batch/progress.html index 2083f046..983077b1 100644 --- a/community/www/batch/progress.html +++ b/community/www/batch/progress.html @@ -29,7 +29,7 @@

Batch Progress

{% for exercise in report.exercises %}
-

{{exercise.title}}

+

Exercise {{exercise.index_label}}: {{exercise.title}}

{% for s in report.get_submissions_of_exercise(exercise.name) %}

{{s.owner.full_name}}

diff --git a/community/www/batch/progress.py b/community/www/batch/progress.py index 5556d03d..adfb72dd 100644 --- a/community/www/batch/progress.py +++ b/community/www/batch/progress.py @@ -25,7 +25,7 @@ class BatchReport: self.submissions_by_exercise[s.exercise].append(s) def get_exercises(self, course_name): - return frappe.get_all("Exercise", {"course": course_name}, ["name", "title"]) + return frappe.get_all("Exercise", {"course": course_name, "lesson": ["!=", ""]}, ["name", "title", "index_label"], order_by="index_label") def get_submissions_of_exercise(self, exercise_name): return self.submissions_by_exercise[exercise_name]