refactor: fixed the course page
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
22
community/query.py
Normal 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))
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user