From 5e973b21ae3a0b13442a89095cb60cc8ad5b7253 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 7 Mar 2022 18:21:11 +0530 Subject: [PATCH 1/5] feat: course web form --- school/lms/doctype/lms_course/lms_course.json | 17 ++- school/lms/web_form/course/__init__.py | 0 school/lms/web_form/course/course.js | 3 + school/lms/web_form/course/course.json | 125 ++++++++++++++++++ school/lms/web_form/course/course.py | 5 + 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 school/lms/web_form/course/__init__.py create mode 100644 school/lms/web_form/course/course.js create mode 100644 school/lms/web_form/course/course.json create mode 100644 school/lms/web_form/course/course.py diff --git a/school/lms/doctype/lms_course/lms_course.json b/school/lms/doctype/lms_course/lms_course.json index 84abccb2..61ce2ca7 100644 --- a/school/lms/doctype/lms_course/lms_course.json +++ b/school/lms/doctype/lms_course/lms_course.json @@ -10,7 +10,7 @@ "allow_guest_to_view": 1, "allow_import": 1, "allow_rename": 1, - "creation": "2022-02-08 16:34:42.721203", + "creation": "2022-02-22 15:28:26.091549", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", @@ -174,7 +174,7 @@ "link_fieldname": "course" } ], - "modified": "2022-02-16 11:50:20.661085", + "modified": "2022-03-07 14:47:51.745509", "modified_by": "Administrator", "module": "LMS", "name": "LMS Course", @@ -191,6 +191,19 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "email": 1, + "export": 1, + "if_owner": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "select": 1, + "share": 1, + "write": 1 } ], "search_fields": "title", diff --git a/school/lms/web_form/course/__init__.py b/school/lms/web_form/course/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/school/lms/web_form/course/course.js b/school/lms/web_form/course/course.js new file mode 100644 index 00000000..699703c5 --- /dev/null +++ b/school/lms/web_form/course/course.js @@ -0,0 +1,3 @@ +frappe.ready(function() { + // bind events here +}) \ No newline at end of file diff --git a/school/lms/web_form/course/course.json b/school/lms/web_form/course/course.json new file mode 100644 index 00000000..3c6df39c --- /dev/null +++ b/school/lms/web_form/course/course.json @@ -0,0 +1,125 @@ +{ + "accept_payment": 0, + "allow_comments": 0, + "allow_delete": 0, + "allow_edit": 1, + "allow_incomplete": 0, + "allow_multiple": 1, + "allow_print": 0, + "amount": 0.0, + "amount_based_on_field": 0, + "apply_document_permissions": 1, + "button_label": "Save", + "creation": "2022-03-07 14:40:41.262163", + "custom_css": "", + "doc_type": "LMS Course", + "docstatus": 0, + "doctype": "Web Form", + "idx": 0, + "is_multi_step_form": 0, + "is_standard": 1, + "login_required": 1, + "max_attachment_size": 0, + "modified": "2022-03-07 14:48:04.889844", + "modified_by": "Administrator", + "module": "LMS", + "name": "course", + "owner": "Administrator", + "payment_button_label": "Buy Now", + "published": 1, + "route": "course", + "route_to_success_link": 0, + "show_attachments": 0, + "show_in_grid": 0, + "show_sidebar": 0, + "sidebar_items": [], + "success_url": "/course", + "title": "Course", + "web_form_fields": [ + { + "allow_read_on_all_link_options": 0, + "fieldname": "title", + "fieldtype": "Data", + "hidden": 0, + "label": "Title", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "video_link", + "fieldtype": "Data", + "hidden": 0, + "label": "Video Embed Link", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "image", + "fieldtype": "Attach Image", + "hidden": 0, + "label": "Preview Image", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "tags", + "fieldtype": "Data", + "hidden": 0, + "label": "Tags", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "short_introduction", + "fieldtype": "Small Text", + "hidden": 0, + "label": "Short Introduction", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "description", + "fieldtype": "Data", + "hidden": 0, + "label": "Description", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "chapters", + "fieldtype": "Table", + "hidden": 0, + "label": "Chapters", + "max_length": 0, + "max_value": 0, + "options": "Chapter Reference", + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + } + ] +} \ No newline at end of file diff --git a/school/lms/web_form/course/course.py b/school/lms/web_form/course/course.py new file mode 100644 index 00000000..e1ada619 --- /dev/null +++ b/school/lms/web_form/course/course.py @@ -0,0 +1,5 @@ +import frappe + +def get_context(context): + # do your magic here + pass From 8f9cd729758782afbe7416814c0a2ee2a6262c95 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Wed, 9 Mar 2022 12:29:03 +0530 Subject: [PATCH 2/5] feat: course creation from ui --- .../course_chapter/course_chapter.json | 18 +++- .../doctype/course_lesson/course_lesson.json | 21 ++++- .../doctype/course_lesson/course_lesson.py | 12 ++- school/lms/doctype/lms_course/lms_course.json | 5 +- school/lms/web_form/chapter/__init__.py | 0 school/lms/web_form/chapter/chapter.js | 3 + school/lms/web_form/chapter/chapter.json | 89 ++++++++++++++++++ school/lms/web_form/chapter/chapter.py | 5 + school/lms/web_form/course/course.js | 8 +- school/lms/web_form/course/course.json | 30 +++++- school/lms/web_form/lesson/__init__.py | 0 school/lms/web_form/lesson/lesson.js | 17 ++++ school/lms/web_form/lesson/lesson.json | 91 +++++++++++++++++++ school/lms/web_form/lesson/lesson.py | 5 + school/www/batch/learn.html | 5 +- school/www/courses/course.html | 7 ++ 16 files changed, 300 insertions(+), 16 deletions(-) create mode 100644 school/lms/web_form/chapter/__init__.py create mode 100644 school/lms/web_form/chapter/chapter.js create mode 100644 school/lms/web_form/chapter/chapter.json create mode 100644 school/lms/web_form/chapter/chapter.py create mode 100644 school/lms/web_form/lesson/__init__.py create mode 100644 school/lms/web_form/lesson/lesson.js create mode 100644 school/lms/web_form/lesson/lesson.json create mode 100644 school/lms/web_form/lesson/lesson.py diff --git a/school/lms/doctype/course_chapter/course_chapter.json b/school/lms/doctype/course_chapter/course_chapter.json index 7dca741a..1b5395c0 100644 --- a/school/lms/doctype/course_chapter/course_chapter.json +++ b/school/lms/doctype/course_chapter/course_chapter.json @@ -59,7 +59,7 @@ "link_fieldname": "chapter" } ], - "modified": "2021-09-29 15:33:44.611229", + "modified": "2022-03-08 15:21:10.389729", "modified_by": "Administrator", "module": "LMS", "name": "Course Chapter", @@ -77,11 +77,25 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "email": 1, + "export": 1, + "if_owner": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "select": 1, + "share": 1, + "write": 1 } ], "search_fields": "title", "sort_field": "modified", "sort_order": "DESC", + "states": [], "title_field": "title", "track_changes": 1 -} +} \ No newline at end of file diff --git a/school/lms/doctype/course_lesson/course_lesson.json b/school/lms/doctype/course_lesson/course_lesson.json index d63eb69b..fd113a0c 100644 --- a/school/lms/doctype/course_lesson/course_lesson.json +++ b/school/lms/doctype/course_lesson/course_lesson.json @@ -1,6 +1,6 @@ { "actions": [], - "allow_import": 1, + "allow_events_in_timeline": 1, "allow_rename": 1, "autoname": "format:{####} {title}", "creation": "2021-05-03 06:21:12.995984", @@ -73,7 +73,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-10-11 15:07:38.134808", + "modified": "2022-03-08 17:56:50.504143", "modified_by": "Administrator", "module": "LMS", "name": "Course Lesson", @@ -89,11 +89,26 @@ "read": 1, "report": 1, "role": "System Manager", + "select": 1, + "share": 1, + "write": 1 + }, + { + "create": 1, + "email": 1, + "export": 1, + "if_owner": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "select": 1, "share": 1, "write": 1 } ], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 -} +} \ No newline at end of file diff --git a/school/lms/doctype/course_lesson/course_lesson.py b/school/lms/doctype/course_lesson/course_lesson.py index 38adb6a3..cd20613e 100644 --- a/school/lms/doctype/course_lesson/course_lesson.py +++ b/school/lms/doctype/course_lesson/course_lesson.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document from ...md import find_macros -from school.lms.utils import get_course_progress +from school.lms.utils import get_course_progress, get_lesson_url class CourseLesson(Document): def validate(self): @@ -108,3 +108,13 @@ def save_progress(lesson, course, status): progress = get_course_progress(course) frappe.db.set_value("LMS Batch Membership", membership, "progress", progress) return progress + +@frappe.whitelist() +def get_lesson_info(lesson_name): + chapter = frappe.db.get_value("Course Lesson", lesson_name, "chapter") + course = frappe.db.get_value("Course Chapter", chapter, "course") + + lesson_idx = frappe.db.get_value("Lesson Reference", {"lesson": lesson_name}, ["idx"]) + chapter_idx = frappe.db.get_value("Chapter Reference", {"chapter": chapter}, ["idx"]) + + return get_lesson_url(course, f"{chapter_idx}.{lesson_idx}") diff --git a/school/lms/doctype/lms_course/lms_course.json b/school/lms/doctype/lms_course/lms_course.json index 61ce2ca7..b40ac09b 100644 --- a/school/lms/doctype/lms_course/lms_course.json +++ b/school/lms/doctype/lms_course/lms_course.json @@ -7,7 +7,6 @@ "label": "Reindex Exercises" } ], - "allow_guest_to_view": 1, "allow_import": 1, "allow_rename": 1, "creation": "2022-02-22 15:28:26.091549", @@ -150,7 +149,6 @@ "options": "Related Courses" } ], - "index_web_pages_for_search": 1, "is_published_field": "is_published", "links": [ { @@ -174,7 +172,7 @@ "link_fieldname": "course" } ], - "modified": "2022-03-07 14:47:51.745509", + "modified": "2022-03-08 15:20:58.501082", "modified_by": "Administrator", "module": "LMS", "name": "LMS Course", @@ -189,6 +187,7 @@ "read": 1, "report": 1, "role": "System Manager", + "select": 1, "share": 1, "write": 1 }, diff --git a/school/lms/web_form/chapter/__init__.py b/school/lms/web_form/chapter/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/school/lms/web_form/chapter/chapter.js b/school/lms/web_form/chapter/chapter.js new file mode 100644 index 00000000..699703c5 --- /dev/null +++ b/school/lms/web_form/chapter/chapter.js @@ -0,0 +1,3 @@ +frappe.ready(function() { + // bind events here +}) \ No newline at end of file diff --git a/school/lms/web_form/chapter/chapter.json b/school/lms/web_form/chapter/chapter.json new file mode 100644 index 00000000..a1db2177 --- /dev/null +++ b/school/lms/web_form/chapter/chapter.json @@ -0,0 +1,89 @@ +{ + "accept_payment": 0, + "allow_comments": 0, + "allow_delete": 0, + "allow_edit": 1, + "allow_incomplete": 0, + "allow_multiple": 1, + "allow_print": 0, + "amount": 0.0, + "amount_based_on_field": 0, + "apply_document_permissions": 0, + "button_label": "Save", + "creation": "2022-03-07 18:41:07.058806", + "doc_type": "Course Chapter", + "docstatus": 0, + "doctype": "Web Form", + "idx": 0, + "is_multi_step_form": 0, + "is_standard": 1, + "login_required": 1, + "max_attachment_size": 0, + "modified": "2022-03-07 18:41:07.058806", + "modified_by": "Administrator", + "module": "LMS", + "name": "chapter", + "owner": "Administrator", + "payment_button_label": "Buy Now", + "published": 1, + "route": "chapter", + "route_to_success_link": 0, + "show_attachments": 0, + "show_in_grid": 0, + "show_sidebar": 0, + "sidebar_items": [], + "success_url": "/chapter", + "title": "Chapter", + "web_form_fields": [ + { + "allow_read_on_all_link_options": 0, + "fieldname": "course", + "fieldtype": "Link", + "hidden": 0, + "label": "Course", + "max_length": 0, + "max_value": 0, + "options": "LMS Course", + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "title", + "fieldtype": "Data", + "hidden": 0, + "label": "Title", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "description", + "fieldtype": "Small Text", + "hidden": 0, + "label": "Description", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "lessons", + "fieldtype": "Table", + "hidden": 0, + "label": "Lessons", + "max_length": 0, + "max_value": 0, + "options": "Lesson Reference", + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + } + ] +} \ No newline at end of file diff --git a/school/lms/web_form/chapter/chapter.py b/school/lms/web_form/chapter/chapter.py new file mode 100644 index 00000000..e1ada619 --- /dev/null +++ b/school/lms/web_form/chapter/chapter.py @@ -0,0 +1,5 @@ +import frappe + +def get_context(context): + # do your magic here + pass diff --git a/school/lms/web_form/course/course.js b/school/lms/web_form/course/course.js index 699703c5..23ad7a61 100644 --- a/school/lms/web_form/course/course.js +++ b/school/lms/web_form/course/course.js @@ -1,3 +1,7 @@ frappe.ready(function() { - // bind events here -}) \ No newline at end of file + frappe.web_form.after_save = () => { + setTimeout(() => { + window.location.href = `/courses/${frappe.web_form.doc.name}`; + }) + } +}); diff --git a/school/lms/web_form/course/course.json b/school/lms/web_form/course/course.json index 3c6df39c..01eb9e76 100644 --- a/school/lms/web_form/course/course.json +++ b/school/lms/web_form/course/course.json @@ -20,7 +20,7 @@ "is_standard": 1, "login_required": 1, "max_attachment_size": 0, - "modified": "2022-03-07 14:48:04.889844", + "modified": "2022-03-09 10:10:30.069458", "modified_by": "Administrator", "module": "LMS", "name": "course", @@ -48,6 +48,29 @@ "reqd": 1, "show_in_filter": 0 }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "tags", + "fieldtype": "Data", + "hidden": 0, + "label": "Tags", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "", + "fieldtype": "Column Break", + "hidden": 0, + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, { "allow_read_on_all_link_options": 0, "fieldname": "video_link", @@ -74,10 +97,9 @@ }, { "allow_read_on_all_link_options": 0, - "fieldname": "tags", - "fieldtype": "Data", + "fieldname": "", + "fieldtype": "Section Break", "hidden": 0, - "label": "Tags", "max_length": 0, "max_value": 0, "read_only": 0, diff --git a/school/lms/web_form/lesson/__init__.py b/school/lms/web_form/lesson/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/school/lms/web_form/lesson/lesson.js b/school/lms/web_form/lesson/lesson.js new file mode 100644 index 00000000..afc067af --- /dev/null +++ b/school/lms/web_form/lesson/lesson.js @@ -0,0 +1,17 @@ +frappe.ready(function() { + frappe.web_form.after_save = () => { + setTimeout(() => { + + frappe.call({ + method: "school.lms.doctype.course_lesson.course_lesson.get_lesson_info", + args: { + "lesson_name": frappe.web_form.doc.name + }, + callback: (data) => { + window.location.href = data.message; + } + }); + + }); + }; +}); diff --git a/school/lms/web_form/lesson/lesson.json b/school/lms/web_form/lesson/lesson.json new file mode 100644 index 00000000..0aebf239 --- /dev/null +++ b/school/lms/web_form/lesson/lesson.json @@ -0,0 +1,91 @@ +{ + "accept_payment": 0, + "allow_comments": 0, + "allow_delete": 0, + "allow_edit": 1, + "allow_incomplete": 0, + "allow_multiple": 1, + "allow_print": 0, + "amount": 0.0, + "amount_based_on_field": 0, + "apply_document_permissions": 1, + "button_label": "Save", + "creation": "2022-03-07 18:41:42.549831", + "custom_css": "", + "doc_type": "Course Lesson", + "docstatus": 0, + "doctype": "Web Form", + "idx": 0, + "introduction_text": "



Create lessons for your course. You can add some additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same.


Content TypeSyntax
Video{{ Video(\"url_of_source\") }}
YouTube Video{{ YouTubeVideo(\"unique_embed_id\") }}
Exercise{{ Exercise(\"exercise_name\") }}
Quiz{{ Quiz(\"lms_quiz_name\") }}
Assignment{{ Assignment(\"id-filetype\") }}
", + "is_multi_step_form": 0, + "is_standard": 1, + "login_required": 1, + "max_attachment_size": 0, + "modified": "2022-03-09 09:55:58.406164", + "modified_by": "Administrator", + "module": "LMS", + "name": "lesson", + "owner": "Administrator", + "payment_button_label": "Buy Now", + "published": 1, + "route": "lesson", + "route_to_success_link": 0, + "show_attachments": 0, + "show_in_grid": 0, + "show_sidebar": 0, + "sidebar_items": [], + "success_url": "/lesson", + "title": "Lesson", + "web_form_fields": [ + { + "allow_read_on_all_link_options": 1, + "fieldname": "chapter", + "fieldtype": "Link", + "hidden": 0, + "label": "Course Chapter", + "max_length": 0, + "max_value": 0, + "options": "Course Chapter", + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "title", + "fieldtype": "Data", + "hidden": 0, + "label": "Title", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "default": "0", + "fieldname": "include_in_preview", + "fieldtype": "Check", + "hidden": 0, + "label": "Include In Preview", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, + { + "allow_read_on_all_link_options": 0, + "fieldname": "body", + "fieldtype": "Data", + "hidden": 0, + "label": "Body", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + } + ] +} \ No newline at end of file diff --git a/school/lms/web_form/lesson/lesson.py b/school/lms/web_form/lesson/lesson.py new file mode 100644 index 00000000..e1ada619 --- /dev/null +++ b/school/lms/web_form/lesson/lesson.py @@ -0,0 +1,5 @@ +import frappe + +def get_context(context): + # do your magic here + pass diff --git a/school/www/batch/learn.html b/school/www/batch/learn.html index 34a5bd52..cc6258ea 100644 --- a/school/www/batch/learn.html +++ b/school/www/batch/learn.html @@ -42,10 +42,13 @@ {% if membership or is_instructor %} eligible-for-submission {% endif %}" data-lesson="{{ lesson.name }}" data-course="{{ course.name }}">{{ lesson.title }} COMPLETED + + {% if is_instructor %} + {{ _("Edit") }} + {% endif %}
- {% set instructors = instructors %} {% set ins_len = instructors | length %} {% for instructor in instructors %} {% if ins_len > 1 and loop.index == 1 %} diff --git a/school/www/courses/course.html b/school/www/courses/course.html index e76af9fa..2081ca52 100644 --- a/school/www/courses/course.html +++ b/school/www/courses/course.html @@ -1,9 +1,11 @@ {% extends "templates/base.html" %} {% block title %}{{ course.title }} {% endblock %} + {% block head_include %} {% endblock %} + {% block content %}
@@ -26,6 +28,11 @@ style=" {% if course.image %} background-position: center; background-size: cover; background-image: url({{ course.image }}); {% else %} background-color: var(--gray-200) {% endif %}">
+ {% if is_instructor(course.name) %} + {{ _("New Lesson") }} + {{ _("New Chapter") }} + {{ _("Edit") }} + {% endif %} {{ BreadCrumb(course) }} {{ CourseCardWide(course) }}
From c8af6d3672b07edc00b02988cac4cc71ad2e1a8a Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Fri, 11 Mar 2022 11:15:13 +0530 Subject: [PATCH 3/5] feat: course creation from portal setting --- school/lms/doctype/lms_settings/lms_settings.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/school/lms/doctype/lms_settings/lms_settings.json b/school/lms/doctype/lms_settings/lms_settings.json index 35c07925..752ac995 100644 --- a/school/lms/doctype/lms_settings/lms_settings.json +++ b/school/lms/doctype/lms_settings/lms_settings.json @@ -6,6 +6,7 @@ "engine": "InnoDB", "field_order": [ "show_search", + "portal_course_creation", "search_placeholder", "column_break_2", "force_profile_completion", @@ -101,12 +102,18 @@ { "fieldname": "column_break_12", "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "portal_course_creation", + "fieldtype": "Check", + "label": "Enable Course Creation from Portal" } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2022-02-23 16:15:28.586903", + "modified": "2022-03-10 18:45:58.372370", "modified_by": "Administrator", "module": "LMS", "name": "LMS Settings", @@ -127,4 +134,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} From 27e1aec001f481b6a7c2a677bdf79fbf65bac783 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Tue, 15 Mar 2022 16:51:39 +0530 Subject: [PATCH 4/5] fix: dashboard links, web form redirects and patch for status --- .../chapter_reference/chapter_reference.json | 5 +++- .../doctype/course_lesson/course_lesson.py | 10 ++------ .../lesson_reference/lesson_reference.json | 5 +++- school/lms/doctype/lms_course/lms_course.json | 6 +++-- school/lms/doctype/lms_course/lms_course.py | 2 +- school/lms/web_form/course/course.js | 3 ++- school/lms/web_form/lesson/lesson.js | 14 +++++++++-- school/lms/widgets/CourseCard.html | 8 +++--- school/overrides/user.py | 8 +++--- school/patches.txt | 1 + school/patches/v0_0/set_status_in_course.py | 7 ++++++ school/public/css/style.css | 17 +++++++------ school/templates/courses_created.html | 2 +- school/www/courses/course.html | 21 ++++++++++++---- school/www/courses/course.js | 1 + school/www/courses/course.py | 8 +++--- school/www/dashboard/index.html | 25 ++++++++++++++++--- school/www/profiles/profile.html | 2 +- 18 files changed, 99 insertions(+), 46 deletions(-) create mode 100644 school/patches/v0_0/set_status_in_course.py diff --git a/school/lms/doctype/chapter_reference/chapter_reference.json b/school/lms/doctype/chapter_reference/chapter_reference.json index a251b1a4..0c67d748 100644 --- a/school/lms/doctype/chapter_reference/chapter_reference.json +++ b/school/lms/doctype/chapter_reference/chapter_reference.json @@ -1,5 +1,6 @@ { "actions": [], + "autoname": "hash", "creation": "2021-07-27 16:25:02.903245", "doctype": "DocType", "editable_grid": 1, @@ -20,13 +21,15 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-09-30 10:35:30.014950", + "modified": "2022-03-15 09:39:41.937565", "modified_by": "Administrator", "module": "LMS", "name": "Chapter Reference", + "naming_rule": "Random", "owner": "Administrator", "permissions": [], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/school/lms/doctype/course_lesson/course_lesson.py b/school/lms/doctype/course_lesson/course_lesson.py index cd20613e..ee0023b6 100644 --- a/school/lms/doctype/course_lesson/course_lesson.py +++ b/school/lms/doctype/course_lesson/course_lesson.py @@ -110,11 +110,5 @@ def save_progress(lesson, course, status): return progress @frappe.whitelist() -def get_lesson_info(lesson_name): - chapter = frappe.db.get_value("Course Lesson", lesson_name, "chapter") - course = frappe.db.get_value("Course Chapter", chapter, "course") - - lesson_idx = frappe.db.get_value("Lesson Reference", {"lesson": lesson_name}, ["idx"]) - chapter_idx = frappe.db.get_value("Chapter Reference", {"chapter": chapter}, ["idx"]) - - return get_lesson_url(course, f"{chapter_idx}.{lesson_idx}") +def get_lesson_info(chapter): + return frappe.db.get_value("Course Chapter", chapter, "course") diff --git a/school/lms/doctype/lesson_reference/lesson_reference.json b/school/lms/doctype/lesson_reference/lesson_reference.json index a3e77ebb..86129694 100644 --- a/school/lms/doctype/lesson_reference/lesson_reference.json +++ b/school/lms/doctype/lesson_reference/lesson_reference.json @@ -1,5 +1,6 @@ { "actions": [], + "autoname": "hash", "creation": "2021-07-27 16:25:48.269536", "doctype": "DocType", "editable_grid": 1, @@ -20,13 +21,15 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-09-30 10:35:47.832547", + "modified": "2022-03-15 09:39:29.495991", "modified_by": "Administrator", "module": "LMS", "name": "Lesson Reference", + "naming_rule": "Random", "owner": "Administrator", "permissions": [], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/school/lms/doctype/lms_course/lms_course.json b/school/lms/doctype/lms_course/lms_course.json index dad39ff4..671e6efb 100644 --- a/school/lms/doctype/lms_course/lms_course.json +++ b/school/lms/doctype/lms_course/lms_course.json @@ -144,8 +144,10 @@ "fieldname": "status", "fieldtype": "Select", "hidden": 1, + "in_list_view": 1, + "in_standard_filter": 1, "label": "Status", - "options": "In Progress\nReady for Review\nApproved", + "options": "In Progress\nUnder Review\nApproved", "read_only": 1 }, { @@ -184,7 +186,7 @@ "link_fieldname": "course" } ], - "modified": "2022-03-14 17:56:46.514391", + "modified": "2022-03-15 10:16:53.796878", "modified_by": "Administrator", "module": "LMS", "name": "LMS Course", diff --git a/school/lms/doctype/lms_course/lms_course.py b/school/lms/doctype/lms_course/lms_course.py index de9bc76f..94648505 100644 --- a/school/lms/doctype/lms_course/lms_course.py +++ b/school/lms/doctype/lms_course/lms_course.py @@ -208,5 +208,5 @@ def submit_for_review(course): chapters = frappe.get_all("Chapter Reference", {"parent": course}) if not len(chapters): return "No Chp" - frappe.db.set_value("LMS Course", course, "status", "Ready for Review") + frappe.db.set_value("LMS Course", course, "status", "Under Review") return "OK" diff --git a/school/lms/web_form/course/course.js b/school/lms/web_form/course/course.js index 1aae8b5c..ff539e0a 100644 --- a/school/lms/web_form/course/course.js +++ b/school/lms/web_form/course/course.js @@ -1,5 +1,6 @@ frappe.ready(function() { frappe.web_form.after_save = () => { - window.location.href = `/dashboard#courses-created`; + let route = frappe.web_form.doc.name ? `/courses/${frappe.web_form.doc.name}` : `/course`; + window.location.href = route; } }); diff --git a/school/lms/web_form/lesson/lesson.js b/school/lms/web_form/lesson/lesson.js index 49c264fd..bf3a24c8 100644 --- a/school/lms/web_form/lesson/lesson.js +++ b/school/lms/web_form/lesson/lesson.js @@ -1,5 +1,15 @@ frappe.ready(function() { - frappe.web_form.after_save = () => { - window.location.href = `/courses/` + frappe.web_form.after_save = () => { + setTimeout(() => { + frappe.call({ + method: "school.lms.doctype.course_lesson.course_lesson.get_lesson_info", + args: { + "chapter": frappe.web_form.doc.chapter + }, + callback: (data) => { + window.location.href = `/courses/${data.message}`; + } + }); + }); }; }); diff --git a/school/lms/widgets/CourseCard.html b/school/lms/widgets/CourseCard.html index 52f613ed..437d54ab 100644 --- a/school/lms/widgets/CourseCard.html +++ b/school/lms/widgets/CourseCard.html @@ -17,9 +17,11 @@
{% if get_lessons(course.name) | length %} - - {{ get_lessons(course.name) | length }} {{ _("Lessons") }} - + {{ get_lessons(course.name) | length }} {{ _("Lessons") }} + {% endif %} + {% if course.status and course.status != "Approved"%} + {% set pill_color = "gray" if course.status == "In Progress" else "orange" %} + {{ course.status }} {% endif %}
{{ course.title }}
diff --git a/school/overrides/user.py b/school/overrides/user.py index da199318..25bd819c 100644 --- a/school/overrides/user.py +++ b/school/overrides/user.py @@ -124,7 +124,7 @@ class CustomUser(User): def get_enrolled_courses(): in_progress = [] completed = [] - memberships = get_course_membership(member_type="Student") + memberships = get_course_membership(frappe.session.user, member_type="Student") for membership in memberships: course = frappe.db.get_value("LMS Course", membership.course, ["name", "upcoming", "title", "image", "enable_certification"], as_dict=True) @@ -139,7 +139,7 @@ def get_enrolled_courses(): "completed": completed } -def get_course_membership(member=frappe.session.user, member_type=None): +def get_course_membership(member, member_type=None): """ Returns all memberships of the user """ filters = { "member": member @@ -150,7 +150,7 @@ def get_course_membership(member=frappe.session.user, member_type=None): return frappe.get_all("LMS Batch Membership", filters, ["name", "course", "progress"]) -def get_authored_courses(member=frappe.session.user, only_published=True): +def get_authored_courses(member, only_published=True): """Returns the number of courses authored by this user. """ course_details = [] @@ -164,7 +164,7 @@ def get_authored_courses(member=frappe.session.user, only_published=True): for course in courses: course_details.append(frappe.db.get_value("LMS Course", course, - ["name", "upcoming", "title", "image", "enable_certification"], as_dict=True)) + ["name", "upcoming", "title", "image", "enable_certification", "status"], as_dict=True)) return course_details diff --git a/school/patches.txt b/school/patches.txt index a0a0de43..53e9fff4 100644 --- a/school/patches.txt +++ b/school/patches.txt @@ -23,3 +23,4 @@ execute:frappe.delete_doc("Workspace", "LMS", ignore_missing=True, force=True) # execute:frappe.delete_doc("Custom Field", "User-verify_age", ignore_missing=True, force=True) school.patches.v0_0.multiple_instructors #11-02-2022 school.patches.v0_0.set_course_in_lesson #14-03-2022 +school.patches.v0_0.set_status_in_course diff --git a/school/patches/v0_0/set_status_in_course.py b/school/patches/v0_0/set_status_in_course.py new file mode 100644 index 00000000..e8f54c1a --- /dev/null +++ b/school/patches/v0_0/set_status_in_course.py @@ -0,0 +1,7 @@ +import frappe + +def execute(): + courses = frappe.get_all("LMS Course", {"status": ("is", "not set")}, ["name", "is_published"]) + for course in courses: + status = "Approved" if course.is_published else "In Progress" + frappe.db.set_value("LMS Course", course.name, "status", status) diff --git a/school/public/css/style.css b/school/public/css/style.css index 8ad21492..f4266417 100644 --- a/school/public/css/style.css +++ b/school/public/css/style.css @@ -73,7 +73,7 @@ input[type=checkbox] { } .common-page-style { - padding: 4rem 0 5rem; + padding: 2rem 0 5rem; min-height: 60vh; font-size: var(--text-base); } @@ -347,7 +347,7 @@ input[type=checkbox] { .is-secondary { background: #FFFFFF; - color: inherit; + color: var(--gray-900); } .is-secondary:hover { @@ -357,7 +357,7 @@ input[type=checkbox] { .is-default { background: var(--gray-100); - color: var(--gray-700); + color: var(--gray-900); } .is-default:disabled { @@ -1238,7 +1238,6 @@ pre { } .course-intructor-rating-section .seperator::before { - content: "\00B7"; margin: 0 0.25rem; } } @@ -1428,8 +1427,8 @@ pre { } .dashboard .nav-link { - color: var(--text-muted); - padding: var(--padding-md) 0; + color: var(--text-muted); + padding: 0 0 var(--padding-md); margin-right: var(--margin-xl); } @@ -1443,6 +1442,8 @@ pre { color: inherit; } -.dashboard .nav { - border-bottom: 1px solid var(--border-color); +.dashboard-button { + position: relative; + top: -50px; + margin-left: auto; } diff --git a/school/templates/courses_created.html b/school/templates/courses_created.html index 434474ad..5977fee0 100644 --- a/school/templates/courses_created.html +++ b/school/templates/courses_created.html @@ -1,4 +1,4 @@ -{% set courses = get_authored_courses(only_published=False) %} +{% set courses = get_authored_courses(frappe.session.user, only_published=False) %} {% if courses | length %}
{% for course in courses %} diff --git a/school/www/courses/course.html b/school/www/courses/course.html index f6225b0f..09bd2aa0 100644 --- a/school/www/courses/course.html +++ b/school/www/courses/course.html @@ -29,8 +29,14 @@ {% else %} background-color: var(--gray-200) {% endif %}">
{% if is_instructor(course.name) %} - {{ _("New Lesson") }} - {{ _("New Chapter") }} + + + {{ _("Add Lesson") }} + + + + {{ _("Add Chapter") }} + {{ _("Edit") }} {% endif %} {{ BreadCrumb(course) }} @@ -131,9 +137,15 @@
{{ course.title }}
- You have opted to be notified for this course. You will receive an email when the course becomes available. + {{ _("You have opted to be notified for this course. You will receive an email when the course becomes available.") }}
+ {% if course.status == "Under Review" %} +
+ {{ _("Your course is currently under review. Once the review is complete, the System Admins will publish it on the website.") }} +
+ {% endif %} + {% if get_lessons(course.name) | length %}
@@ -162,14 +174,13 @@ {% set lesson_index = get_lesson_index(membership.current_lesson) if membership and membership.current_lesson else '1.1' %} - {% if show_start_learing_cta %}
{{ _("Start Learning") }}
- {% elif is_instructor(course.name) and not course.is_published and status != "Ready for Review" %} + {% elif is_instructor(course.name) and not course.is_published and course.status != "Under Review" %}
{{ _("Submit for Review") }} diff --git a/school/www/courses/course.js b/school/www/courses/course.js index 66ae4c82..67447feb 100644 --- a/school/www/courses/course.js +++ b/school/www/courses/course.js @@ -274,6 +274,7 @@ const submit_for_review = (e) => { Please add chapters and lessons to your course before you submit it for review.`)); } else if (data.message == "OK") { frappe.msgprint(__("Your course has been submitted for review.")) + window.location.reload(); } } }) diff --git a/school/www/courses/course.py b/school/www/courses/course.py index 70818259..b8bfc35a 100644 --- a/school/www/courses/course.py +++ b/school/www/courses/course.py @@ -13,7 +13,7 @@ def get_context(context): course = frappe.db.get_value("LMS Course", course_name, ["name", "title", "image", "short_introduction", "description", "is_published", "upcoming", - "disable_self_learning", "video_link", "enable_certification"], + "disable_self_learning", "video_link", "enable_certification", "status"], as_dict=True) related_courses = frappe.get_all("Related Courses", {"parent": course.name}, ["course"]) @@ -33,7 +33,7 @@ def get_context(context): if context.course.upcoming: context.is_user_interested = get_user_interest(context.course.name) context.restriction = check_profile_restriction() - context.show_start_learing_cta = show_start_learing_cta(course, membership) + context.show_start_learing_cta = show_start_learing_cta(course, membership, context.restriction) context.metatags = { "title": course.title, "image": course.image, @@ -48,5 +48,5 @@ def get_user_interest(course): "user": frappe.session.user }) -def show_start_learing_cta(course, membership): - return not course.disable_self_learning and not membership and not course.upcoming and not restriction.restrict and not is_instructor(course.name) +def show_start_learing_cta(course, membership, restriction): + return not course.disable_self_learning and not membership and not course.upcoming and not restriction.get("restrict") and not is_instructor(course.name) diff --git a/school/www/dashboard/index.html b/school/www/dashboard/index.html index 23bf4ef7..c643915d 100644 --- a/school/www/dashboard/index.html +++ b/school/www/dashboard/index.html @@ -3,23 +3,32 @@ {% endblock %} {% block content %} +{% set portal_course_creation = frappe.db.get_single_value("LMS Settings", "portal_course_creation") %}
-