diff --git a/community/hooks.py b/community/hooks.py index 40e0e8ba..8026dd8f 100644 --- a/community/hooks.py +++ b/community/hooks.py @@ -21,7 +21,7 @@ app_license = "AGPL" # include js, css files in header of web template web_include_css = "community.bundle.css" # web_include_css = "/assets/community/css/community.css" -# web_include_js = "/assets/community/js/community.js" +web_include_js = "website.bundle.js" # include custom scss in every website theme (without file extension ".scss") # website_theme_scss = "community/public/scss/website" @@ -141,6 +141,7 @@ website_route_rules = [ {"from_route": "/courses//learn/.", "to_route": "batch/learn"}, {"from_route": "/courses//progress", "to_route": "batch/progress"}, {"from_route": "/courses//join", "to_route": "batch/join"}, + {"from_route": "/users", "to_route": "profiles/profile"} ] website_redirects = [ @@ -150,6 +151,7 @@ website_redirects = [ update_website_context = [ 'community.widgets.update_website_context', ] + jinja = { "methods": [ "community.page_renderers.get_profile_url" diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index babbe45b..385bf762 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -187,20 +187,6 @@ class LMSCourse(Document): def get_slugified_chapter_title(self, chapter): return slugify(chapter) - def get_course_progress(self): - """ Returns the course progress of the session user """ - lesson_count = len(self.get_lessons()) - completed_lessons = frappe.db.count("LMS Course Progress", - { - "course": self.name, - "owner": frappe.session.user, - "status": "Complete" - }) - precision = cint(frappe.db.get_default("float_precision")) or 3 - if not lesson_count: - return 0 - return flt(((completed_lessons/lesson_count) * 100), precision) - def get_batch(self, batch_name): return find("LMS Batch", name=batch_name, course=self.name) @@ -340,6 +326,20 @@ class LMSCourse(Document): }, ["status"]) + def get_course_progress(self, member=None): + """ Returns the course progress of the session user """ + lesson_count = len(self.get_lessons()) + completed_lessons = frappe.db.count("LMS Course Progress", + { + "course": self.name, + "owner": member or frappe.session.user, + "status": "Complete" + }) + precision = cint(frappe.db.get_default("float_precision")) or 3 + if not lesson_count: + return 0 + return flt(((completed_lessons/lesson_count) * 100), precision) + def get_neighbours(self, current, lessons): current = flt(current) numbers = sorted(lesson.number for lesson in lessons) diff --git a/community/lms/web_template/course_cards/course_cards.html b/community/lms/web_template/course_cards/course_cards.html index 3e59bc97..437ab432 100644 --- a/community/lms/web_template/course_cards/course_cards.html +++ b/community/lms/web_template/course_cards/course_cards.html @@ -3,7 +3,7 @@
{% for course_row in courses %} {% set course = frappe.get_doc("LMS Course", course_row.course) %} - {{ widgets.CourseCard(course=course) }} + {{ widgets.CourseCard(course=course, read_only=False) }} {% endfor %}
diff --git a/community/lms/widgets/BatchHeader.html b/community/lms/widgets/BatchHeader.html deleted file mode 100644 index a6c99cdc..00000000 --- a/community/lms/widgets/BatchHeader.html +++ /dev/null @@ -1,4 +0,0 @@ -
-

{{batch_name}}

-
{{member_count}} members
-
diff --git a/community/lms/widgets/CourseCard.html b/community/lms/widgets/CourseCard.html index 8fe82fb4..3934316f 100644 --- a/community/lms/widgets/CourseCard.html +++ b/community/lms/widgets/CourseCard.html @@ -1,15 +1,26 @@ +{% set membership = course.get_membership(frappe.session.user) %} +{% set progress = course.get_course_progress() %}
+
{% for tag in course.get_tags() %}
{{ tag }}
{% endfor %} + {% if membership and not read_only %} + {% if progress < 100 %} +  
{{ frappe.utils.rounded(progress) }}% Completed
+ {% else %} +
Completed
+ {% endif %} + {% endif %}
{% if not course.image %}
{{ course.title[0] }}
{% endif %}
+
{% if course.get_chapters() | length %} @@ -27,37 +38,57 @@ {% endif %}
{{ course.title }}
-
-
- {{ widgets.Avatar(member=course.get_instructor(), avatar_class="avatar-small") }} - - {{ course.get_instructor().full_name }} +
+ + {{ widgets.Avatar(member=course.get_instructor(), avatar_class="avatar-small") }} + + + {{ course.get_instructor().full_name }} + + {% if course.get_students() | length %} {{ course.get_students() | length }} - - {% endif %} + {% endif %} {% set avg_rating = course.get_average_rating() %} {% if avg_rating %} - + {{ avg_rating }} {% endif %}
- {% set membership = course.get_membership(frappe.session.user) %} + + {% if not read_only %} {% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and - membership.current_lesson - else '1.1' %} + membership.current_lesson else '1.1' %} + {% set query_parameter = "?batch=" + membership.batch if membership and + membership.batch else "" %} + {% set certificate = course.is_certified() %} - {% set query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" %} + {% if certificate %} + + - {% if course.upcoming %} + {% elif course.enable_certification and progress == 100 %} + + + {% elif progress == 100 %} + + + + {% elif course.upcoming %} @@ -76,15 +107,39 @@ {% endif %} + {% endif %}
+ diff --git a/community/lms/widgets/InstructorSection.html b/community/lms/widgets/InstructorSection.html deleted file mode 100644 index c478e452..00000000 --- a/community/lms/widgets/InstructorSection.html +++ /dev/null @@ -1,6 +0,0 @@ -
- {{ widgets.Avatar(member=instructor, avatar_class="avatar-medium") }} - {{ instructor.full_name }} -
Course Creator
- -
diff --git a/community/overrides/user.py b/community/overrides/user.py index ffce3bb5..780400f9 100644 --- a/community/overrides/user.py +++ b/community/overrides/user.py @@ -124,3 +124,20 @@ class CustomUser(User): mentored_courses.append(map) return mentored_courses + + def get_enrolled_courses(self): + in_progress = [] + completed = [] + memberships = self.get_course_membership("Student"); + for membership in memberships: + course = frappe.get_doc("LMS Course", membership.course) + progress = course.get_course_progress(member=self.name) + if progress < 100: + in_progress.append(course) + else: + completed.append(course) + + return { + "in_progress": in_progress, + "completed": completed + } diff --git a/community/public/css/style.css b/community/public/css/style.css index f066ac34..e7e47d22 100644 --- a/community/public/css/style.css +++ b/community/public/css/style.css @@ -66,6 +66,7 @@ input[type=checkbox] { position: relative; top: 1rem; left: 1rem; + width: 95%; } .course-card-pills { @@ -75,7 +76,6 @@ input[type=checkbox] { border-radius: 4px; padding: 4px 6px; font-size: 10px; - line-height: 120%; text-align: center; letter-spacing: 0.011em; text-transform: uppercase; @@ -84,6 +84,15 @@ input[type=checkbox] { box-shadow: 0px 5px 10px rgb(0 0 0 / 10%); } +.dark-pills { + background: rgba(25, 39, 52, 0.8); + color: #ffffff; +} +.dark-pills img { + width: 0.75rem; + height: 0.75rem; +} + .common-page-style { background: #F4F5F6; padding-bottom: 5rem; @@ -102,7 +111,6 @@ input[type=checkbox] { .course-card { flex-direction: column; - height: 380px; } .muted-text { @@ -132,8 +140,8 @@ input[type=checkbox] { letter-spacing: -0.014em; color: var(--text-color); align-self: stretch; - margin-bottom: 16px; - height: 45px; + margin-bottom: 1.5rem; + height: 56px; } @media (max-width: 360px) { @@ -152,10 +160,6 @@ input[type=checkbox] { margin-bottom: 16px; } -.course-card-meta-2 { - margin-bottom: 16px; -} - .course-instructor { margin: 0px 8px; font-size: 12px; @@ -176,6 +180,7 @@ input[type=checkbox] { padding: 8px 0px 8px; text-align: center; line-height: 135%; + cursor: pointer; } .cards-parent { @@ -1149,13 +1154,18 @@ input[type=checkbox] { } } +.zindex { + position: relative; + z-index: 2; +} + .progress { width: 100%; height: 8px; } .progress-bar { - background-color: #318AD8; + background-color: var(--primary-color); } .progress-percentage { diff --git a/community/public/js/profile.js b/community/public/js/profile.js new file mode 100644 index 00000000..b3f4bc28 --- /dev/null +++ b/community/public/js/profile.js @@ -0,0 +1,6 @@ +frappe.ready(() => { + if (frappe.session.user == "Guest") { + var link_array = $('.nav-link').filter((i, elem) => $(elem).text().trim() === "My Profile"); + link_array.length && $(link_array[0]).addClass("hide"); + } +}) diff --git a/community/public/js/website.bundle.js b/community/public/js/website.bundle.js new file mode 100644 index 00000000..04d6b3fe --- /dev/null +++ b/community/public/js/website.bundle.js @@ -0,0 +1 @@ +import "./profile.js" diff --git a/community/www/courses/course.html b/community/www/courses/course.html index c22f0d52..645978a5 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -74,6 +74,7 @@
+{% if course.video_link %} +{% endif %} {% endmacro%} diff --git a/community/www/courses/index.html b/community/www/courses/index.html index 058dc87f..991108e5 100644 --- a/community/www/courses/index.html +++ b/community/www/courses/index.html @@ -14,7 +14,7 @@
{% for course in courses %} - {{ widgets.CourseCard(course=course) }} + {{ widgets.CourseCard(course=course, read_only=False) }} {% endfor %}
diff --git a/community/www/profiles/profile.html b/community/www/profiles/profile.html index 8ee9aeca..1d4bb37e 100644 --- a/community/www/profiles/profile.html +++ b/community/www/profiles/profile.html @@ -7,11 +7,12 @@ {% block content %}
+ {% set read_only = member.name != frappe.session.user %} {{ ProfileBanner(member) }} {{ AboutOverviewSection(member) }} - {{ CoursesCreated(member) }} - {{ CoursesMentored(member) }} - {{ CoursesEnrolled(member) }} + {{ CoursesEnrolled(member, read_only) }} + {{ CoursesCreated(member, read_only) }} + {{ CoursesMentored(member, read_only) }} {{ ProfileTabs(profile_tabs) }}
@@ -106,7 +107,7 @@ {% endmacro %} -{% macro CoursesCreated(member) %} +{% macro CoursesCreated(member, read_only) %} {% if member.get_authored_courses() | length %}
@@ -115,14 +116,14 @@
{% for course in member.get_authored_courses() %} {% set course_details = frappe.get_doc("LMS Course", course) %} - {{ widgets.CourseCard(course=course_details) }} + {{ widgets.CourseCard(course=course_details, read_only=read_only) }} {% endfor %}
{% endif %} {% endmacro %} -{% macro CoursesMentored(member) %} +{% macro CoursesMentored(member, read_only) %} {% if member.get_mentored_courses() | length %}
@@ -131,27 +132,42 @@
{% for mentorship in member.get_mentored_courses() %} {% set course_details = frappe.get_doc("LMS Course", mentorship.course) %} - {{ widgets.CourseCard(course=course_details) }} + {{ widgets.CourseCard(course=course_details, read_only=read_only) }} {% endfor %}
{% endif %} {% endmacro %} -{% macro CoursesEnrolled(member) %} -{% if member.get_course_membership("Student") | length %} +{% macro CoursesEnrolled(member, read_only) %} +{% set enrolled = member.get_enrolled_courses() %} + +{% if enrolled.completed | length %}
- Courses Enrolled + Courses Completed
- {% for membership in member.get_course_membership("Student") %} - {% set course_details = frappe.get_doc("LMS Course", membership.course) %} - {{ widgets.CourseCard(course=course_details) }} + {% for course in enrolled.completed %} + {{ widgets.CourseCard(course=course, read_only=read_only) }} {% endfor %}
{% endif %} + +{% if enrolled.in_progress | length %} +
+
+ Courses In Progress +
+
+ {% for course in enrolled.in_progress %} + {{ widgets.CourseCard(course=course, read_only=read_only) }} + {% endfor %} +
+
+{% endif %} + {% endmacro %} {% macro ProfileTabs(profile_tabs) %} @@ -166,3 +182,16 @@ {% endfor %}
{% endmacro %} + +{% block script %} + +{% endblock %} diff --git a/community/www/profiles/profile.py b/community/www/profiles/profile.py index 2ea2bdd5..73ea980f 100644 --- a/community/www/profiles/profile.py +++ b/community/www/profiles/profile.py @@ -1,10 +1,18 @@ import frappe +from community.page_renderers import get_profile_url_prefix def get_context(context): context.no_cache = 1 try: - context.member = frappe.get_doc("User", {"username": frappe.form_dict["username"]}) + username = frappe.form_dict["username"] + except KeyError: + username = frappe.db.get_value("User", frappe.session.user, ["username"]) + if username: + frappe.local.flags.redirect_location = get_profile_url_prefix() + username + raise frappe.Redirect + try: + context.member = frappe.get_doc("User", {"username": username}) except: context.template = "www/404.html" return