feat: progress page
This commit is contained in:
38
lms/hooks.py
38
lms/hooks.py
@@ -95,7 +95,8 @@ override_doctype_class = {
|
|||||||
# Hook on document methods and events
|
# Hook on document methods and events
|
||||||
|
|
||||||
doc_events = {
|
doc_events = {
|
||||||
"Discussion Reply": {"after_insert": "lms.lms.utils.create_notification_log"}
|
"Discussion Reply": {"after_insert": "lms.lms.utils.create_notification_log"},
|
||||||
|
"Course Lesson": {"on_update": "lms.lms.doctype.lms_quiz.lms_quiz.update_lesson_info"}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Scheduled Tasks
|
# Scheduled Tasks
|
||||||
@@ -137,35 +138,28 @@ website_route_rules = [
|
|||||||
{"from_route": "/courses/<course>", "to_route": "courses/course"},
|
{"from_route": "/courses/<course>", "to_route": "courses/course"},
|
||||||
{"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"},
|
{"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"},
|
||||||
{"from_route": "/courses/<course>/learn", "to_route": "batch/learn"},
|
{"from_route": "/courses/<course>/learn", "to_route": "batch/learn"},
|
||||||
{
|
{"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>",
|
||||||
"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>",
|
"to_route": "batch/learn"},
|
||||||
"to_route": "batch/learn",
|
|
||||||
},
|
|
||||||
{"from_route": "/quizzes", "to_route": "batch/quiz_list"},
|
{"from_route": "/quizzes", "to_route": "batch/quiz_list"},
|
||||||
{"from_route": "/quizzes/<quizname>", "to_route": "batch/quiz"},
|
{"from_route": "/quizzes/<quizname>", "to_route": "batch/quiz"},
|
||||||
{"from_route": "/classes/<classname>", "to_route": "classes/class"},
|
{"from_route": "/classes/<classname>", "to_route": "classes/class"},
|
||||||
{"from_route": "/courses/<course>/progress", "to_route": "batch/progress"},
|
{"from_route": "/courses/<course>/progress", "to_route": "batch/progress"},
|
||||||
{"from_route": "/courses/<course>/join", "to_route": "batch/join"},
|
{"from_route": "/courses/<course>/join", "to_route": "batch/join"},
|
||||||
{"from_route": "/courses/<course>/manage", "to_route": "cohorts"},
|
{"from_route": "/courses/<course>/manage", "to_route": "cohorts"},
|
||||||
{"from_route": "/courses/<course>/cohorts/<cohort>", "to_route": "cohorts/cohort"},
|
{"from_route": "/courses/<course>/cohorts/<cohort>",
|
||||||
{
|
"to_route": "cohorts/cohort"},
|
||||||
"from_route": "/courses/<course>/cohorts/<cohort>/<page>",
|
{"from_route": "/courses/<course>/cohorts/<cohort>/<page>",
|
||||||
"to_route": "cohorts/cohort",
|
"to_route": "cohorts/cohort"},
|
||||||
},
|
{"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>",
|
||||||
{
|
"to_route": "cohorts/subgroup"},
|
||||||
"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>",
|
{"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>/<page>",
|
||||||
"to_route": "cohorts/subgroup",
|
"to_route": "cohorts/subgroup"},
|
||||||
},
|
{"from_route": "/courses/<course>/join/<cohort>/<subgroup>/<invite_code>",
|
||||||
{
|
"to_route": "cohorts/join"},
|
||||||
"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>/<page>",
|
|
||||||
"to_route": "cohorts/subgroup",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from_route": "/courses/<course>/join/<cohort>/<subgroup>/<invite_code>",
|
|
||||||
"to_route": "cohorts/join",
|
|
||||||
},
|
|
||||||
{"from_route": "/users", "to_route": "profiles/profile"},
|
{"from_route": "/users", "to_route": "profiles/profile"},
|
||||||
{"from_route": "/jobs/<job>", "to_route": "jobs/job"},
|
{"from_route": "/jobs/<job>", "to_route": "jobs/job"},
|
||||||
|
{"from_route": "/classes/<classname>/students/<username>",
|
||||||
|
"to_route": "/classes/progress"}
|
||||||
]
|
]
|
||||||
|
|
||||||
website_redirects = [
|
website_redirects = [
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"student",
|
"student",
|
||||||
"student_name"
|
"student_name",
|
||||||
|
"username"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -26,12 +27,19 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Student Name",
|
"label": "Student Name",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "student.username",
|
||||||
|
"fieldname": "username",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Username",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-11-09 16:25:07.819344",
|
"modified": "2022-11-15 11:13:39.410578",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Class Student",
|
"name": "Class Student",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class CourseLesson(Document):
|
|||||||
e = frappe.get_doc(doctype_map[section], name)
|
e = frappe.get_doc(doctype_map[section], name)
|
||||||
e.lesson = self.name
|
e.lesson = self.name
|
||||||
e.index_ = index
|
e.index_ = index
|
||||||
|
e.course = self.course
|
||||||
e.save(ignore_permissions=True)
|
e.save(ignore_permissions=True)
|
||||||
index += 1
|
index += 1
|
||||||
self.update_orphan_documents(doctype_map[section], documents)
|
self.update_orphan_documents(doctype_map[section], documents)
|
||||||
@@ -49,6 +50,7 @@ class CourseLesson(Document):
|
|||||||
for name in orphan_documents:
|
for name in orphan_documents:
|
||||||
ex = frappe.get_doc(doctype, name)
|
ex = frappe.get_doc(doctype, name)
|
||||||
ex.lesson = None
|
ex.lesson = None
|
||||||
|
ex.course = None
|
||||||
ex.index_ = 0
|
ex.index_ = 0
|
||||||
ex.index_label = ""
|
ex.index_label = ""
|
||||||
ex.save()
|
ex.save()
|
||||||
|
|||||||
@@ -7,7 +7,21 @@ from frappe import _
|
|||||||
from frappe.utils import cint
|
from frappe.utils import cint
|
||||||
|
|
||||||
class LMSClass(Document):
|
class LMSClass(Document):
|
||||||
pass
|
|
||||||
|
def validate(self):
|
||||||
|
validate_membership(self)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_membership(self):
|
||||||
|
for course in self.courses:
|
||||||
|
for student in self.students:
|
||||||
|
filters = {
|
||||||
|
"doctype": "LMS Batch Membership",
|
||||||
|
"member": student.student,
|
||||||
|
"course": course.course
|
||||||
|
}
|
||||||
|
if not frappe.db.exists(filters):
|
||||||
|
frappe.get_doc(filters).save()
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -9,9 +9,12 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"title",
|
"title",
|
||||||
"questions",
|
"questions",
|
||||||
"lesson",
|
"section_break_3",
|
||||||
"max_attempts",
|
"max_attempts",
|
||||||
"time"
|
"time",
|
||||||
|
"column_break_5",
|
||||||
|
"lesson",
|
||||||
|
"course"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -46,11 +49,27 @@
|
|||||||
"fieldname": "time",
|
"fieldname": "time",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Time Per Question (in Seconds)"
|
"label": "Time Per Question (in Seconds)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "lesson.course",
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_5",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_3",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-08-19 17:54:41.685182",
|
"modified": "2022-11-15 15:36:39.585488",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz",
|
"name": "LMS Quiz",
|
||||||
@@ -69,8 +88,10 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"show_title_field_in_link": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"states": [],
|
||||||
|
"title_field": "title",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -60,6 +60,13 @@ class LMSQuiz(Document):
|
|||||||
return result[0]
|
return result[0]
|
||||||
|
|
||||||
|
|
||||||
|
def update_lesson_info(doc, method):
|
||||||
|
if doc.quiz_id:
|
||||||
|
frappe.db.set_value("LMS Quiz", doc.quiz_id, {
|
||||||
|
"lesson": doc.name,
|
||||||
|
"course": doc.course
|
||||||
|
})
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def quiz_summary(quiz, results):
|
def quiz_summary(quiz, results):
|
||||||
score = 0
|
score = 0
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"member",
|
|
||||||
"member_name",
|
|
||||||
"column_break_3",
|
|
||||||
"quiz",
|
"quiz",
|
||||||
"score",
|
"score",
|
||||||
|
"course",
|
||||||
|
"column_break_3",
|
||||||
|
"member",
|
||||||
|
"member_name",
|
||||||
"section_break_6",
|
"section_break_6",
|
||||||
"result"
|
"result"
|
||||||
],
|
],
|
||||||
@@ -46,7 +47,8 @@
|
|||||||
"fetch_from": "member.full_name",
|
"fetch_from": "member.full_name",
|
||||||
"fieldname": "member_name",
|
"fieldname": "member_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Member Name"
|
"label": "Member Name",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
@@ -55,12 +57,20 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "section_break_6",
|
"fieldname": "section_break_6",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "quiz.course",
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-10-10 18:57:42.813738",
|
"modified": "2022-11-15 15:27:07.770945",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz Submission",
|
"name": "LMS Quiz Submission",
|
||||||
|
|||||||
@@ -87,9 +87,9 @@ input[type=checkbox] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.common-page-style {
|
.common-page-style {
|
||||||
padding: 2rem 0 5rem;
|
padding: 2rem 0 5rem;
|
||||||
padding-top: 3rem;
|
padding-top: 3rem;
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.common-card-style {
|
.common-card-style {
|
||||||
@@ -443,10 +443,6 @@ input[type=checkbox] {
|
|||||||
padding: 2rem 1rem;
|
padding: 2rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.member-card .talk-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.break {
|
.break {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@@ -978,10 +974,6 @@ pre {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading {
|
|
||||||
font-size: var(--text-4xl);
|
|
||||||
}
|
|
||||||
|
|
||||||
.testimonial-card {
|
.testimonial-card {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
@@ -1835,8 +1827,28 @@ select {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
grid-gap: 1rem;
|
grid-gap: 1rem;
|
||||||
|
font-size: var(--text-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
.class-cours {
|
.class-cours {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subheading {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--gray-900);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-course-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: var(--gray-100);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-heading {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--gray-900);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "templates/base.html" %}
|
{% extends "templates/base.html" %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ _(class_info.title) }}
|
{{ _(class_info.title) }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<div class="course-home-headings">
|
<div class="course-home-headings">
|
||||||
{{ class_info.title }}
|
{{ class_info.title }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="medium">
|
||||||
{{ class_info.description }}
|
{{ class_info.description }}
|
||||||
</div>
|
</div>
|
||||||
<div class="medium">
|
<div class="medium">
|
||||||
@@ -108,11 +108,12 @@
|
|||||||
{% if class_students | length %}
|
{% if class_students | length %}
|
||||||
<div class="mt-10">
|
<div class="mt-10">
|
||||||
{% for student in class_students %}
|
{% for student in class_students %}
|
||||||
<div class="">
|
<div class="" style="position: relative;">
|
||||||
<span>{{ student.student_name }}</span>
|
<span>{{ student.student_name }}</span>
|
||||||
<svg class="icon icon-md pull-right remove-student" data-student="{{ student.student }}">
|
<svg class="icon icon-md pull-right remove-student" data-student="{{ student.student }}">
|
||||||
<use href="#icon-delete"></use>
|
<use href="#icon-delete"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
<a class="stretched-link" href="/classes/{{ class_info.name }}/students/{{ student.username }}"></a>
|
||||||
</div>
|
</div>
|
||||||
{% if not loop.last %} <hr> {% endif %}
|
{% if not loop.last %} <hr> {% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
from lms.lms.utils import has_course_moderator_role
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
context.no_cache = 1
|
context.no_cache = 1
|
||||||
|
|
||||||
|
if not has_course_moderator_role():
|
||||||
|
message = "Only Moderators have access to this page."
|
||||||
|
if frappe.session.user == "Guest":
|
||||||
|
message = "Please login to access this page."
|
||||||
|
|
||||||
|
raise frappe.PermissionError(_(message))
|
||||||
|
|
||||||
class_name = frappe.form_dict["classname"]
|
class_name = frappe.form_dict["classname"]
|
||||||
|
|
||||||
context.class_info = frappe.db.get_value("LMS Class", class_name, ["name", "title", "start_date", "end_date", "description"], as_dict=True)
|
context.class_info = frappe.db.get_value("LMS Class", class_name, ["name", "title", "start_date", "end_date", "description"], as_dict=True)
|
||||||
@@ -14,4 +24,4 @@ def get_context(context):
|
|||||||
|
|
||||||
context.class_students = frappe.get_all("Class Student", {
|
context.class_students = frappe.get_all("Class Student", {
|
||||||
"parent": class_name
|
"parent": class_name
|
||||||
}, ["student", "student_name"])
|
}, ["student", "student_name", "username"])
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
from lms.lms.utils import has_course_moderator_role
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
context.no_cache = 1
|
context.no_cache = 1
|
||||||
|
|
||||||
|
if not has_course_moderator_role():
|
||||||
|
message = "Only Moderators have access to this page."
|
||||||
|
if frappe.session.user == "Guest":
|
||||||
|
message = "Please login to access this page."
|
||||||
|
|
||||||
|
raise frappe.PermissionError(_(message))
|
||||||
|
|
||||||
context.classes = frappe.get_all("LMS Class", fields=["name", "title", "start_date", "end_date"])
|
context.classes = frappe.get_all("LMS Class", fields=["name", "title", "start_date", "end_date"])
|
||||||
|
|||||||
76
lms/www/classes/progress.html
Normal file
76
lms/www/classes/progress.html
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
{% extends "templates/base.html" %}
|
||||||
|
{% block title %}
|
||||||
|
{{ student.first_name }} 's {{ _("Progress") }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="common-page-style">
|
||||||
|
<div class="container">
|
||||||
|
{{ BreadCrumb(class_info, student) }}
|
||||||
|
<div class="common-card-style column-card">
|
||||||
|
<div class="course-home-headings">
|
||||||
|
{{ student.full_name }}
|
||||||
|
</div>
|
||||||
|
{{ Progress(class_courses, student) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro BreadCrumb(class_info, student) %}
|
||||||
|
<div class="breadcrumb">
|
||||||
|
<a class="dark-links" href="/classes">{{ _("All Classes") }}</a>
|
||||||
|
<img class="ml-1 mr-1" src="/assets/lms/icons/chevron-right.svg">
|
||||||
|
<a class="dark-links" href="/classes/{{ class_info.name }}">{{ class_info.name }}</a>
|
||||||
|
<img class="ml-1 mr-1" src="/assets/lms/icons/chevron-right.svg">
|
||||||
|
<span class="breadcrumb-destination">{{ student.full_name }}</span>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro Progress(class_info, student) %}
|
||||||
|
<div>
|
||||||
|
{% for course in class_courses %}
|
||||||
|
<div class="medium">
|
||||||
|
<div class="progress-course-header">
|
||||||
|
<div class="section-heading"> {{ course.title }} </div>
|
||||||
|
<div> {{ frappe.utils.cint(course.membership.progress) }}% </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% for quiz in course.quizzes %}
|
||||||
|
|
||||||
|
{% set filters = { "member": student.name, "course": course.course } %}
|
||||||
|
{% set submitted = frappe.db.exists("LMS Quiz Submission", filters) %}
|
||||||
|
{% set score = frappe.db.get_value("LMS Quiz Submission", filters, ["score"]) %}
|
||||||
|
|
||||||
|
<div class="my-5">
|
||||||
|
<div class="subheading"> {{ _("Quiz") }}: </div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<div>
|
||||||
|
{{ quiz.title }}
|
||||||
|
</div>
|
||||||
|
{% if submitted %}
|
||||||
|
<div class="ml-5">
|
||||||
|
{{ score }}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="indicator-pill red ml-5">
|
||||||
|
Not Attempted
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% for quiz in class_courses.assignments %}
|
||||||
|
<div>
|
||||||
|
{{ assignments.assignment }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
26
lms/www/classes/progress.py
Normal file
26
lms/www/classes/progress.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def get_context(context):
|
||||||
|
context.no_cache = 1
|
||||||
|
|
||||||
|
student = frappe.form_dict["username"]
|
||||||
|
classname = frappe.form_dict["classname"]
|
||||||
|
|
||||||
|
context.student = frappe.db.get_value("User", {"username": student}, ["first_name", "full_name", "name"], as_dict=True)
|
||||||
|
context.class_info = frappe.db.get_value("LMS Class", classname, ["name"], as_dict=True)
|
||||||
|
|
||||||
|
class_courses = frappe.get_all("Class Course", {
|
||||||
|
"parent": classname
|
||||||
|
}, ["course", "title"])
|
||||||
|
|
||||||
|
for course in class_courses:
|
||||||
|
course.membership = frappe.db.get_value("LMS Batch Membership", {
|
||||||
|
"member": context.student.name,
|
||||||
|
"course": course.course
|
||||||
|
}, ["progress"], as_dict=True)
|
||||||
|
course.quizzes = frappe.get_all("LMS Quiz", {"course": course.course}, ["name", "title"])
|
||||||
|
course.assignments = frappe.get_all("Lesson Assignment", {"course": course.course}, ["name", "assignment"])
|
||||||
|
|
||||||
|
print(class_courses)
|
||||||
|
context.class_courses = class_courses
|
||||||
Reference in New Issue
Block a user