refactor: fixed the course page

This commit is contained in:
Anand Chitipothu
2021-05-06 06:47:09 +05:30
parent da902d23f7
commit dc5b637ada
11 changed files with 191 additions and 141 deletions

View File

@@ -2,7 +2,7 @@
"actions": [],
"allow_guest_to_view": 1,
"allow_rename": 1,
"autoname": "field:title",
"autoname": "field:slug",
"creation": "2021-03-01 16:49:33.622422",
"doctype": "DocType",
"editable_grid": 1,
@@ -89,7 +89,7 @@
"link_fieldname": "course"
}
],
"modified": "2021-05-03 05:52:30.396824",
"modified": "2021-05-06 06:06:08.760597",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Course",

View File

@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from ...utils import slugify
from community.query import find, find_all
class LMSCourse(Document):
@staticmethod
@@ -139,24 +140,8 @@ class LMSCourse(Document):
now = frappe.utils.nowdate()
batches = find_all("LMS Batch",
course=self.name,
start_date=[">", now])
start_date=[">", now],
status="Active",
visibility="Public")
return batches
def find_all(doctype, order_by=None, **filters):
"""Queries the database for documents of a doctype matching given filters.
"""
rows = frappe.db.get_all(doctype,
filters=filters,
fields='*',
order_by=order_by)
return [frappe.get_doc(dict(row, doctype=doctype)) for row in rows]
def find(doctype, **filters):
"""Queries the database for a document of given doctype matching given filters.
"""
rows = frappe.db.get_all(doctype,
filters=filters,
fields='*')
if rows:
row = rows[0]
return frappe.get_doc(dict(row, doctype=doctype))

View File

@@ -1,6 +1,6 @@
<div class="chapter-teaser">
<div class="teaser-body">
<h3 class="chapter-title">{{ chapter.title }}</h3>
<h3 class="chapter-title"><span class="chapter-number">{{index}}</span> {{ chapter.title }}</h3>
<div class="chapter-description">
{{ chapter.description or "" }}
</div>

View File

@@ -3,8 +3,8 @@
"public/css/lms.css"
],
"css/community.css": [
"public/css/vars.css",
"public/css/style.css",
"public/css/vars.css",
"public/css/style.less"
]
}

View File

@@ -34,82 +34,8 @@ body {
margin: 0px;
}
.course-header {
margin-top: 20px;
padding: 20px;
background: var(--header-bg);
color: var(--header-color);
border-radius: 9px;
}
.course-author-avatar {
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 20px;
}
.course-header h1 {
color: inherit;
}
.course-type {
text-transform: uppercase;
font-size: 1.0em;
color: var(--tag-color);
}
.sidebar {
background: var(--sidebar-bg);
margin: 20px 0px;
border-radius: 10px;
padding: 1px 20px 20px 20px;
color: var(--text-color);
}
.sidebar h3 {
margin-top: 20px;
color: var(--c2);
}
.sidebar-batch {
background: var(--sidebar-bg);
color: var(--text-color);
position: fixed;
left: 0;
height: 100%;
}
.sidebar-batch a {
padding: 16px 8px 8px 16px;
display: block;
}
.instructor {
padding: 10px;
}
.instructor-title {
font-weight: bold;
}
.instructor-subtitle {
font-size: 0.8em;
color: var(--text-color);
}
.sidebar .notice {
padding: 10px;
border-radius: 10px;
border: 1px dashed var(--text-color);
}
.sidebar .notice a {
color: inherit;
text-decoration: underline;
}
.course-details {
/* .course-details {
margin: 20px 0px;
}
@@ -118,7 +44,7 @@ body {
font-size: 1.4em;
font-weight: bold;
margin: 20px 0px 10px 0px;
}
} */
.chapter-plan {
border-radius: 10px;
@@ -133,7 +59,7 @@ body {
font-weight: bold;
}
.chapter-number {
/* .chapter-number {
background: var(--text-color);
color: white;
border-radius: 50%;
@@ -146,7 +72,7 @@ body {
.chapter-description {
margin: 20px 0px;
}
} */
.lessons {
padding-left: 20px;
@@ -302,4 +228,4 @@ img.profile-photo {
color: #2D005A;
font-weight: 600;
line-height: 51px;
}
}

View File

@@ -5,6 +5,11 @@ body {
font-family: "Inter", sans-serif;
}
h2 {
margin: 20px 0px;
color: black;
}
.teaser {
background: white;
border-radius: 9px;
@@ -122,3 +127,108 @@ section.lightgray {
padding: 2rem 0px;
margin-top: 2rem;
}
.course-type {
text-transform: uppercase;
font-size: 1.0em;
font-weight: bold;
color: var(--tag-color);
}
.course-header {
margin-top: 20px;
}
/*
.course-header {
margin-top: 20px;
padding: 20px;
background: var(--header-bg);
color: var(--header-color);
border-radius: 9px;
}
.course-author-avatar {
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 20px;
}
.course-header h1 {
color: inherit;
}
*/
// .gray-section {
// background:#F6F6F6;
// border: 1px solid #C4C4C4;
// padding: 20px;
// margin: 20px 0px;
// }
.instructor-title {
font-weight: bold;
color: black;
}
.instructor-subtitle {
font-size: 0.8em;
color: var(--text-color);
}
// .mentors-wrapper {
// .gray-section();
// }
.chapter-number {
background: var(--text-color);
color: white;
border-radius: 50%;
height: 24px;
min-width: 24px;
align-items: center;
padding: 5px 8px 2px 8px;
margin-right: 5px;
}
.sidebar {
background: var(--sidebar-bg);
border: 1px solid var(--sidebar-border);
margin: 20px 0px;
border-radius: 10px;
padding: 1px 20px 20px 20px;
}
.sidebar h3 {
margin-top: 20px;
color: black;
}
.sidebar-batch {
background: var(--sidebar-bg);
color: var(--text-color);
position: fixed;
left: 0;
height: 100%;
}
.sidebar-batch a {
padding: 16px 8px 8px 16px;
display: block;
}
.sidebar .notice {
margin-top: 10px;
padding: 10px;
border-radius: 10px;
border: 1px dashed var(--text-color);
}
.sidebar .notice a {
color: inherit;
text-decoration: underline;
}

View File

@@ -1,4 +1,7 @@
/* Define all your css variables here. */
:root {
--primary-color: #08B74F;
--tag-color: #737373;
--sidebar-bg: #F6F6F6;
--sidebar-border: #C4C4C4;
}

22
community/query.py Normal file
View File

@@ -0,0 +1,22 @@
"""Utilities to find docs.
"""
import frappe
def find_all(doctype, order_by=None, **filters):
"""Queries the database for documents of a doctype matching given filters.
"""
rows = frappe.db.get_all(doctype,
filters=filters,
fields='*',
order_by=order_by)
return [frappe.get_doc(dict(row, doctype=doctype)) for row in rows]
def find(doctype, **filters):
"""Queries the database for a document of given doctype matching given filters.
"""
rows = frappe.db.get_all(doctype,
filters=filters,
fields='*')
if rows:
row = rows[0]
return frappe.get_doc(dict(row, doctype=doctype))

View File

@@ -11,22 +11,23 @@
<div class="course-header">
<div class="course-type">course</div>
<h1 id="course-title" data-course="{{course.name}}">{{course.title}}</h1>
<div class="course-short-intro">{{ course.short_introduction }}</div>
</div>
<div class="row">
<div class="col-lg-9 col-md-12">
<div class="col-lg-8 col-md-12">
<div class="course-details">
{{ CourseVideo(course) }}
{{ CourseDescription(course) }}
{{ BatchSection(course) }}
{{ CourseOutline(course) }}
</div>
</div>
<div class="col-lg-3 col-md-12">
<div class="col-lg-4 col-md-12">
<div class="sidebar">
{{ InstructorsSection(course.get_instructor()) }}
</div>
<div class="sidebar">
{{ MentorsSection(course.get_mentors(), course.is_mentor(frappe.session.user), course.name) }}
</div>
@@ -35,14 +36,7 @@
</div>
{% endblock %}
{% macro CourseDescription(course) %}
<h2>Course Description</h2>
<div class="course-description">
{{ course.short_introduction }}
</div>
{% macro CourseVideo(course) %}
{% if course.video_link %}
<div class="preview-video">
<iframe
@@ -57,6 +51,14 @@
{% endif %}
{% endmacro %}
{% macro CourseDescription(course) %}
<h2>Course Description</h2>
<div class="course-description">
{{ course.short_introduction }}
</div>
{% endmacro %}
{% macro BatchSection(course) %}
{% if course.is_mentor(frappe.session.user) %}
{{ BatchSectionForMentors(course, course.get_batches(mentor=frappe.session.user)) }}
@@ -86,7 +88,7 @@
<div class="cta">
<div class="">
{% if can_manage %}
<button >Manage</button>
<a href="/courses/{{course.name}}/{{batch.name}}/about" class="btn btn-secondary">Manage</a>
{% else %}
<button class="join-batch" data-batch="{{ batch.name | urlencode }}">Join this Batch</button>
{% endif %}
@@ -136,6 +138,6 @@
<h2>Course Outline</h2>
{% for chapter in course.get_chapters() %}
{{ widgets.ChapterTeaser(chapter=chapter)}}
{{ widgets.ChapterTeaser(index=loop.index, chapter=chapter)}}
{% endfor %}
{% endmacro %}

View File

@@ -14,12 +14,14 @@ def get_member_with_name(name):
def get_batch(code):
try:
return frappe.db.get_value("LMS Batch", {"code": code}, ["name", "description"], as_dict=True)
print("get_batch", code)
return frappe.db.get_value("LMS Batch", {"name": code}, ["name", "description"], as_dict=True)
except frappe.DoesNotExistError:
print("Error: notfound")
return
def is_member_of_batch(batch_code):
membership = frappe.get_all("LMS Batch Membership", {"batch": get_batch(batch_code).name, "member": get_member_with_email()})
membership = frappe.get_all("LMS Batch Membership", {"batch": batch_code, "member": get_member_with_email()})
if len(membership):
return True
return False
@@ -54,4 +56,4 @@ def get_batch_members(batch):
if membership.member_type == "Mentor":
member.is_mentor = True
members.append(member)
return members
return members

View File

@@ -1,31 +1,31 @@
{% macro InstructorsSection(instructor) %}
<h3>Instructor</h3>
<div class="instructor">
<div class="instructor-title">{{instructor.full_name}}</div>
<div class="instructor-subtitle">Created {{instructor.get_course_count()}} courses</div>
</div>
<h3>Instructor</h3>
<div class="instructor">
<div class="instructor-title">{{instructor.full_name}}</div>
<div class="instructor-subtitle">Created {{instructor.get_course_count()}} courses</div>
</div>
{% endmacro %}
{% macro MentorsSection(mentors, is_mentor, course_name) %}
<h3>Mentors</h3>
{% for m in mentors %}
<div class="instructor">
<div class="instructor-title">{{m.full_name}}</div>
<div class="instructor-subtitle">Mentored {{m.get_batch_count()}} batches</div>
</div>
{% endfor %}
{% if not is_mentor %}
<div id="mentor-request" class="notice">
Interested to become a mentor?
<h3>Mentors</h3>
{% for m in mentors %}
<div class="instructor">
<div class="instructor-title">{{m.full_name}}</div>
<div class="instructor-subtitle">Mentored {{m.get_batch_count()}} batches</div>
</div>
{% endfor %}
{% if not is_mentor %}
<div id="mentor-request" class="notice">
Interested to become a mentor?
<div><a id="apply-now" data-course="{{course_name | urlencode}}" href="">Apply Now!</a></div>
</div>
<div id="already-applied" class="notice hide">
You've applied to become a mentor for this course. Your request is currently under review.
<div><a id="apply-now" data-course="{{course_name | urlencode}}" href="">Apply Now!</a></div>
</div>
<div id="already-applied" class="notice hide">
You've applied to become a mentor for this course. Your request is currently under review.
If you are not any more interested to mentor this course, you can <a id="cancel-request" data-course="{{course_name | urlencode}}" href="">cancel your application</a>.
</div>
{% endif %}
If you are not any more interested to mentor this course, you can <a id="cancel-request" data-course="{{course_name | urlencode}}" href="">cancel your application</a>.
</div>
{% endif %}
{% endmacro %}