From 1e3152e303cb8a977375d3d1a344f1c75a781b8e Mon Sep 17 00:00:00 2001 From: pateljannat Date: Thu, 10 Jun 2021 13:41:11 +0530 Subject: [PATCH 1/4] fix: ui --- community/hooks.py | 18 +++--- community/lms/doctype/chapter/chapter.py | 1 + community/lms/doctype/lesson/lesson.json | 11 +++- community/lms/doctype/lms_batch/lms_batch.py | 2 +- .../lms_batch_membership.py | 3 + .../lms/doctype/lms_course/lms_course.py | 7 ++- community/lms/models.py | 2 +- community/lms/widgets/BatchTabs.html | 18 +++--- community/lms/widgets/ChapterTeaser.html | 6 +- community/lms/widgets/CourseOutline.html | 10 ++-- community/lms/widgets/InstructorSection.html | 7 ++- community/public/css/style.css | 1 + community/public/css/style.less | 2 +- community/www/batch/home.html | 18 +++--- community/www/batch/learn.py | 9 ++- community/www/batch/members.html | 18 +++--- community/www/batch/progress.html | 2 +- community/www/batch/progress.py | 7 ++- community/www/batch/utils.py | 9 ++- community/www/courses/course.html | 58 +++++++++---------- community/www/courses/index.html | 10 ++-- community/www/hackathons/macros/card.html | 6 +- 22 files changed, 120 insertions(+), 105 deletions(-) diff --git a/community/hooks.py b/community/hooks.py index e6916c0b..150c88bc 100644 --- a/community/hooks.py +++ b/community/hooks.py @@ -136,15 +136,15 @@ primary_rules = [ {"from_route": "/hackathons//", "to_route": "hackathons/project"}, {"from_route": "/dashboard", "to_route": ""}, {"from_route": "/add-a-new-batch", "to_route": "add-a-new-batch"}, - {"from_route": "/courses///home", "to_route": "batch/home"}, - {"from_route": "/courses///learn", "to_route": "batch/learn"}, - {"from_route": "/courses///learn/.", "to_route": "batch/learn"}, - {"from_route": "/courses///schedule", "to_route": "batch/schedule"}, - {"from_route": "/courses///members", "to_route": "batch/members"}, - {"from_route": "/courses///discuss", "to_route": "batch/discuss"}, - {"from_route": "/courses///about", "to_route": "batch/about"}, - {"from_route": "/courses///progress", "to_route": "batch/progress"}, - {"from_route": "/courses///join", "to_route": "batch/join"} + {"from_route": "/courses//home", "to_route": "batch/home"}, + {"from_route": "/courses//learn", "to_route": "batch/learn"}, + {"from_route": "/courses//learn/.", "to_route": "batch/learn"}, + {"from_route": "/courses//schedule", "to_route": "batch/schedule"}, + {"from_route": "/courses//members", "to_route": "batch/members"}, + {"from_route": "/courses//discuss", "to_route": "batch/discuss"}, + {"from_route": "/courses//about", "to_route": "batch/about"}, + {"from_route": "/courses//progress", "to_route": "batch/progress"}, + {"from_route": "/courses//join", "to_route": "batch/join"} ] # Any frappe default URL is blocked by profile-rules, add it here to unblock it diff --git a/community/lms/doctype/chapter/chapter.py b/community/lms/doctype/chapter/chapter.py index b616de2c..6c160455 100644 --- a/community/lms/doctype/chapter/chapter.py +++ b/community/lms/doctype/chapter/chapter.py @@ -12,4 +12,5 @@ class Chapter(Document): filters={"chapter": self.name}, fields='name', order_by="index_") + print("rows", rows) return [frappe.get_doc('Lesson', row['name']) for row in rows] diff --git a/community/lms/doctype/lesson/lesson.json b/community/lms/doctype/lesson/lesson.json index 4772b255..59df2394 100644 --- a/community/lms/doctype/lesson/lesson.json +++ b/community/lms/doctype/lesson/lesson.json @@ -12,7 +12,8 @@ "index_", "index_label", "body", - "sections" + "sections", + "include_in_preview" ], "fields": [ { @@ -59,11 +60,17 @@ "in_list_view": 1, "label": "Index Label", "read_only": 1 + }, + { + "default": "0", + "fieldname": "include_in_preview", + "fieldtype": "Check", + "label": "Include In Preview" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-06-01 05:30:48.127494", + "modified": "2021-06-10 10:06:39.176891", "modified_by": "Administrator", "module": "LMS", "name": "Lesson", diff --git a/community/lms/doctype/lms_batch/lms_batch.py b/community/lms/doctype/lms_batch/lms_batch.py index 185134ae..93ed20bd 100644 --- a/community/lms/doctype/lms_batch/lms_batch.py +++ b/community/lms/doctype/lms_batch/lms_batch.py @@ -83,7 +83,7 @@ class LMSBatch(Document): def get_learn_url(self, lesson_number): if not lesson_number: return - return f"/courses/{self.course}/{self.name}/learn/{lesson_number}" + return f"/courses/{self.course}/learn/{lesson_number}" @frappe.whitelist() def save_message(message, batch): diff --git a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py index 7d714d46..cda7c53b 100644 --- a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py +++ b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py @@ -43,6 +43,9 @@ class LMSBatchMembership(Document): member_name = frappe.db.get_value("User", self.member, "full_name") frappe.throw(_("{0} is already a {1} of {2} course through {3} batch").format(member_name, membership.member_type, course, membership.batch)) + def get_user_batch(course, user=frappe.session.user): + return frappe.db.get_value("LMS Batch Membership", {"member": user, "course": course}, "batch") + @frappe.whitelist() def create_membership(batch, member=None, member_type="Student", role="Member"): frappe.get_doc({ diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index b3d08ef9..315a9092 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -8,6 +8,7 @@ from frappe.model.document import Document import json from ...utils import slugify from community.query import find, find_all +from frappe.utils import flt class LMSCourse(Document): @staticmethod @@ -112,7 +113,7 @@ class LMSCourse(Document): """Returns all chapters of this course. """ # TODO: chapters should have a way to specify the order - return find_all("Chapter", course=self.name, order_by="creation") + return find_all("Chapter", course=self.name, order_by="index_") def get_batch(self, batch_name): return find("LMS Batch", name=batch_name, course=self.name) @@ -197,6 +198,7 @@ class CourseOutline: self.lessons = self.get_lessons() def get_next(self, current): + current = flt(current) numbers = sorted(lesson['number'] for lesson in self.lessons) try: index = numbers.index(current) @@ -205,6 +207,7 @@ class CourseOutline: return None def get_prev(self, current): + current = flt(current) numbers = sorted(lesson['number'] for lesson in self.lessons) try: index = numbers.index(current) @@ -228,7 +231,7 @@ class CourseOutline: chapter_numbers = {c['name']: c['index_'] for c in self.chapters} for lesson in lessons: - lesson['number'] = "{}.{}".format(chapter_numbers[lesson['chapter']], lesson['index_']) + lesson['number'] = flt("{}.{}".format(chapter_numbers[lesson['chapter']], lesson['index_'])) return lessons @frappe.whitelist() diff --git a/community/lms/models.py b/community/lms/models.py index 00c910c3..2e7249d7 100644 --- a/community/lms/models.py +++ b/community/lms/models.py @@ -2,4 +2,4 @@ """ from .doctype.lms_course.lms_course import LMSCourse as Course from .doctype.lms_sketch.lms_sketch import LMSSketch as Sketch - +from .doctype.lms_batch_membership.lms_batch_membership import LMSBatchMembership as Membership diff --git a/community/lms/widgets/BatchTabs.html b/community/lms/widgets/BatchTabs.html index 48378660..983b5655 100644 --- a/community/lms/widgets/BatchTabs.html +++ b/community/lms/widgets/BatchTabs.html @@ -1,28 +1,30 @@
- Courses /{% if course.is_mentor(frappe.session.user) %} {{ course.title }} {% else %} {{ course.title }} {% endif %} + Courses /{% if course.is_mentor(frappe.session.user) %} {{ course.title }} {% else %} + {{ course.title }} {% endif %}
diff --git a/community/lms/widgets/ChapterTeaser.html b/community/lms/widgets/ChapterTeaser.html index 1678b1bb..fce2a11a 100644 --- a/community/lms/widgets/ChapterTeaser.html +++ b/community/lms/widgets/ChapterTeaser.html @@ -1,15 +1,15 @@
-

{{index}}. {{ chapter.title }}

+
{{index}}. {{ chapter.title }}
{{ chapter.description or "" }}
{% for lesson in chapter.get_lessons() %}
- {{ lesson.title }} + {{ lesson.title }} {% if show_progress and not course.is_mentor(frappe.session.user) and lesson.get_progress() %} - {{ lesson.get_progress() }} + {{ lesson.get_progress() }} {% endif %}
{% endfor %} diff --git a/community/lms/widgets/CourseOutline.html b/community/lms/widgets/CourseOutline.html index 249013ff..b4b5629c 100644 --- a/community/lms/widgets/CourseOutline.html +++ b/community/lms/widgets/CourseOutline.html @@ -1,5 +1,7 @@ -

Course Outline

+
+

Course Outline

-{% for chapter in course.get_chapters() %} -{{ widgets.ChapterTeaser(index=loop.index, chapter=chapter, course=course, batch=batch, show_link=show_link, show_progress=show_progress)}} -{% endfor %} + {% for chapter in course.get_chapters() %} + {{ widgets.ChapterTeaser(index=loop.index, chapter=chapter, course=course, batch=batch, show_link=show_link, show_progress=show_progress)}} + {% endfor %} +
diff --git a/community/lms/widgets/InstructorSection.html b/community/lms/widgets/InstructorSection.html index d7634b65..367148dd 100644 --- a/community/lms/widgets/InstructorSection.html +++ b/community/lms/widgets/InstructorSection.html @@ -1,5 +1,6 @@ -

Instructor

-
{{instructor.full_name}}
-
Created {{instructor.get_course_count()}} courses
+ {{ widgets.Avatar(member=instructor, avatar_class="avatar-medium") }} + {{ instructor.full_name }} +
Course Creator
+
diff --git a/community/public/css/style.css b/community/public/css/style.css index 699d8dfc..c1ff3462 100644 --- a/community/public/css/style.css +++ b/community/public/css/style.css @@ -82,6 +82,7 @@ body { border-radius: 10px; margin: 10px 0px; background: white; + box-shadow: 0px 5px 10px rgb(0 0 0 / 10%); border: 1px solid #ddc; } diff --git a/community/public/css/style.less b/community/public/css/style.less index c265dafe..9580e195 100644 --- a/community/public/css/style.less +++ b/community/public/css/style.less @@ -10,6 +10,7 @@ h2 { .teaser-body { padding: 20px; + box-shadow: 0px 5px 10px rgb(0 0 0 / 10%) } .teaser-footer { padding: 20px; @@ -162,7 +163,6 @@ section.lightgray { // } .instructor-title { - font-weight: bold; color: black; } diff --git a/community/www/batch/home.html b/community/www/batch/home.html index db439963..a1f6a4a9 100644 --- a/community/www/batch/home.html +++ b/community/www/batch/home.html @@ -11,26 +11,28 @@ {% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/" + batch.name + "/join" %}
{{ widgets.BatchTabs(course=course, batch=batch) }} -
+ +
{{ widgets.CourseOutline(course=course, batch=batch, show_link=True, show_progress=True) }}
-

Batch Schedule

+

Batch Schedule

{{ widgets.RenderBatch(course=course, batch=batch) }}
{% if batch.description %} -

Batch Details

- {{ frappe.utils.md_to_html(batch.description) }} +
+

Batch Details

+ {{ frappe.utils.md_to_html(batch.description) }} +
{% endif %} {% if course.is_mentor(frappe.session.user) %} diff --git a/community/www/batch/learn.py b/community/www/batch/learn.py index 4f031eab..08ccb05e 100644 --- a/community/www/batch/learn.py +++ b/community/www/batch/learn.py @@ -1,6 +1,7 @@ from re import I import frappe from . import utils +from frappe.utils import cstr def get_context(context): utils.get_common_context(context) @@ -10,9 +11,10 @@ def get_context(context): lesson_number = f"{chapter_index}.{lesson_index}" course_name = context.course.name - + print(chapter_index, lesson_index) if not chapter_index or not lesson_index: index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1" + print(index_) frappe.local.flags.redirect_location = context.batch.get_learn_url(index_) raise frappe.Redirect @@ -33,8 +35,9 @@ def get_context(context): def get_chapter_title(course_name, lesson_number): if not lesson_number: return - chapter_index = lesson_number.split(".")[0] - lesson_index = lesson_number.split(".")[1] + lesson_split = cstr(lesson_number).split(".") + chapter_index = lesson_split[0] + lesson_index = lesson_split[1] chapter_name = frappe.db.get_value("Chapter", {"course": course_name, "index_": chapter_index}, "name") return frappe.db.get_value("Lesson", {"chapter": chapter_name, "index_": lesson_index}, "title") diff --git a/community/www/batch/members.html b/community/www/batch/members.html index 035e12dd..32baa20d 100644 --- a/community/www/batch/members.html +++ b/community/www/batch/members.html @@ -19,23 +19,19 @@ {% macro MembersList(members) %}
{% for member in members %} -
-
- {{ widgets.Avatar(member=member, avatar_class="avatar-large") }} -
-
-
- +
+ {{ widgets.Avatar(member=member, avatar_class="avatar-large") }} +
+
+

{{ member.full_name }}

{% if course.is_mentor(member.name) %} -
-
Mentor
-
+
Mentor
{% endif %}
{% if member.bio %} - {{member.bio}} + {{member.bio}} {% endif %}
diff --git a/community/www/batch/progress.html b/community/www/batch/progress.html index 983077b1..0762d835 100644 --- a/community/www/batch/progress.html +++ b/community/www/batch/progress.html @@ -26,7 +26,7 @@
{{ widgets.BatchTabs(course=course, batch=batch) }}
-

Batch Progress

+

Batch Progress

{% for exercise in report.exercises %}

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

diff --git a/community/www/batch/progress.py b/community/www/batch/progress.py index adfb72dd..13578ac1 100644 --- a/community/www/batch/progress.py +++ b/community/www/batch/progress.py @@ -14,12 +14,13 @@ def get_context(context): context.exercise = exercise context.report = BatchReport(context.course, context.batch) + print(context.report) class BatchReport: def __init__(self, course, batch): self.submissions = get_submissions(batch) self.exercises = self.get_exercises(course.name) - + print(self.submissions) self.submissions_by_exercise = defaultdict(list) for s in self.submissions: self.submissions_by_exercise[s.exercise].append(s) @@ -34,7 +35,7 @@ def get_submissions(batch): students = batch.get_students() students_map = {s.email: s for s in students} names, values = nparams("s", students_map.keys()) - + print(students, names, values) sql = """ select owner, exercise, name, solution, creation, image from ( @@ -45,7 +46,7 @@ def get_submissions(batch): """.format(names) data = frappe.db.sql(sql, values=values, as_dict=True) - + print(data) for row in data: row['owner'] = students_map[row['owner']] return data diff --git a/community/www/batch/utils.py b/community/www/batch/utils.py index 24b5dd32..76c47228 100644 --- a/community/www/batch/utils.py +++ b/community/www/batch/utils.py @@ -1,21 +1,20 @@ import frappe -from community.lms.models import Course +from community.lms.models import Course, Membership def get_common_context(context): context.no_cache = 1 course_name = frappe.form_dict["course"] - batch_name = frappe.form_dict["batch"] course = Course.find(course_name) if not course: context.template = "www/404.html" return - + batch_name = Membership.get_user_batch(course_name) batch = course.get_batch(batch_name) - if not batch or not batch.is_member(frappe.session.user): + """ if not batch or not batch.is_member(frappe.session.user): frappe.local.flags.redirect_location = "/courses/" + course_name - raise frappe.Redirect + raise frappe.Redirect """ context.course = course context.batch = batch diff --git a/community/www/courses/course.html b/community/www/courses/course.html index 0d4d7ccc..0963437f 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -12,28 +12,20 @@
Courses / {{ course.title }}
-

{{course.title}}

+

{{course.title}}

{{ course.short_introduction }}
-
-
+
+
{{ CourseVideo(course) }} - {{ CourseDescription(course) }} + {{ widgets.InstructorSection(instructor=course.get_instructor()) }} {{ BatchSection(course) }} {{ widgets.CourseOutline(course=course, show_link=False) }}
-
- - -
{% endblock %} @@ -49,28 +41,31 @@ {% endmacro %} {% macro CourseDescription(course) %} -

Course Description

+
+

Course Description

-
- {{ frappe.utils.md_to_html(course.description) }} +
+ {{ frappe.utils.md_to_html(course.description) }} +
{% endmacro %} {% macro BatchSection(course) %} -{% if course.is_mentor(frappe.session.user) %} -{{ BatchSectionForMentors(course, course.get_batches(mentor=frappe.session.user)) }} -{% else %} -{{ BatchSectionForStudents(course, course.get_upcoming_batches()) }} -{% endif %} +
+
+ {% if course.is_mentor(frappe.session.user) %} + {{ BatchSectionForMentors(course, course.get_batches(mentor=frappe.session.user)) }} + {% else %} + {{ BatchSectionForStudents(course, course.get_upcoming_batches()) }} + {% endif %} +
+
{% endmacro %} {% macro BatchSectionForMentors(course, mentor_batches) %}

Your Batches

{% if mentor_batches %} -
{% for batch in mentor_batches %} @@ -92,14 +87,15 @@ {% macro BatchSectionForStudents(course, upcoming_batches) %} {% if upcoming_batches %} -

Upcoming Batches

- -
- {% for batch in upcoming_batches %} -
- {{ widgets.RenderBatch(course=course, batch=batch, can_join=True) }} +
+

Upcoming Batches

+
+ {% for batch in upcoming_batches %} +
+ {{ widgets.RenderBatch(course=course, batch=batch, can_join=True) }} +
+ {% endfor %}
- {% endfor %} + {% endif %}
-{% endif %} {% endmacro %} diff --git a/community/www/courses/index.html b/community/www/courses/index.html index 6a69235c..2533c6b0 100644 --- a/community/www/courses/index.html +++ b/community/www/courses/index.html @@ -10,19 +10,17 @@ {% block content %}
-
-

{{ 'Courses' }}

-
+

{{ 'All Courses' }}

{% for course in courses %} {{ course_card(course) }} {% endfor %} - {% if courses %} +
@@ -32,7 +30,7 @@ {% macro course_card(course) %}
-
+
{{ course.title }}
{% if course.description %} diff --git a/community/www/hackathons/macros/card.html b/community/www/hackathons/macros/card.html index 6eed31e0..912a3cda 100644 --- a/community/www/hackathons/macros/card.html +++ b/community/www/hackathons/macros/card.html @@ -1,7 +1,7 @@ {% macro hackathon_card(hackathon) %}
-
+
{{ hackathon.name }}
@@ -12,7 +12,7 @@ {% macro null_card() %}
-
+
-{% endmacro %} \ No newline at end of file +{% endmacro %} From 7840512a13a8dfc4bd23a785003c7debee0c1c9f Mon Sep 17 00:00:00 2001 From: pateljannat Date: Mon, 14 Jun 2021 18:45:46 +0530 Subject: [PATCH 2/4] fix: ui, preview, progress, batches --- community/lms/api.py | 7 - community/lms/doctype/chapter/chapter.py | 1 - .../doctype/invite_request/invite_request.py | 3 +- community/lms/doctype/lesson/lesson.json | 23 +-- community/lms/doctype/lesson/lesson.py | 39 +---- community/lms/doctype/lms_batch/lms_batch.py | 5 - .../lms_batch_membership.json | 13 +- .../lms_batch_membership.py | 13 +- .../lms/doctype/lms_course/lms_course.py | 16 ++ community/lms/doctype/lms_section/__init__.py | 0 .../lms/doctype/lms_section/lms_section.json | 66 -------- .../lms/doctype/lms_section/lms_section.py | 33 ---- community/lms/section_parser.py | 84 ---------- .../add_a_new_batch/add_a_new_batch.json | 4 +- .../lms/web_form/join_a_batch/__init__.py | 0 .../lms/web_form/join_a_batch/join_a_batch.js | 3 - .../web_form/join_a_batch/join_a_batch.json | 48 ------ .../lms/web_form/join_a_batch/join_a_batch.py | 7 - community/lms/widgets/BatchTabs.html | 43 ++++- community/lms/widgets/ChapterTeaser.html | 38 ++++- community/lms/widgets/RenderBatch.html | 5 +- community/public/css/style.css | 13 -- community/public/css/style.less | 20 +++ community/www/batch/learn.html | 21 +-- community/www/batch/learn.js | 8 +- community/www/batch/learn.py | 15 +- community/www/batch/utils.py | 16 +- community/www/courses/course.html | 2 +- community/www/courses/course.js | 150 ++++++++++-------- community/www/courses/course.py | 2 +- community/www/courses/index.html | 2 +- 31 files changed, 275 insertions(+), 425 deletions(-) delete mode 100644 community/lms/doctype/lms_section/__init__.py delete mode 100644 community/lms/doctype/lms_section/lms_section.json delete mode 100644 community/lms/doctype/lms_section/lms_section.py delete mode 100644 community/lms/section_parser.py delete mode 100644 community/lms/web_form/join_a_batch/__init__.py delete mode 100644 community/lms/web_form/join_a_batch/join_a_batch.js delete mode 100644 community/lms/web_form/join_a_batch/join_a_batch.json delete mode 100644 community/lms/web_form/join_a_batch/join_a_batch.py diff --git a/community/lms/api.py b/community/lms/api.py index 1ed198e1..089ad86d 100644 --- a/community/lms/api.py +++ b/community/lms/api.py @@ -15,13 +15,6 @@ def autosave_section(section, code): doc.insert() return {"name": doc.name} -@frappe.whitelist() -def get_section(name): - """Saves the code edited in one of the sections. - """ - doc = frappe.get_doc("LMS Section", name) - return doc and doc.as_dict() - @frappe.whitelist() def submit_solution(exercise, code): """Submits a solution. diff --git a/community/lms/doctype/chapter/chapter.py b/community/lms/doctype/chapter/chapter.py index 6c160455..b616de2c 100644 --- a/community/lms/doctype/chapter/chapter.py +++ b/community/lms/doctype/chapter/chapter.py @@ -12,5 +12,4 @@ class Chapter(Document): filters={"chapter": self.name}, fields='name', order_by="index_") - print("rows", rows) return [frappe.get_doc('Lesson', row['name']) for row in rows] diff --git a/community/lms/doctype/invite_request/invite_request.py b/community/lms/doctype/invite_request/invite_request.py index 00bc18c2..325f2611 100644 --- a/community/lms/doctype/invite_request/invite_request.py +++ b/community/lms/doctype/invite_request/invite_request.py @@ -58,7 +58,8 @@ def create_invite_request(invite_email): frappe.get_doc({ "doctype": "Invite Request", - "invite_email": invite_email + "invite_email": invite_email, + "status": "Approved" }).save(ignore_permissions=True) return "OK" diff --git a/community/lms/doctype/lesson/lesson.json b/community/lms/doctype/lesson/lesson.json index 59df2394..18c20147 100644 --- a/community/lms/doctype/lesson/lesson.json +++ b/community/lms/doctype/lesson/lesson.json @@ -8,12 +8,13 @@ "field_order": [ "chapter", "lesson_type", + "include_in_preview", + "column_break_4", "title", "index_", "index_label", - "body", - "sections", - "include_in_preview" + "section_break_6", + "body" ], "fields": [ { @@ -48,12 +49,6 @@ "fieldtype": "Markdown Editor", "label": "Body" }, - { - "fieldname": "sections", - "fieldtype": "Table", - "label": "Sections", - "options": "LMS Section" - }, { "fieldname": "index_label", "fieldtype": "Data", @@ -66,11 +61,19 @@ "fieldname": "include_in_preview", "fieldtype": "Check", "label": "Include In Preview" + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_4", + "fieldtype": "Column Break" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-06-10 10:06:39.176891", + "modified": "2021-06-11 19:03:23.138165", "modified_by": "Administrator", "module": "LMS", "name": "Lesson", diff --git a/community/lms/doctype/lesson/lesson.py b/community/lms/doctype/lesson/lesson.py index 52d8bf28..49abb2d7 100644 --- a/community/lms/doctype/lesson/lesson.py +++ b/community/lms/doctype/lesson/lesson.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document -from ...section_parser import SectionParser from ...md import markdown_to_html, find_macros class Lesson(Document): @@ -39,9 +38,6 @@ class Lesson(Document): def render_html(self): return markdown_to_html(self.body) - def get_sections(self): - return sorted(self.get('sections'), key=lambda s: s.index) - def get_exercises(self): if not self.body: return [] @@ -50,30 +46,6 @@ class Lesson(Document): exercises = [value for name, value in macros if name == "Exercise"] return [frappe.get_doc("Exercise", name) for name in exercises] - def make_lms_section(self, index, section): - s = frappe.new_doc('LMS Section', parent_doc=self, parentfield='sections') - s.type = section.type - s.id = section.id - s.label = section.label - s.contents = section.contents - s.index = index - return s - - def get_next(self): - """Returns the number for the next lesson. - - The return value would be like 1.2, 2.1 etc. - It will be None if there is no next lesson. - """ - - - def get_prev(self): - """Returns the number for the prev lesson. - - The return value would be like 1.2, 2.1 etc. - It will be None if there is no next lesson. - """ - def get_progress(self): return frappe.db.get_value("LMS Course Progress", {"lesson": self.name, "owner": frappe.session.user}, "status") @@ -98,11 +70,7 @@ def save_progress(lesson, batch): return lesson_details = frappe.get_doc("Lesson", lesson) - dynamic_content = frappe.db.count("LMS Section", - filters={ - "type": ["not in", ["example", "text"]], - "parent": lesson_details.name - }) + dynamic_content = find_macros(lesson_details.body) status = "Complete" if dynamic_content: @@ -121,12 +89,11 @@ def update_progress(lesson): if frappe.db.exists("LMS Course Progress", {"lesson": lesson, "owner": user}): course_progress = frappe.get_doc("LMS Course Progress", {"lesson": lesson, "owner": user}) course_progress.status = "Complete" - course_progress.save() + course_progress.save(ignore_permissions=True) def all_dynamic_content_submitted(lesson, user): - exercise_names = frappe.get_list("Exercise", {"lesson": lesson}, ["name"], pluck="name") + exercise_names = frappe.get_list("Exercise", {"lesson": lesson}, pluck="name") all_exercises_submitted = False - print(exercise_names) query = { "exercise": ["in", exercise_names], "owner": user diff --git a/community/lms/doctype/lms_batch/lms_batch.py b/community/lms/doctype/lms_batch/lms_batch.py index 93ed20bd..391eac7e 100644 --- a/community/lms/doctype/lms_batch/lms_batch.py +++ b/community/lms/doctype/lms_batch/lms_batch.py @@ -80,11 +80,6 @@ class LMSBatch(Document): membership = self.get_membership(user) return membership and membership.current_lesson - def get_learn_url(self, lesson_number): - if not lesson_number: - return - return f"/courses/{self.course}/learn/{lesson_number}" - @frappe.whitelist() def save_message(message, batch): doc = frappe.get_doc({ diff --git a/community/lms/doctype/lms_batch_membership/lms_batch_membership.json b/community/lms/doctype/lms_batch_membership/lms_batch_membership.json index 68d2eaed..6a0cc143 100644 --- a/community/lms/doctype/lms_batch_membership/lms_batch_membership.json +++ b/community/lms/doctype/lms_batch_membership/lms_batch_membership.json @@ -13,7 +13,8 @@ "course", "member_type", "role", - "current_lesson" + "current_lesson", + "is_current" ], "fields": [ { @@ -80,11 +81,19 @@ "fieldtype": "Data", "label": "Memeber Username", "read_only": 1 + }, + { + "default": "0", + "fieldname": "is_current", + "fieldtype": "Check", + "hidden": 1, + "label": "Is Currently Being Used", + "read_only": 1 } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-05-24 12:40:57.125694", + "modified": "2021-06-14 10:24:35.425498", "modified_by": "Administrator", "module": "LMS", "name": "LMS Batch Membership", diff --git a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py index cda7c53b..f7a39b74 100644 --- a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py +++ b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py @@ -43,9 +43,6 @@ class LMSBatchMembership(Document): member_name = frappe.db.get_value("User", self.member, "full_name") frappe.throw(_("{0} is already a {1} of {2} course through {3} batch").format(member_name, membership.member_type, course, membership.batch)) - def get_user_batch(course, user=frappe.session.user): - return frappe.db.get_value("LMS Batch Membership", {"member": user, "course": course}, "batch") - @frappe.whitelist() def create_membership(batch, member=None, member_type="Student", role="Member"): frappe.get_doc({ @@ -56,3 +53,13 @@ def create_membership(batch, member=None, member_type="Student", role="Member"): "member": member or frappe.session.user }).save(ignore_permissions=True) return "OK" + +@frappe.whitelist() +def update_current_membership(batch, course, member=frappe.session.user): + all_memberships = frappe.get_all("LMS Batch Membership", {"member": member, "course": course}) + for membership in all_memberships: + frappe.db.set_value("LMS Batch Membership", membership.name, "is_current", 0) + + current_membership = frappe.get_all("LMS Batch Membership", {"batch": batch, "member": member}) + if len(current_membership): + frappe.db.set_value("LMS Batch Membership", current_membership[0].name, "is_current", 1) diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index 315a9092..30e25b85 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -187,6 +187,22 @@ class LMSCourse(Document): exercise.save() i += 1 + def get_learn_url(self, lesson_number): + if not lesson_number: + return + return f"/courses/{self.name}/learn/{lesson_number}" + + def get_current_batch(self, member=frappe.session.user): + current_membership = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name, "is_current": 1}, pluck="batch") + if len(current_membership): + return current_membership[0] + return frappe.db.get_value("LMS Batch Membership", {"member": member, "course": self.name}, "batch") + + def get_all_memberships(self, member=frappe.session.user): + all_memberships = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name}, ["batch", "is_current"]) + for membership in all_memberships: + membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") + return all_memberships def get_outline(self): return CourseOutline(self) diff --git a/community/lms/doctype/lms_section/__init__.py b/community/lms/doctype/lms_section/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/community/lms/doctype/lms_section/lms_section.json b/community/lms/doctype/lms_section/lms_section.json deleted file mode 100644 index 3b056485..00000000 --- a/community/lms/doctype/lms_section/lms_section.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "actions": [], - "creation": "2021-03-05 15:10:53.906006", - "doctype": "DocType", - "engine": "InnoDB", - "field_order": [ - "label", - "type", - "contents", - "code", - "attrs", - "index", - "id" - ], - "fields": [ - { - "fieldname": "label", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Label" - }, - { - "fieldname": "type", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Type" - }, - { - "fieldname": "contents", - "fieldtype": "Markdown Editor", - "label": "Contents" - }, - { - "fieldname": "code", - "fieldtype": "Code", - "label": "Code" - }, - { - "fieldname": "attrs", - "fieldtype": "Long Text", - "label": "attrs" - }, - { - "fieldname": "index", - "fieldtype": "Int", - "label": "Index" - }, - { - "fieldname": "id", - "fieldtype": "Data", - "label": "id" - } - ], - "index_web_pages_for_search": 1, - "istable": 1, - "links": [], - "modified": "2021-05-19 18:55:26.019625", - "modified_by": "Administrator", - "module": "LMS", - "name": "LMS Section", - "owner": "Administrator", - "permissions": [], - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1 -} \ No newline at end of file diff --git a/community/lms/doctype/lms_section/lms_section.py b/community/lms/doctype/lms_section/lms_section.py deleted file mode 100644 index 65c33f46..00000000 --- a/community/lms/doctype/lms_section/lms_section.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2021, FOSS United and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.document import Document - -class LMSSection(Document): - def __repr__(self): - return f"" - - def get_exercise(self): - if self.type == "exercise": - return frappe.get_doc("Exercise", self.id) - - def get_latest_code_for_user(self): - """Returns the latest code for the logged in user. - """ - if not frappe.session.user or frappe.session.user == "Guest": - return self.contents - result = frappe.get_all('Code Revision', - fields=["code"], - filters={ - "author": frappe.session.user, - "section": self.name - }, - order_by="creation desc", - page_length=1) - if result: - return result[0]['code'] - else: - return self.contents diff --git a/community/lms/section_parser.py b/community/lms/section_parser.py deleted file mode 100644 index 183a7c6b..00000000 --- a/community/lms/section_parser.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Utility to split the text in the topic into multiple sections. - -{{ section(type="example", id="foo") }} -circle(100, 100, 50) -{{ end }} - -""" -from __future__ import annotations -from dataclasses import dataclass -import re -from typing import List, Tuple, Dict, Iterator - -RE_SECTION = re.compile(r"^\{\{\s(\w+)\s*(?:\((.*)\))?\s*\}\}\s*") -class SectionParser: - def parse(self, text: str) -> Iterator[Section]: - """Parses given text into sections and return an iterator over sections. - """ - lines = text.splitlines() - marked_lines = self.parse_lines(lines) - return self.group_sections(marked_lines) - - def parse_lines(self, lines: List[str]) -> List[Tuple[str, str, str]]: - for line in lines: - m = RE_SECTION.match(line) - if m: - yield m.group(1), self.parse_attrs(m.group(2)), None - else: - yield None, None, line - - def parse_attrs(self, attrs_str: str) -> Dict[str, str]: - # XXX-Anand: Hack - code = "dict({})".format(attrs_str or "") - return eval(code) - - def group_sections(self, marked_lines) -> Iterator[Section]: - index = 0 - - def make_section(type='text', id=None, label=None, **attrs): - nonlocal index - index += 1 - - id = id or f"section-{index}" - label = label or id - return Section( - type=type, - id=id, - label=label, - attrs=attrs) - - section = make_section("text") - - for mark, attrs, line in marked_lines: - if not mark: - section.append(line) - continue - - yield section - - if mark == 'end': - section = make_section(type='text') - else: - section = make_section(**attrs) - - yield section - -@dataclass -class Section: - """One section of the Topic. - """ - type: str - id: str - label: str - contents: str = "" - attrs: dict = None - - def append(self, line): - if not line.endswith("\n"): - line = line + "\n" - self.contents += line - - def __repr__(self): - attrs = dict(type=self.type, id=self.id, label=self.label, **self.attrs) - attrs_str = ", ".join(f'{k}="{v}"' for k, v in attrs.items()) - return f'' diff --git a/community/lms/web_form/add_a_new_batch/add_a_new_batch.json b/community/lms/web_form/add_a_new_batch/add_a_new_batch.json index 76735390..caf901ff 100644 --- a/community/lms/web_form/add_a_new_batch/add_a_new_batch.json +++ b/community/lms/web_form/add_a_new_batch/add_a_new_batch.json @@ -11,7 +11,7 @@ "apply_document_permissions": 0, "button_label": "Save", "creation": "2021-04-20 11:37:49.135114", - "custom_css": ".datepicker.active {\n background-color: white;\n}", + "custom_css": ".datepicker.active {\n background-color: white;\n}\n\n[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}", "doc_type": "LMS Batch", "docstatus": 0, "doctype": "Web Form", @@ -19,7 +19,7 @@ "is_standard": 1, "login_required": 1, "max_attachment_size": 0, - "modified": "2021-06-02 15:52:06.383260", + "modified": "2021-06-14 15:28:08.206622", "modified_by": "Administrator", "module": "LMS", "name": "add-a-new-batch", diff --git a/community/lms/web_form/join_a_batch/__init__.py b/community/lms/web_form/join_a_batch/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/community/lms/web_form/join_a_batch/join_a_batch.js b/community/lms/web_form/join_a_batch/join_a_batch.js deleted file mode 100644 index 699703c5..00000000 --- a/community/lms/web_form/join_a_batch/join_a_batch.js +++ /dev/null @@ -1,3 +0,0 @@ -frappe.ready(function() { - // bind events here -}) \ No newline at end of file diff --git a/community/lms/web_form/join_a_batch/join_a_batch.json b/community/lms/web_form/join_a_batch/join_a_batch.json deleted file mode 100644 index 9afd7801..00000000 --- a/community/lms/web_form/join_a_batch/join_a_batch.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "accept_payment": 0, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 0, - "allow_incomplete": 0, - "allow_multiple": 0, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "apply_document_permissions": 0, - "button_label": "Save", - "creation": "2021-04-15 13:32:14.171328", - "doc_type": "LMS Batch Membership", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2021-04-15 13:32:14.171328", - "modified_by": "Administrator", - "module": "LMS", - "name": "join-a-batch", - "owner": "Administrator", - "payment_button_label": "Buy Now", - "published": 1, - "route": "join-a-batch", - "route_to_success_link": 0, - "show_attachments": 0, - "show_in_grid": 0, - "show_sidebar": 0, - "sidebar_items": [], - "success_url": "/join-a-batch", - "title": "Join a Batch", - "web_form_fields": [ - { - "allow_read_on_all_link_options": 0, - "fieldtype": "Attach", - "hidden": 0, - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - } - ] -} \ No newline at end of file diff --git a/community/lms/web_form/join_a_batch/join_a_batch.py b/community/lms/web_form/join_a_batch/join_a_batch.py deleted file mode 100644 index 2334f8b2..00000000 --- a/community/lms/web_form/join_a_batch/join_a_batch.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def get_context(context): - # do your magic here - pass diff --git a/community/lms/widgets/BatchTabs.html b/community/lms/widgets/BatchTabs.html index 983b5655..5a3b8a0f 100644 --- a/community/lms/widgets/BatchTabs.html +++ b/community/lms/widgets/BatchTabs.html @@ -2,9 +2,28 @@
Courses /{% if course.is_mentor(frappe.session.user) %} {{ course.title }} {% else %} {{ course.title }} {% endif %} + {% set all_memberships = course.get_all_memberships() %} + {% if all_memberships | length > 1 %} + + + {% endif %}
+{% if not batch %} +{% set display_class = "hide" %} +{% else %} +{% set display_class = "" %} +{% endif %}
+ + diff --git a/community/lms/widgets/RenderBatch.html b/community/lms/widgets/RenderBatch.html index 60e77784..4a9431bb 100644 --- a/community/lms/widgets/RenderBatch.html +++ b/community/lms/widgets/RenderBatch.html @@ -1,6 +1,6 @@
-
Session every {{batch.sessions_on}}
+
Session every {{batch.sessions_on}}
{{frappe.utils.format_time(batch.start_time, "short")}} - {{frappe.utils.format_time(batch.end_time, "short")}}
@@ -18,7 +18,8 @@
{% if can_manage %} - Manage + Manage {% elif can_join %} diff --git a/community/public/css/style.css b/community/public/css/style.css index c1ff3462..448b6431 100644 --- a/community/public/css/style.css +++ b/community/public/css/style.css @@ -157,19 +157,6 @@ img.profile-photo { line-height: 51px; } -.anchor_style { - color: inherit; -} - -a:hover { - text-decoration: none; - color: inherit; -} - -.anchor_style:hover { - text-decoration: underline -} - section { padding: 5rem 0 5rem 0; } diff --git a/community/public/css/style.less b/community/public/css/style.less index 9580e195..b74cd666 100644 --- a/community/public/css/style.less +++ b/community/public/css/style.less @@ -67,6 +67,20 @@ h2 { } } + +.anchor_style { + color: inherit; +} + +.anchor_style:hover { + text-decoration: none +} + +.no-preview:hover { + cursor: pointer; + color: #2490ef; +} + section { padding: 60px 0px; } @@ -331,3 +345,9 @@ section.lightgray { margin: 40px 0px 0px 20px; } } + +.no-preview-message { + width: fit-content; + margin: 50px 0px 50px; + color: black; +} diff --git a/community/www/batch/learn.html b/community/www/batch/learn.html index 17a12ff2..da9834b4 100644 --- a/community/www/batch/learn.html +++ b/community/www/batch/learn.html @@ -25,9 +25,16 @@ {{ widgets.BatchTabs(course=course, batch=batch) }}
-

{{ lesson.title }}

+

{{ lesson.title }}

+ {% if batch or lesson.include_in_preview %} {{ lesson.render_html() }} + {% else %} +
+ This lesson is not available for Preview. Please join a batch to access the complete course. + Checkout Upcoming Batches +
+ {% endif %} {{ pagination(prev_chap, prev_url, next_chap, next_url) }}
@@ -53,18 +60,6 @@ {%- block script %} {{ super() }} - - {% for ext in page_extensions %} {{ ext.render_footer() }} {% endfor %} diff --git a/community/www/batch/learn.js b/community/www/batch/learn.js index 4410fb08..05fbcb33 100644 --- a/community/www/batch/learn.js +++ b/community/www/batch/learn.js @@ -1,5 +1,5 @@ frappe.ready(() => { - if (!$(".title").hasClass("is_mentor")) { + if ($(".title").attr("data-batch") && !$(".title").hasClass("is_mentor")) { frappe.call({ method: "community.lms.doctype.lesson.lesson.save_progress", args: { @@ -8,4 +8,10 @@ frappe.ready(() => { } }) } + if ($(".title").attr("data-batch")) { + frappe.call("community.lms.api.save_current_lesson", { + "batch_name": $(".title").attr("data-batch"), + "lesson_name": $(".title").attr("data-name") + }) + } }) diff --git a/community/www/batch/learn.py b/community/www/batch/learn.py index ceb5fa36..241bc1e7 100644 --- a/community/www/batch/learn.py +++ b/community/www/batch/learn.py @@ -3,6 +3,8 @@ import frappe from . import utils from frappe.utils import cstr +from community.www import batch + def get_context(context): utils.get_common_context(context) @@ -11,11 +13,12 @@ def get_context(context): lesson_number = f"{chapter_index}.{lesson_index}" course_name = context.course.name - print(chapter_index, lesson_index) if not chapter_index or not lesson_index: - index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1" - print(index_) - frappe.local.flags.redirect_location = context.batch.get_learn_url(index_) + if context.batch: + index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1" + else: + index_ = "1.1" + frappe.local.flags.redirect_location = context.course.get_learn_url(index_) raise frappe.Redirect context.lesson = context.course.get_lesson(chapter_index, lesson_index) @@ -27,8 +30,8 @@ def get_context(context): next_ = outline.get_next(lesson_number) context.prev_chap = get_chapter_title(course_name, prev_) context.next_chap = get_chapter_title(course_name, next_) - context.next_url = context.batch.get_learn_url(next_) - context.prev_url = context.batch.get_learn_url(prev_) + context.next_url = context.course.get_learn_url(next_) + context.prev_url = context.course.get_learn_url(prev_) context.page_extensions = get_page_extensions() diff --git a/community/www/batch/utils.py b/community/www/batch/utils.py index 76c47228..4405ba2c 100644 --- a/community/www/batch/utils.py +++ b/community/www/batch/utils.py @@ -1,5 +1,5 @@ import frappe -from community.lms.models import Course, Membership +from community.lms.models import Course def get_common_context(context): context.no_cache = 1 @@ -10,16 +10,16 @@ def get_common_context(context): if not course: context.template = "www/404.html" return - batch_name = Membership.get_user_batch(course_name) + + batch_name = course.get_current_batch() batch = course.get_batch(batch_name) - """ if not batch or not batch.is_member(frappe.session.user): - frappe.local.flags.redirect_location = "/courses/" + course_name - raise frappe.Redirect """ + context.batch = batch + if batch_name: + context.members = batch.get_mentors() + batch.get_students() + context.member_count = len(context.members) + context.course = course - context.batch = batch - context.members = batch.get_mentors() + batch.get_students() - context.member_count = len(context.members) context.livecode_url = get_livecode_url() def get_livecode_url(): diff --git a/community/www/courses/course.html b/community/www/courses/course.html index 0963437f..7a34fb21 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -88,7 +88,7 @@ {% macro BatchSectionForStudents(course, upcoming_batches) %} {% if upcoming_batches %}
-

Upcoming Batches

+

Upcoming Batches

{% for batch in upcoming_batches %}
diff --git a/community/www/courses/course.js b/community/www/courses/course.js index ae77bdb0..58928149 100644 --- a/community/www/courses/course.js +++ b/community/www/courses/course.js @@ -1,72 +1,92 @@ frappe.ready(() => { - if (frappe.session.user != "Guest") { - frappe.call({ - 'method': 'community.lms.doctype.lms_mentor_request.lms_mentor_request.has_requested', - 'args': { - course: decodeURIComponent($("#course-title").attr("data-course")), - }, - 'callback': (data) => { - if (data.message > 0) { - $("#mentor-request").addClass("hide"); - $("#already-applied").removeClass("hide") - } - } - }) - } + if (frappe.session.user != "Guest") { + frappe.call({ + 'method': 'community.lms.doctype.lms_mentor_request.lms_mentor_request.has_requested', + 'args': { + course: decodeURIComponent($("#course-title").attr("data-course")), + }, + 'callback': (data) => { + if (data.message > 0) { + $("#mentor-request").addClass("hide"); + $("#already-applied").removeClass("hide") + } + } + }) + } - $("#apply-now").click((e) => { + $("#apply-now").click((e) => { e.preventDefault(); - if (frappe.session.user == "Guest") { - window.location.href = `/login?redirect-to=/courses/${$(e.currentTarget).attr("data-course")}`; - return; - } - frappe.call({ - "method": "community.lms.doctype.lms_mentor_request.lms_mentor_request.create_request", - "args": { - "course": decodeURIComponent($(e.currentTarget).attr("data-course")) - }, - "callback": (data) => { - if (data.message == "OK") { - $("#mentor-request").addClass("hide"); - $("#already-applied").removeClass("hide") - } - } - }) - }) + if (frappe.session.user == "Guest") { + window.location.href = `/login?redirect-to=/courses/${$(e.currentTarget).attr("data-course")}`; + return; + } + frappe.call({ + "method": "community.lms.doctype.lms_mentor_request.lms_mentor_request.create_request", + "args": { + "course": decodeURIComponent($(e.currentTarget).attr("data-course")) + }, + "callback": (data) => { + if (data.message == "OK") { + $("#mentor-request").addClass("hide"); + $("#already-applied").removeClass("hide") + } + } + }) + }) - $("#cancel-request").click((e) => { + $("#cancel-request").click((e) => { e.preventDefault() - frappe.call({ - "method": "community.lms.doctype.lms_mentor_request.lms_mentor_request.cancel_request", - "args": { - "course": decodeURIComponent($(e.currentTarget).attr("data-course")) - }, - "callback": (data) => { - if (data.message == "OK") { - $("#mentor-request").removeClass("hide"); - $("#already-applied").addClass("hide") - } - } - }) - }) + frappe.call({ + "method": "community.lms.doctype.lms_mentor_request.lms_mentor_request.cancel_request", + "args": { + "course": decodeURIComponent($(e.currentTarget).attr("data-course")) + }, + "callback": (data) => { + if (data.message == "OK") { + $("#mentor-request").removeClass("hide"); + $("#already-applied").addClass("hide") + } + } + }) + }) - $(".join-batch").click((e) => { - e.preventDefault() - if (frappe.session.user == "Guest") { - window.location.href = `/login?redirect-to=/courses/${$(e.currentTarget).attr("data-course")}`; - return; - } - batch = decodeURIComponent($(e.currentTarget).attr("data-batch")) - frappe.call({ - "method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership", - "args": { - "batch": batch - }, - "callback": (data) => { - if (data.message == "OK") { - frappe.msgprint(__("You are now a student of this course.")) - } - } - }) - }) + $(".join-batch").click((e) => { + e.preventDefault(); + var course = $(e.currentTarget).attr("data-course") + if (frappe.session.user == "Guest") { + window.location.href = `/login?redirect-to=/courses/${course}`; + return; + } + batch = decodeURIComponent($(e.currentTarget).attr("data-batch")) + frappe.call({ + "method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership", + "args": { + "batch": batch + }, + "callback": (data) => { + if (data.message == "OK") { + frappe.msgprint(__("You are now a student of this course.")); + setTimeout(function () { + window.location.href = `/courses/${course}/home`; + }, 2000); + } + } + }) + }) + + $(".manage-batch").click((e) => { + e.preventDefault(); + var batch = decodeURIComponent($(e.currentTarget).attr("data-batch")); + var course = decodeURIComponent($(e.currentTarget).attr("data-course")); + frappe.call({ + method: "community.lms.doctype.lms_batch_membership.lms_batch_membership.update_current_membership", + args: { + batch: batch, + course: course + }, + callback: (data) => { + window.location.href = `/courses/${course}/home`; + } + }) + }) }) diff --git a/community/www/courses/course.py b/community/www/courses/course.py index 69957fb3..e2ff459f 100644 --- a/community/www/courses/course.py +++ b/community/www/courses/course.py @@ -19,6 +19,6 @@ def get_context(context): batch = course.get_student_batch(frappe.session.user) if batch: - frappe.local.flags.redirect_location = f"/courses/{course.name}/{batch.name}/learn" + frappe.local.flags.redirect_location = f"/courses/{course.name}/learn" raise frappe.Redirect diff --git a/community/www/courses/index.html b/community/www/courses/index.html index 2533c6b0..89de4c19 100644 --- a/community/www/courses/index.html +++ b/community/www/courses/index.html @@ -29,7 +29,7 @@ {% macro course_card(course) %}
- +
{{ course.title }}
From 17f03aeee76814fdb2902314754764e1a730f54b Mon Sep 17 00:00:00 2001 From: pateljannat Date: Tue, 15 Jun 2021 13:01:57 +0530 Subject: [PATCH 3/4] fix: join batch, removed code revision, redirects for other pages if batch missing --- .../community_project_member.py | 5 +- .../lms/doctype/code_revision/__init__.py | 0 .../doctype/code_revision/code_revision.js | 8 --- .../doctype/code_revision/code_revision.json | 58 ------------------- .../doctype/code_revision/code_revision.py | 10 ---- .../code_revision/test_code_revision.py | 10 ---- community/lms/doctype/lesson/lesson.py | 2 +- .../lms/doctype/lms_course/lms_course.py | 4 ++ community/lms/widgets/ChapterTeaser.html | 4 +- community/www/batch/discuss.py | 2 + community/www/batch/home.html | 6 +- community/www/batch/home.py | 2 + community/www/batch/join.html | 36 +++++++----- community/www/batch/members.py | 3 +- community/www/batch/utils.py | 3 + community/www/courses/course.html | 4 +- 16 files changed, 49 insertions(+), 108 deletions(-) delete mode 100644 community/lms/doctype/code_revision/__init__.py delete mode 100644 community/lms/doctype/code_revision/code_revision.js delete mode 100644 community/lms/doctype/code_revision/code_revision.json delete mode 100644 community/lms/doctype/code_revision/code_revision.py delete mode 100644 community/lms/doctype/code_revision/test_code_revision.py diff --git a/community/hackathon/doctype/community_project_member/community_project_member.py b/community/hackathon/doctype/community_project_member/community_project_member.py index 50fb2d4a..6068c39c 100644 --- a/community/hackathon/doctype/community_project_member/community_project_member.py +++ b/community/hackathon/doctype/community_project_member/community_project_member.py @@ -3,13 +3,14 @@ # For license information, please see license.txt from __future__ import unicode_literals -# import frappe +import frappe from frappe.model.document import Document +from frappe import _ class CommunityProjectMember(Document): def validate(self): self.validate_if_already_member() - + def validate_if_already_member(self): if frappe.get_all("Community Project Member", {"owner": self.owner}): frappe.throw(_("You have already applied for the membership of this project.")) diff --git a/community/lms/doctype/code_revision/__init__.py b/community/lms/doctype/code_revision/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/community/lms/doctype/code_revision/code_revision.js b/community/lms/doctype/code_revision/code_revision.js deleted file mode 100644 index 4f9451ce..00000000 --- a/community/lms/doctype/code_revision/code_revision.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2021, FOSS United and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Code Revision', { - // refresh: function(frm) { - - // } -}); diff --git a/community/lms/doctype/code_revision/code_revision.json b/community/lms/doctype/code_revision/code_revision.json deleted file mode 100644 index 4b2cc036..00000000 --- a/community/lms/doctype/code_revision/code_revision.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "actions": [], - "creation": "2021-04-07 00:26:28.806520", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "section", - "code", - "author" - ], - "fields": [ - { - "fieldname": "section", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Section", - "options": "LMS Section" - }, - { - "fieldname": "code", - "fieldtype": "Code", - "label": "Code" - }, - { - "fieldname": "author", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Author", - "options": "User" - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2021-04-14 11:26:19.628317", - "modified_by": "Administrator", - "module": "LMS", - "name": "Code Revision", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "section", - "track_changes": 1 -} \ No newline at end of file diff --git a/community/lms/doctype/code_revision/code_revision.py b/community/lms/doctype/code_revision/code_revision.py deleted file mode 100644 index 5ca32baa..00000000 --- a/community/lms/doctype/code_revision/code_revision.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2021, FOSS United and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -# import frappe -from frappe.model.document import Document - -class CodeRevision(Document): - pass diff --git a/community/lms/doctype/code_revision/test_code_revision.py b/community/lms/doctype/code_revision/test_code_revision.py deleted file mode 100644 index 3ce8a443..00000000 --- a/community/lms/doctype/code_revision/test_code_revision.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2021, FOSS United and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestCodeRevision(unittest.TestCase): - pass diff --git a/community/lms/doctype/lesson/lesson.py b/community/lms/doctype/lesson/lesson.py index 49abb2d7..c96d3315 100644 --- a/community/lms/doctype/lesson/lesson.py +++ b/community/lms/doctype/lesson/lesson.py @@ -92,7 +92,7 @@ def update_progress(lesson): course_progress.save(ignore_permissions=True) def all_dynamic_content_submitted(lesson, user): - exercise_names = frappe.get_list("Exercise", {"lesson": lesson}, pluck="name") + exercise_names = frappe.get_list("Exercise", {"lesson": lesson}, pluck="name", ignore_permissions=True) all_exercises_submitted = False query = { "exercise": ["in", exercise_names], diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index 30e25b85..e4a35ad2 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -194,12 +194,16 @@ class LMSCourse(Document): def get_current_batch(self, member=frappe.session.user): current_membership = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name, "is_current": 1}, pluck="batch") + print(current_membership, member, self.name) if len(current_membership): return current_membership[0] + print(frappe.db.get_value("LMS Batch Membership", {"member": member, "course": self.name}, "batch")) return frappe.db.get_value("LMS Batch Membership", {"member": member, "course": self.name}, "batch") def get_all_memberships(self, member=frappe.session.user): + print(member) all_memberships = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name}, ["batch", "is_current"]) + print(all_memberships) for membership in all_memberships: membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") return all_memberships diff --git a/community/lms/widgets/ChapterTeaser.html b/community/lms/widgets/ChapterTeaser.html index 2d900a60..b0cf37c9 100644 --- a/community/lms/widgets/ChapterTeaser.html +++ b/community/lms/widgets/ChapterTeaser.html @@ -45,7 +45,9 @@ } window.checkout_upcoming_batches = () => { - $('html,body').animate({scrollTop: $(".upcoming").offset().top}, 300); + if ($(".upcoming").length > 0) { + $('html,body').animate({ scrollTop: $(".upcoming").offset().top }, 300); + } frappe.hide_msgprint(); } }) diff --git a/community/www/batch/discuss.py b/community/www/batch/discuss.py index 5da3db2d..95ffcb34 100644 --- a/community/www/batch/discuss.py +++ b/community/www/batch/discuss.py @@ -4,3 +4,5 @@ from . import utils def get_context(context): utils.get_common_context(context) context.messages = context.batch.get_messages() + if not context.batch: + utils.redirect_to_lesson(context.course) diff --git a/community/www/batch/home.html b/community/www/batch/home.html index a1f6a4a9..4b930430 100644 --- a/community/www/batch/home.html +++ b/community/www/batch/home.html @@ -8,7 +8,7 @@ {% endblock %} {% block content %} -{% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/" + batch.name + "/join" %} +{% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/join?batch=" + batch.name %}
{{ widgets.BatchTabs(course=course, batch=batch) }}