fix: get_doc references
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
{% if membership or is_instructor %} eligible-for-submission {% endif %}" data-lesson="{{ lesson.name }}"
|
||||
data-course="{{ course.name }}">
|
||||
{{ lesson.title }}
|
||||
<span class="lesson-progress {{hide if course.get_progress(lesson.name) != 'Complete' else ''}}">COMPLETED</span>
|
||||
<span class="lesson-progress {{hide if get_progress(course.name, lesson.name) != 'Complete' else ''}}">COMPLETED</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
|
||||
</small>
|
||||
{% endif %}
|
||||
{{ lesson.render_html() }}</div>
|
||||
{{ render_html(lesson.body) }}</div>
|
||||
{% else %}
|
||||
<div class="common-card-style lesson-content-card">
|
||||
<div class="w-25 text-center" style="margin: 0 auto;">
|
||||
@@ -78,8 +78,8 @@
|
||||
</div>
|
||||
|
||||
|
||||
{% if not course.is_mentor(frappe.session.user) and membership %}
|
||||
{% set progress = course.get_progress(lesson.name) %}
|
||||
{% if not is_mentor(course.name, frappe.session.user) and membership %}
|
||||
{% set progress = get_progress(course.name, lesson.name) %}
|
||||
<div class="custom-checkbox {% if progress == 'Complete' %} hide {% endif %}">
|
||||
<label class="quiz-label">
|
||||
<input class="option mark-progress" type="checkbox" checked>
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
from re import I
|
||||
import frappe
|
||||
from . import utils
|
||||
from frappe.utils import cstr
|
||||
from school.www.utils import get_common_context, redirect_to_lesson, get_lesson_url
|
||||
from frappe.utils import cstr, flt
|
||||
|
||||
from school.www import batch
|
||||
|
||||
def get_context(context):
|
||||
utils.get_common_context(context)
|
||||
get_common_context(context)
|
||||
|
||||
chapter_index = frappe.form_dict.get("chapter")
|
||||
lesson_index = frappe.form_dict.get("lesson")
|
||||
lesson_number = f"{chapter_index}.{lesson_index}"
|
||||
|
||||
if not chapter_index or not lesson_index:
|
||||
if context.batch:
|
||||
index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1"
|
||||
else:
|
||||
index_ = "1.1"
|
||||
utils.redirect_to_lesson(context.course, index_)
|
||||
redirect_to_lesson(context.course, index_)
|
||||
|
||||
context.lesson = get_current_lesson_details(lesson_number, context)
|
||||
neighbours = context.course.get_neighbours(lesson_number, context.lessons)
|
||||
context.next_url = get_learn_url(neighbours["next"], context.course)
|
||||
context.prev_url = get_learn_url(neighbours["prev"], context.course)
|
||||
neighbours = get_neighbours(lesson_number, context.lessons)
|
||||
context.next_url = get_url(neighbours["next"], context.course)
|
||||
context.prev_url = get_url(neighbours["prev"], context.course)
|
||||
|
||||
meta_info = context.lesson.title + " - " + context.course.title
|
||||
context.metatags = {
|
||||
@@ -38,15 +37,16 @@ def get_context(context):
|
||||
"lesson": context.lesson.name,
|
||||
"is_member": context.membership is not None
|
||||
}
|
||||
print(context)
|
||||
|
||||
def get_current_lesson_details(lesson_number, context):
|
||||
details_list = list(filter(lambda x: cstr(x.number) == lesson_number, context.lessons))
|
||||
if not len(details_list):
|
||||
utils.redirect_to_lesson(context.course)
|
||||
redirect_to_lesson(context.course)
|
||||
return details_list[0]
|
||||
|
||||
def get_learn_url(lesson_number, course):
|
||||
return course.get_learn_url(lesson_number) and course.get_learn_url(lesson_number) + course.query_parameter
|
||||
def get_url(lesson_number, course):
|
||||
return get_lesson_url(course.name, lesson_number) and get_lesson_url(course.name, lesson_number) + course.query_parameter
|
||||
|
||||
def get_lesson_index(course, batch, user):
|
||||
lesson = batch.get_current_lesson(user)
|
||||
@@ -59,3 +59,12 @@ def get_page_extensions(context):
|
||||
for e in extensions:
|
||||
e.set_context(context)
|
||||
return extensions
|
||||
|
||||
def get_neighbours(current, lessons):
|
||||
current = flt(current)
|
||||
numbers = sorted(lesson.number for lesson in lessons)
|
||||
index = numbers.index(current)
|
||||
return {
|
||||
"prev": numbers[index-1] if index-1 >= 0 else None,
|
||||
"next": numbers[index+1] if index+1 < len(numbers) else None
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if membership %}
|
||||
{% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and
|
||||
{% set lesson_index = get_lesson_index(membership.current_lesson) if membership and
|
||||
membership.current_lesson
|
||||
else '1.1' %}
|
||||
<a class="button wide-button is-primary" id="continue-learning"
|
||||
href="{{ course.get_learn_url(lesson_index) }}{{ course.query_parameter }}">
|
||||
href="{{ get_lesson_url(course.name, lesson_index) }}{{ course.query_parameter }}">
|
||||
Continue Learning <img class="ml-2" src="/assets/school/icons/white-arrow.svg" />
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if course.is_cohort_staff(frappe.session.user) %}
|
||||
{% if is_cohort_staff(course.name, frappe.session.user) %}
|
||||
<a class="button wide-button is-secondary"
|
||||
href="/courses/{{course.name}}/manage"
|
||||
style="color: inherit;">
|
||||
@@ -129,14 +129,14 @@
|
||||
<div class="course-home-headings">
|
||||
Creator
|
||||
</div>
|
||||
{% for instructor in course.get_instructors() %}
|
||||
{% for instructor in get_instructors(course.name) %}
|
||||
{{ widgets.MemberCard(member=instructor, show_course_count=True, avatar_class="avatar-large") }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro Progress(course) %}
|
||||
{% set certificate = course.is_certified() %}
|
||||
{% set certificate = is_certified(course.name) %}
|
||||
{% set progress = frappe.utils.cint(membership.progress) %}
|
||||
{% if progress %}
|
||||
<div class="course-progress-section">
|
||||
@@ -186,17 +186,17 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro Overview(course) %}
|
||||
{% set avg_rating = course.get_average_rating() %}
|
||||
{% if course.get_students() | length or avg_rating %}
|
||||
{% set avg_rating = get_average_rating(course.name) %}
|
||||
{% if get_students(course.name) | length or avg_rating %}
|
||||
<div class="course-overview-section">
|
||||
<div class="course-home-headings">
|
||||
Overview
|
||||
</div>
|
||||
<div class="common-card-style overview-card small-title">
|
||||
{% if course.get_students() | length %}
|
||||
{% if get_students(course.name) | length %}
|
||||
<div class="overview-item">
|
||||
<img class="icon-background mr-1" src="/assets/school/icons/user.svg" />
|
||||
{{ course.get_students() | length }} Enrolled
|
||||
{{ get_students(course.name) | length }} Enrolled
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if avg_rating %}
|
||||
@@ -213,13 +213,13 @@
|
||||
<!-- Mentors -->
|
||||
|
||||
{% macro Mentors(course) %}
|
||||
{% if course.get_mentors() | length %}
|
||||
{% if get_mentors(course.name) | length %}
|
||||
<div class="course-home-mentors">
|
||||
<div class="course-home-headings">
|
||||
Mentors
|
||||
</div>
|
||||
<div class="member-parent">
|
||||
{% for mentor in course.get_mentors() %}
|
||||
{% for mentor in get_mentors(course.name) %}
|
||||
{{ widgets.MemberCard(member=mentor, show_course_count=False) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import frappe
|
||||
from school.lms.doctype.lms_settings.lms_settings import check_profile_restriction
|
||||
from school.www.utils import get_membership
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
@@ -16,7 +17,7 @@ def get_context(context):
|
||||
raise frappe.Redirect
|
||||
|
||||
context.course = course
|
||||
membership = course.get_membership(frappe.session.user)
|
||||
membership = get_membership(course.name, frappe.session.user)
|
||||
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
||||
context.membership = membership
|
||||
if context.course.upcoming:
|
||||
|
||||
@@ -15,7 +15,7 @@ def get_context(context):
|
||||
def get_courses():
|
||||
courses = frappe.get_all("LMS Course",
|
||||
filters={"is_published": True},
|
||||
fields=["name", "upcoming", "title", "image"])
|
||||
fields=["name", "upcoming", "title", "image", "enable_certification"])
|
||||
|
||||
live_courses, upcoming_courses = [], []
|
||||
for course in courses:
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<div class="profile-info">
|
||||
<div class="profile-name-section">
|
||||
<div class="profile-name"> {{ member.full_name }} </div>
|
||||
{% if member.get_authored_courses() | length %}
|
||||
{% if get_authored_courses(member.name) | length %}
|
||||
<div class="creator-badge"> Creator </div>
|
||||
{% endif %}
|
||||
{% if member.looking_for_job %}
|
||||
@@ -104,14 +104,16 @@
|
||||
|
||||
|
||||
{% macro CoursesCreated(member, read_only) %}
|
||||
{% if member.get_authored_courses() | length %}
|
||||
{% set authored_courses = get_authored_courses(member.name) %}
|
||||
{% if authored_courses | length %}
|
||||
<div class="profile-courses">
|
||||
<div class="course-home-headings">
|
||||
Courses Created
|
||||
</div>
|
||||
<div class="cards-parent">
|
||||
{% for course in member.get_authored_courses() %}
|
||||
{% set course_details = frappe.get_doc("LMS Course", course) %}
|
||||
{% for course in authored_courses %}
|
||||
{% set course_details = frappe.db.get_value("LMS Course", course,
|
||||
["name", "upcoming", "title", "image", "enable_certification"], as_dict=True) %}
|
||||
{{ widgets.CourseCard(course=course_details, read_only=read_only) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
import frappe
|
||||
from school.lms.models import Course
|
||||
from frappe.utils import flt
|
||||
from frappe.utils import flt, cint
|
||||
from school.lms.utils import slugify
|
||||
from school.lms.md import markdown_to_html
|
||||
|
||||
def get_common_context(context):
|
||||
context.no_cache = 1
|
||||
|
||||
course_name = frappe.form_dict["course"]
|
||||
try:
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
except KeyError:
|
||||
batch_name = None
|
||||
|
||||
course = frappe.get_doc("LMS Course", course_name)
|
||||
course = frappe.db.get_value("LMS Course",
|
||||
frappe.form_dict["course"], ["name", "title", "video_link"], as_dict=True)
|
||||
if not course:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
context.course = course
|
||||
context.lessons = course.get_lessons()
|
||||
membership = get_membership(course_name, frappe.session.user, batch_name)
|
||||
context.lessons = get_lessons(course.name)
|
||||
membership = get_membership(course.name, frappe.session.user, batch_name)
|
||||
context.membership = membership
|
||||
if membership:
|
||||
batch = course.get_batch(membership.batch)
|
||||
batch = get_batch(course.name, membership.batch)
|
||||
|
||||
if batch:
|
||||
context.batch = batch
|
||||
@@ -32,7 +33,7 @@ def get_livecode_url():
|
||||
return frappe.db.get_single_value("LMS Settings", "livecode_url")
|
||||
|
||||
def redirect_to_lesson(course, index_="1.1"):
|
||||
frappe.local.flags.redirect_location = course.get_learn_url(index_) + course.query_parameter
|
||||
frappe.local.flags.redirect_location = get_lesson_url(course.name, index_) + course.query_parameter
|
||||
raise frappe.Redirect
|
||||
|
||||
def get_membership(course, member, batch=None):
|
||||
@@ -55,16 +56,18 @@ def get_membership(course, member, batch=None):
|
||||
def get_chapters(course):
|
||||
"""Returns all chapters of this course.
|
||||
"""
|
||||
chapters = frappe.get_all("Course Chapter",
|
||||
{ "course": course },
|
||||
["name", "title", "description", "idx"])
|
||||
chapters = frappe.get_all("Chapter Reference", {"parent": course},
|
||||
["idx", "chapter"], order_by="idx")
|
||||
for chapter in chapters:
|
||||
chapter_details = frappe.db.get_value("Course Chapter", { "name": chapter.chapter },
|
||||
["name", "title", "description"], as_dict=True)
|
||||
chapter.update(chapter_details)
|
||||
return chapters
|
||||
|
||||
def get_lessons(course, chapter=None):
|
||||
""" If chapter is passed, returns lessons of only that chapter.
|
||||
Else returns lessons of all chapters of the course """
|
||||
lessons = []
|
||||
|
||||
if chapter:
|
||||
return get_lesson_details(chapter)
|
||||
|
||||
@@ -82,7 +85,8 @@ def get_lesson_details(chapter):
|
||||
order_by="idx")
|
||||
|
||||
for row in lesson_list:
|
||||
lesson_details = frappe.db.get_value("Course Lesson", row.lesson, "name", as_dict=True)
|
||||
lesson_details = frappe.db.get_value("Course Lesson", row.lesson,
|
||||
["name", "title", "include_in_preview", "body"], as_dict=True)
|
||||
lesson_details.number = flt("{}.{}".format(chapter.idx, row.idx))
|
||||
lessons.append(lesson_details)
|
||||
return lessons
|
||||
@@ -91,11 +95,171 @@ def get_tags(course):
|
||||
tags = frappe.db.get_value("LMS Course", course, "tags")
|
||||
return tags.split(",") if tags else []
|
||||
|
||||
def get_instructors(self):
|
||||
instructors = []
|
||||
if self.instructors:
|
||||
for instructor in self.instructors:
|
||||
instructors.append(frappe.get_doc("User", instructor.instructor))
|
||||
else:
|
||||
instructors.append(frappe.get_doc("User", self.owner))
|
||||
return instructors
|
||||
def get_instructors(course):
|
||||
instructor_details = []
|
||||
instructors = frappe.get_all("Course Instructor", {"parent": course},
|
||||
["instructor"], order_by="idx")
|
||||
if not instructors:
|
||||
instructors = frappe.db.get_value("LMS Course", course, "owner").split(" ")
|
||||
for instructor in instructors:
|
||||
instructor_details.append(frappe.db.get_value("User",
|
||||
instructor.instructor,
|
||||
["name", "username", "full_name", "user_image"],
|
||||
as_dict=True))
|
||||
return instructor_details
|
||||
|
||||
def get_students(course, batch=None):
|
||||
"""Returns (email, full_name, username) of all the students of this batch as a list of dict.
|
||||
"""
|
||||
filters = {
|
||||
"course": course,
|
||||
"member_type": "Student"
|
||||
}
|
||||
if batch:
|
||||
filters["batch"] = batch
|
||||
return frappe.get_all(
|
||||
"LMS Batch Membership",
|
||||
filters,
|
||||
["member"])
|
||||
|
||||
def get_average_rating(course):
|
||||
ratings = [review.rating for review in get_reviews(course)]
|
||||
if not len(ratings):
|
||||
return None
|
||||
return sum(ratings)/len(ratings)
|
||||
|
||||
def get_reviews(course):
|
||||
reviews = frappe.get_all("LMS Course Review",
|
||||
{
|
||||
"course": course
|
||||
},
|
||||
["review", "rating", "owner"],
|
||||
order_by= "creation desc")
|
||||
out_of_ratings = frappe.db.get_all("DocField",
|
||||
{
|
||||
"parent": "LMS Course Review",
|
||||
"fieldtype": "Rating"
|
||||
},
|
||||
["options"])
|
||||
out_of_ratings = (len(out_of_ratings) and out_of_ratings[0].options) or 5
|
||||
for review in reviews:
|
||||
review.rating = review.rating * out_of_ratings
|
||||
review.owner_details = frappe.db.get_value("User",
|
||||
review.owner, ["name", "username", "full_name", "user_image"], as_dict=True)
|
||||
|
||||
return reviews
|
||||
|
||||
def is_certified(course):
|
||||
certificate = frappe.get_all("LMS Certification",
|
||||
{
|
||||
"student": frappe.session.user,
|
||||
"course": course
|
||||
})
|
||||
if len(certificate):
|
||||
return certificate[0].name
|
||||
return
|
||||
|
||||
def get_lesson_index(lesson_name):
|
||||
"""Returns the {chapter_index}.{lesson_index} for the lesson.
|
||||
"""
|
||||
lesson = frappe.db.get_value("Lesson Reference",
|
||||
{"lesson": lesson_name}, ["idx", "parent"], as_dict=True)
|
||||
if not lesson:
|
||||
return None
|
||||
|
||||
chapter = frappe.db.get_value("Chapter Reference",
|
||||
{"chapter": lesson.parent}, ["idx"], as_dict=True)
|
||||
if not chapter:
|
||||
return None
|
||||
|
||||
return f"{chapter.idx}.{lesson.idx}"
|
||||
|
||||
def get_lesson_url(course, lesson_number):
|
||||
if not lesson_number:
|
||||
return
|
||||
return f"/courses/{course}/learn/{lesson_number}"
|
||||
|
||||
def get_batch(course, batch_name):
|
||||
return frappe.get_all("LMS Batch", {"name": batch_name, "course": course})
|
||||
|
||||
def get_slugified_chapter_title(chapter):
|
||||
return slugify(chapter)
|
||||
|
||||
def get_progress(course, lesson):
|
||||
return frappe.db.get_value("LMS Course Progress", {
|
||||
"course": course,
|
||||
"owner": frappe.session.user,
|
||||
"lesson": lesson
|
||||
},
|
||||
["status"])
|
||||
|
||||
def render_html(body):
|
||||
return markdown_to_html(body)
|
||||
|
||||
def is_mentor(course, email):
|
||||
"""Checks if given user is a mentor for this course.
|
||||
"""
|
||||
if not email:
|
||||
return False
|
||||
return frappe.db.count("LMS Course Mentor Mapping",
|
||||
{
|
||||
"course": course,
|
||||
"mentor": email
|
||||
})
|
||||
|
||||
def is_cohort_staff(course, user_email):
|
||||
"""Returns True if the user is either a mentor or a staff for one or more active cohorts of this course.
|
||||
"""
|
||||
staff = {
|
||||
"doctype": "Cohort Staff",
|
||||
"course": course,
|
||||
"email": user_email
|
||||
}
|
||||
mentor = {
|
||||
"doctype": "Cohort Mentor",
|
||||
"course": course,
|
||||
"email": user_email
|
||||
}
|
||||
return frappe.db.exists(staff) or frappe.db.exists(mentor)
|
||||
|
||||
def get_mentors(course):
|
||||
"""Returns the list of all mentors for this course.
|
||||
"""
|
||||
course_mentors = []
|
||||
mentors = frappe.get_all("LMS Course Mentor Mapping", {"course": course}, ["mentor"])
|
||||
for mentor in mentors:
|
||||
member = frappe.db.get_value("User", mentor.mentor,
|
||||
["name", "username", "full_name", "user_image"])
|
||||
member.batch_count = frappe.db.count("LMS Batch Membership",
|
||||
{
|
||||
"member": member.name,
|
||||
"member_type": "Mentor"
|
||||
})
|
||||
course_mentors.append(member)
|
||||
return course_mentors
|
||||
|
||||
def is_eligible_to_review(course, membership):
|
||||
""" Checks if user is eligible to review the course """
|
||||
if not membership:
|
||||
return False
|
||||
if frappe.db.count("LMS Course Review",
|
||||
{
|
||||
"course": course,
|
||||
"owner": frappe.session.user
|
||||
}):
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_course_progress(course, member=None):
|
||||
""" Returns the course progress of the session user """
|
||||
lesson_count = len(get_lessons(course))
|
||||
if not lesson_count:
|
||||
return 0
|
||||
completed_lessons = frappe.db.count("LMS Course Progress",
|
||||
{
|
||||
"course": course,
|
||||
"owner": member or frappe.session.user,
|
||||
"status": "Complete"
|
||||
})
|
||||
precision = cint(frappe.db.get_default("float_precision")) or 3
|
||||
return flt(((completed_lessons/lesson_count) * 100), precision)
|
||||
|
||||
Reference in New Issue
Block a user