From 01a1632a5ad672db8077f30a94d1b0f11d53f2fd Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Wed, 16 Aug 2023 22:01:59 +0530 Subject: [PATCH 1/4] feat: course filters --- lms/lms/widgets/CourseCard.html | 13 ++++++------- lms/overrides/user.py | 14 ++++++++++++-- lms/public/css/style.css | 21 +++++++++++++++------ lms/public/js/common_functions.js | 18 ++++++++++++++++++ lms/templates/course_list.html | 2 +- lms/www/courses/index.html | 20 ++++++++++++++++++-- lms/www/courses/index.py | 10 ++++++++++ 7 files changed, 80 insertions(+), 18 deletions(-) diff --git a/lms/lms/widgets/CourseCard.html b/lms/lms/widgets/CourseCard.html index c17422bb..144be5d5 100644 --- a/lms/lms/widgets/CourseCard.html +++ b/lms/lms/widgets/CourseCard.html @@ -8,7 +8,8 @@ {% endif %} -
+
@@ -40,23 +41,21 @@
{{ course.status }}
{% endif %} - {% set student_count = get_students(course.name) | length %} - {% set avg_rating = get_average_rating(course.name) %} - {% if student_count %} + {% if course.enrollment_count %}
- {{ student_count }} + {{ course.enrollment_count }}
{% endif %} - {% if avg_rating %} + {% if course.avg_rating %}
- {{ frappe.utils.flt(avg_rating, frappe.get_system_settings("float_precision") or 3) }} + {{ frappe.utils.flt(course.avg_rating, frappe.get_system_settings("float_precision") or 3) }}
{% endif %} diff --git a/lms/overrides/user.py b/lms/overrides/user.py index 6cfa186d..b561bc0e 100644 --- a/lms/overrides/user.py +++ b/lms/overrides/user.py @@ -5,7 +5,7 @@ from frappe import _ from frappe.core.doctype.user.user import User from frappe.utils import cint, escape_html, random_string from frappe.website.utils import is_signup_disabled -from lms.lms.utils import validate_image +from lms.lms.utils import validate_image, get_average_rating from frappe.website.utils import cleanup_page_name from frappe.model.naming import append_number_if_name_exists from lms.widgets import Widgets @@ -107,11 +107,16 @@ def get_enrolled_courses(): "price_certificate", "currency", "published", + "creation", ], as_dict=True, ) if not course.published: continue + course.enrollment_count = frappe.db.count( + "LMS Batch Membership", {"course": course.name, "member_type": "Student"} + ) + course.avg_rating = get_average_rating(course.name) or 0 progress = cint(membership.progress) if progress < 100: in_progress.append(course) @@ -151,12 +156,17 @@ def get_authored_courses(member=None, only_published=True): "enable_certification", "status", "published", + "creation", ], as_dict=True, ) if only_published and detail and not detail.published: continue + detail.enrollment_count = frappe.db.count( + "LMS Batch Membership", {"course": detail.name, "member_type": "Student"} + ) + detail.avg_rating = get_average_rating(detail.name) or 0 course_details.append(detail) return course_details @@ -265,7 +275,7 @@ def on_session_creation(login_manager): @frappe.whitelist() -def search_users(start: int = 0, text: str=""): +def search_users(start: int = 0, text: str = ""): start = cint(start) search_text = frappe.db.escape(f"%{text}%") diff --git a/lms/public/css/style.css b/lms/public/css/style.css index 803fd9e0..803e2db5 100644 --- a/lms/public/css/style.css +++ b/lms/public/css/style.css @@ -1956,10 +1956,6 @@ select { -webkit-appearance: none; } -.course-list-cta { - float: right; -} - .modal-title { font-size: var(--text-lg) !important; } @@ -2027,15 +2023,24 @@ select { } .lms-menu { + background-color: var(--control-bg); + color: var(--text-color); + border: none; + border-radius: var(--border-radius); + padding: 0.15rem 0.5rem; + box-shadow: var(--btn-shadow); background-image: url(/assets/lms/icons/down-arrow.svg); background-position: right 0.5rem center; background-repeat: no-repeat; background-size: 0.75rem; - padding-right: 2.5rem; - text-align: left; + padding-right: 2rem; -webkit-print-color-adjust: exact; } +.lms-menu:focus-visible { + outline: var(--gray-500); +} + .clickable-row { cursor: pointer; } @@ -2278,4 +2283,8 @@ select { position: absolute; top: 0; left: 0; +} + +.course-filter { + } \ No newline at end of file diff --git a/lms/public/js/common_functions.js b/lms/public/js/common_functions.js index fc5cead8..c424f598 100644 --- a/lms/public/js/common_functions.js +++ b/lms/public/js/common_functions.js @@ -40,6 +40,10 @@ frappe.ready(() => { $("#create-class").click((e) => { open_class_dialog(e); }); + + $("#course-filter").change((e) => { + filter_courses(e); + }); }); const pin_header = () => { @@ -354,3 +358,17 @@ const save_class = (values) => { }, }); }; + +const filter_courses = (e) => { + const course_lists = $(".course-cards-parent"); + const filter = $(e.currentTarget).val(); + course_lists.each((i, list) => { + const course_cards = $(list).children(".course-card"); + course_cards.sort((a, b) => { + var value1 = $(a).data(filter); + var value2 = $(b).data(filter); + return value1 > value2 ? -1 : value1 < value2 ? 1 : 0; + }); + $(list).append(course_cards); + }); +}; diff --git a/lms/templates/course_list.html b/lms/templates/course_list.html index d0bab41d..459eddb7 100644 --- a/lms/templates/course_list.html +++ b/lms/templates/course_list.html @@ -1,6 +1,6 @@
{% if courses | length %} -
+
{% for course in courses %} {{ widgets.CourseCard(course=course, read_only=False) }} {% endfor %} diff --git a/lms/www/courses/index.html b/lms/www/courses/index.html index a9713a9d..98e69e88 100644 --- a/lms/www/courses/index.html +++ b/lms/www/courses/index.html @@ -24,9 +24,25 @@ {% include "lms/templates/search_course/search_course.html" %} -
+
+ + + {% if frappe.session.user != "Guest" %} - + {{ _("My Profile") }} {% endif %} diff --git a/lms/www/courses/index.py b/lms/www/courses/index.py index 844d485f..6e1cafd2 100644 --- a/lms/www/courses/index.py +++ b/lms/www/courses/index.py @@ -6,6 +6,7 @@ from lms.lms.utils import ( get_restriction_details, has_course_moderator_role, get_courses_under_review, + get_average_rating, ) from lms.overrides.user import get_enrolled_courses, get_authored_courses @@ -49,13 +50,22 @@ def get_courses(): "paid_certificate", "price_certificate", "currency", + "creation", ], ) live_courses, upcoming_courses = [], [] for course in courses: + course.enrollment_count = frappe.db.count( + "LMS Batch Membership", {"course": course.name, "member_type": "Student"} + ) + course.avg_rating = get_average_rating(course.name) or 0 if course.upcoming: upcoming_courses.append(course) else: live_courses.append(course) + + live_courses.sort(key=lambda x: x.enrollment_count, reverse=True) + upcoming_courses.sort(key=lambda x: x.enrollment_count, reverse=True) + return live_courses, upcoming_courses From a061a89ee70d60262647cc27c6a7e4eef339f81b Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Aug 2023 22:06:25 +0530 Subject: [PATCH 2/4] fix: paid course details on course card template --- lms/lms/web_template/course_cards/course_cards.html | 2 +- lms/www/courses/course.html | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lms/lms/web_template/course_cards/course_cards.html b/lms/lms/web_template/course_cards/course_cards.html index 0567cf2a..6cf8974b 100644 --- a/lms/lms/web_template/course_cards/course_cards.html +++ b/lms/lms/web_template/course_cards/course_cards.html @@ -7,7 +7,7 @@ {% for course_row in courses %} {% set course = frappe.db.get_value("LMS Course", course_row.course, ["name", "short_introduction", "upcoming", "title", "image", "currency", - "enable_certification", "paid_certificate", "price_certificate"], as_dict=True) %} + "enable_certification", "paid_course", "course_price"], as_dict=True) %} {{ widgets.CourseCard(course=course, read_only=False) }} {% endfor %}
diff --git a/lms/www/courses/course.html b/lms/www/courses/course.html index 202eb4eb..cd294edd 100644 --- a/lms/www/courses/course.html +++ b/lms/www/courses/course.html @@ -122,9 +122,11 @@ {{ Notes(course) }} + {% if course.paid_course %}
{{ frappe.utils.fmt_money(course.course_price, 0, course.currency) }}
+ {% endif %}
From 982d6c9045d06b73c51c8244ccbb2cf148cb4cae Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Fri, 18 Aug 2023 12:39:19 +0530 Subject: [PATCH 3/4] fix: popularity filter for enrolled and authored courses --- lms/overrides/user.py | 4 ++++ lms/www/profiles/profile.html | 20 +++++++++++--------- lms/www/profiles/profile.py | 12 +++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lms/overrides/user.py b/lms/overrides/user.py index 17e55859..def4ac3d 100644 --- a/lms/overrides/user.py +++ b/lms/overrides/user.py @@ -123,6 +123,9 @@ def get_enrolled_courses(): else: completed.append(course) + in_progress.sort(key=lambda x: x.enrollment_count, reverse=True) + completed.sort(key=lambda x: x.enrollment_count, reverse=True) + return {"in_progress": in_progress, "completed": completed} @@ -171,6 +174,7 @@ def get_authored_courses(member=None, only_published=True): detail.avg_rating = get_average_rating(detail.name) or 0 course_details.append(detail) + course_details.sort(key=lambda x: x.enrollment_count, reverse=True) return course_details diff --git a/lms/www/profiles/profile.html b/lms/www/profiles/profile.html index 44a3f010..640493db 100644 --- a/lms/www/profiles/profile.html +++ b/lms/www/profiles/profile.html @@ -5,11 +5,6 @@ {% block content %} -{% set read_only = member.name != frappe.session.user %} -{% set user = member.name %} -{% set courses_created = get_authored_courses(member.name, True) %} -{% set certificates = get_certificates(user) %} -
{{ ProfileBanner(member) }}
@@ -82,14 +77,19 @@ {% if not read_only %}
- {% include "lms/lms/web_template/courses_enrolled/courses_enrolled.html" %} + {% set courses = enrolled_courses %} + {% set title = _("Enrolled Courses") %} + {% set classes = "enrolled-courses" %} + {% include "lms/templates/course_list.html" %}
{% endif %} {% if courses_created | length %} - {% set only_published = True %}
- {% include "lms/templates/courses_created.html" %} + {% set courses = courses_created %} + {% set title = _("Created Courses") %} + {% set classes = "created-courses" %} + {% include "lms/templates/course_list.html" %}
{% endif %} @@ -249,7 +249,9 @@ {% macro CareerPreference(member) %} {% if member.preferred_functions or member.preferred_industries or member.preferred_location or member.dream_companies %} -
{{ _("Career Preference") }}
+
+ {{ _("Career Preference") }} +
{% if member.preferred_functions | length %} diff --git a/lms/www/profiles/profile.py b/lms/www/profiles/profile.py index a4af31a0..6bd97e70 100644 --- a/lms/www/profiles/profile.py +++ b/lms/www/profiles/profile.py @@ -1,7 +1,8 @@ import frappe -from lms.lms.utils import get_lesson_index +from lms.lms.utils import get_lesson_index, get_certificates from lms.page_renderers import get_profile_url_prefix +from lms.overrides.user import get_authored_courses, get_enrolled_courses def get_context(context): @@ -9,14 +10,23 @@ def get_context(context): try: username = frappe.form_dict["username"] + print("username", username) except KeyError: username = frappe.db.get_value("User", frappe.session.user, ["username"]) + print("except", username) if username: frappe.local.flags.redirect_location = get_profile_url_prefix() + username raise frappe.Redirect try: + print(username) context.member = frappe.get_doc("User", {"username": username}) + context.courses_created = get_authored_courses(context.member.name, True) + context.enrolled_courses = ( + get_enrolled_courses()["in_progress"] + get_enrolled_courses()["completed"] + ) + context.read_only = frappe.session.user != context.member.name + context.certificates = get_certificates(context.member.name) except Exception: context.template = "www/404.html" return From fb3e0832d6a4350fed54bb0c6022320a00cfbcc7 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Fri, 18 Aug 2023 12:49:43 +0530 Subject: [PATCH 4/4] chore: removed unnecessary print statements --- lms/www/profiles/profile.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lms/www/profiles/profile.py b/lms/www/profiles/profile.py index 6bd97e70..4fef8a77 100644 --- a/lms/www/profiles/profile.py +++ b/lms/www/profiles/profile.py @@ -10,16 +10,13 @@ def get_context(context): try: username = frappe.form_dict["username"] - print("username", username) except KeyError: username = frappe.db.get_value("User", frappe.session.user, ["username"]) - print("except", username) if username: frappe.local.flags.redirect_location = get_profile_url_prefix() + username raise frappe.Redirect try: - print(username) context.member = frappe.get_doc("User", {"username": username}) context.courses_created = get_authored_courses(context.member.name, True) context.enrolled_courses = (