feat: course filters

This commit is contained in:
Jannat Patel
2023-08-16 22:01:59 +05:30
parent d90bb1e5ea
commit 01a1632a5a
7 changed files with 80 additions and 18 deletions

View File

@@ -8,7 +8,8 @@
{% endif %} {% endif %}
<div class="common-card-style course-card" data-course="{{ course.name }}"> <div class="common-card-style course-card" data-course="{{ course.name }}" data-rating="{{ course.avg_rating }}"
data-enrollment="{{ course.enrollment_count }}" data-creation="{{ course.creation }}">
<div class="course-image {% if not course.image %} default-image {% endif %}" <div class="course-image {% if not course.image %} default-image {% endif %}"
{% if course.image %} style="background-image: url( {{ course.image | urlencode }} );" {% endif %}> {% if course.image %} style="background-image: url( {{ course.image | urlencode }} );" {% endif %}>
@@ -40,23 +41,21 @@
<div class="pull-right indicator-pill {{ pill_color }} "> {{ course.status }} </div> <div class="pull-right indicator-pill {{ pill_color }} "> {{ course.status }} </div>
{% endif %} {% endif %}
{% set student_count = get_students(course.name) | length %} {% if course.enrollment_count %}
{% set avg_rating = get_average_rating(course.name) %}
{% if student_count %}
<div class="vertically-center"> <div class="vertically-center">
<svg class="icon icon-md"> <svg class="icon icon-md">
<use class="" href="#icon-users"> <use class="" href="#icon-users">
</svg> </svg>
{{ student_count }} {{ course.enrollment_count }}
</div> </div>
{% endif %} {% endif %}
{% if avg_rating %} {% if course.avg_rating %}
<div class="vertically-center"> <div class="vertically-center">
<svg class="icon icon-md"> <svg class="icon icon-md">
<use href="#icon-star"></use> <use href="#icon-star"></use>
</svg> </svg>
{{ 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) }}
</div> </div>
{% endif %} {% endif %}

View File

@@ -5,7 +5,7 @@ from frappe import _
from frappe.core.doctype.user.user import User from frappe.core.doctype.user.user import User
from frappe.utils import cint, escape_html, random_string from frappe.utils import cint, escape_html, random_string
from frappe.website.utils import is_signup_disabled 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.website.utils import cleanup_page_name
from frappe.model.naming import append_number_if_name_exists from frappe.model.naming import append_number_if_name_exists
from lms.widgets import Widgets from lms.widgets import Widgets
@@ -107,11 +107,16 @@ def get_enrolled_courses():
"price_certificate", "price_certificate",
"currency", "currency",
"published", "published",
"creation",
], ],
as_dict=True, as_dict=True,
) )
if not course.published: if not course.published:
continue 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) progress = cint(membership.progress)
if progress < 100: if progress < 100:
in_progress.append(course) in_progress.append(course)
@@ -151,12 +156,17 @@ def get_authored_courses(member=None, only_published=True):
"enable_certification", "enable_certification",
"status", "status",
"published", "published",
"creation",
], ],
as_dict=True, as_dict=True,
) )
if only_published and detail and not detail.published: if only_published and detail and not detail.published:
continue 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) course_details.append(detail)
return course_details return course_details

View File

@@ -1956,10 +1956,6 @@ select {
-webkit-appearance: none; -webkit-appearance: none;
} }
.course-list-cta {
float: right;
}
.modal-title { .modal-title {
font-size: var(--text-lg) !important; font-size: var(--text-lg) !important;
} }
@@ -2027,15 +2023,24 @@ select {
} }
.lms-menu { .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-image: url(/assets/lms/icons/down-arrow.svg);
background-position: right 0.5rem center; background-position: right 0.5rem center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 0.75rem; background-size: 0.75rem;
padding-right: 2.5rem; padding-right: 2rem;
text-align: left;
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
} }
.lms-menu:focus-visible {
outline: var(--gray-500);
}
.clickable-row { .clickable-row {
cursor: pointer; cursor: pointer;
} }
@@ -2279,3 +2284,7 @@ select {
top: 0; top: 0;
left: 0; left: 0;
} }
.course-filter {
}

View File

@@ -40,6 +40,10 @@ frappe.ready(() => {
$("#create-class").click((e) => { $("#create-class").click((e) => {
open_class_dialog(e); open_class_dialog(e);
}); });
$("#course-filter").change((e) => {
filter_courses(e);
});
}); });
const pin_header = () => { 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);
});
};

View File

@@ -1,6 +1,6 @@
<div class="{{ classes }}"> <div class="{{ classes }}">
{% if courses | length %} {% if courses | length %}
<div class="cards-parent"> <div class="course-cards-parent cards-parent">
{% for course in courses %} {% for course in courses %}
{{ widgets.CourseCard(course=course, read_only=False) }} {{ widgets.CourseCard(course=course, read_only=False) }}
{% endfor %} {% endfor %}

View File

@@ -24,9 +24,25 @@
{% include "lms/templates/search_course/search_course.html" %} {% include "lms/templates/search_course/search_course.html" %}
<div class="course-list-cta"> <div class="flex align-center pull-right">
<select class="lms-menu" id="course-filter">
<option disabled value="">
{{ _("Sort By") }}
</option>
<option selected value="enrollment">
{{ _("Most Popular") }}
</option>
<option value="rating">
{{ _("Highest Rated") }}
</option>
<option value="creation">
{{ _("Newest") }}
</option>
</select>
{% if frappe.session.user != "Guest" %} {% if frappe.session.user != "Guest" %}
<a class="btn btn-default btn-sm" href="/users"> <a class="btn btn-default btn-sm ml-2" href="/users">
{{ _("My Profile") }} {{ _("My Profile") }}
</a> </a>
{% endif %} {% endif %}

View File

@@ -6,6 +6,7 @@ from lms.lms.utils import (
get_restriction_details, get_restriction_details,
has_course_moderator_role, has_course_moderator_role,
get_courses_under_review, get_courses_under_review,
get_average_rating,
) )
from lms.overrides.user import get_enrolled_courses, get_authored_courses from lms.overrides.user import get_enrolled_courses, get_authored_courses
@@ -49,13 +50,22 @@ def get_courses():
"paid_certificate", "paid_certificate",
"price_certificate", "price_certificate",
"currency", "currency",
"creation",
], ],
) )
live_courses, upcoming_courses = [], [] live_courses, upcoming_courses = [], []
for course in 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: if course.upcoming:
upcoming_courses.append(course) upcoming_courses.append(course)
else: else:
live_courses.append(course) 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 return live_courses, upcoming_courses