From e7a2eb737345aba5d6ee6c1d565da009bf33e3ee Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 31 Jul 2023 12:36:13 +0530 Subject: [PATCH] feat: student dashboard --- lms/lms/utils.py | 51 +++++++++--- lms/public/css/style.css | 79 +++++++++++++++++-- lms/templates/assessments.html | 60 ++++++++++++++ lms/templates/upcoming_evals.html | 45 +++++++++++ lms/www/classes/class.html | 90 ++++++++++++++++++--- lms/www/classes/class.js | 126 ++++++++++++++++++++++++++++++ lms/www/classes/class.py | 101 ++++++++++++++++-------- lms/www/classes/progress.html | 103 +----------------------- lms/www/classes/progress.js | 126 ------------------------------ lms/www/classes/progress.py | 24 ++---- 10 files changed, 498 insertions(+), 307 deletions(-) create mode 100644 lms/templates/assessments.html create mode 100644 lms/templates/upcoming_evals.html diff --git a/lms/lms/utils.py b/lms/lms/utils.py index db62cdcd..ecd65f35 100644 --- a/lms/lms/utils.py +++ b/lms/lms/utils.py @@ -57,21 +57,28 @@ def generate_slug(title, doctype): return slugify(title, used_slugs=slugs) -def get_membership(course, member, batch=None): +def get_membership(course, member=None, batch=None): + if not member: + member = frappe.session.user + filters = {"member": member, "course": course} if batch: filters["batch"] = batch - membership = frappe.db.get_value( - "LMS Batch Membership", - filters, - ["name", "batch", "current_lesson", "member_type", "progress"], - as_dict=True, - ) + is_member = frappe.db.exists("LMS Batch Membership", filters) + if is_member: + membership = frappe.db.get_value( + "LMS Batch Membership", + filters, + ["name", "batch", "current_lesson", "member_type", "progress"], + as_dict=True, + ) - if membership and membership.batch: - membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") - return membership + if membership and membership.batch: + membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title") + return membership + + return False def get_chapters(course): @@ -524,7 +531,7 @@ def has_course_moderator_role(member=None): def has_course_evaluator_role(member=None): return frappe.db.get_value( "Has Role", - {"parent": member or frappe.session.user, "role": "Evaluator"}, + {"parent": member or frappe.session.user, "role": "Class Evaluator"}, "name", ) @@ -700,7 +707,7 @@ def get_chart_data(chart_name, timespan, timegrain, from_date, to_date): } -@frappe.whitelist(allow_guest=True) +@frappe.whitelist() def get_course_completion_data(): all_membership = frappe.db.count("LMS Batch Membership") completed = frappe.db.count("LMS Batch Membership", {"progress": ["like", "%100%"]}) @@ -785,3 +792,23 @@ def get_evaluator(course, class_name=None): evaluator = frappe.db.get_value("LMS Course", course, "evaluator") return evaluator + + +def get_upcoming_evals(student, courses): + print(student, courses) + upcoming_evals = frappe.get_all( + "LMS Certificate Request", + { + "member": student, + "course": ["in", courses], + "date": [">=", frappe.utils.nowdate()], + }, + ["date", "start_time", "course", "evaluator", "google_meet_link"], + order_by="date", + ) + + for evals in upcoming_evals: + evals.course_title = frappe.db.get_value("LMS Course", evals.course, "title") + evals.evaluator_name = frappe.db.get_value("User", evals.evaluator, "full_name") + print(upcoming_evals) + return upcoming_evals diff --git a/lms/public/css/style.css b/lms/public/css/style.css index ca8cacf0..57508a17 100644 --- a/lms/public/css/style.css +++ b/lms/public/css/style.css @@ -326,7 +326,7 @@ input[type=checkbox] { border-radius: var(--border-radius-md); position: relative; border: 1px solid var(--gray-300); - box-shadow: var(--card-shadow); + box-shadow: var(--shadow-inset); } .course-card { @@ -1650,10 +1650,6 @@ li { color: var(--gray-600); } -.discussions-parent .empty-state { - background-color: var(--gray-200); -} - .job-cards-parent { display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); @@ -2204,4 +2200,77 @@ select { .rows .grid-row .grid-footer-toolbar, .grid-form-heading { cursor: none; +} + +.lms-page-style .discussions-section-title { + font-size: var(--text-lg); +} + +.class-dashboard .progress { + width: 150px; + height: 150px; + background: none; + position: relative; +} + +.class-dashboard .progress::after { + content: ""; + width: 100%; + height: 100%; + border-radius: 50%; + border: 6px solid #eee; + position: absolute; + top: 0; + left: 0; +} + +.class-dashboard .progress>span { + width: 50%; + height: 100%; + overflow: hidden; + position: absolute; + top: 0; + z-index: 1; +} + +.class-dashboard .progress .progress-left { + left: 0; +} + +.class-dashboard .progress .progress-bar { + width: 100%; + height: 100%; + background: none; + border-width: 6px; + border-style: solid; + position: absolute; + top: 0; +} + +.class-dashboard .progress .progress-left .progress-bar { + left: 100%; + border-top-right-radius: 80px; + border-bottom-right-radius: 80px; + border-left: 0; + -webkit-transform-origin: center left; + transform-origin: center left; +} + +.class-dashboard .progress .progress-right { + right: 0; +} + +.class-dashboard .progress .progress-right .progress-bar { + left: -100%; + border-top-left-radius: 80px; + border-bottom-left-radius: 80px; + border-right: 0; + -webkit-transform-origin: center right; + transform-origin: center right; +} + +.class-dashboard .progress .progress-value { + position: absolute; + top: 0; + left: 0; } \ No newline at end of file diff --git a/lms/templates/assessments.html b/lms/templates/assessments.html new file mode 100644 index 00000000..e5f1f0b0 --- /dev/null +++ b/lms/templates/assessments.html @@ -0,0 +1,60 @@ +
+
+ {{ _("Assessments") }} +
+ {% if assessments | length %} +
+
+
+
+
+ {{ _("Assessment") }} +
+
+ {{ _("Type") }} +
+
+ {{ _("Status/Score") }} +
+
+
+
+ {% for assessment in assessments %} + {% set has_access = is_moderator and assessment.submission or frappe.session.user == student.name %} +
+
+ + {{ assessment.title }} + +
+ {{ (assessment.assessment_type).split("LMS ")[1] }} +
+ +
+ {% if assessment.submission %} + {% if assessment.assessment_type == "LMS Assignment" %} + {% set status = assessment.submission.status %} + {% set color = "green" if status == "Pass" else "red" if status == "Fail" else "orange" %} +
+ {{ status }} +
+ {% else %} +
+ {{ assessment.submission.score }} +
+ {% endif %} + {% else %} +
+ {{ _("Not Attempted") }} +
+ {% endif %} +
+ +
+
+ {% endfor %} +
+ {% else %} +

{{ _("No Assessments") }}

+ {% endif %} +
\ No newline at end of file diff --git a/lms/templates/upcoming_evals.html b/lms/templates/upcoming_evals.html new file mode 100644 index 00000000..87dc783f --- /dev/null +++ b/lms/templates/upcoming_evals.html @@ -0,0 +1,45 @@ +
+
+ {{ _("Upcoming Evaluations") }} +
+ {% if upcoming_evals | length %} +
+ {% for eval in upcoming_evals %} +
+
+
+ {{ eval.course_title }} +
+ {% if eval.google_meet_link %} + + {{ _("Join") }} + + {% endif %} +
+ +
+ + + + + {{ frappe.utils.format_date(eval.date, "medium") }} -  + + + {{ frappe.utils.format_time(eval.start_time, "hh:mm a") }} + +
+
+ + {{ _("Evaluator") }}: + + + {{ eval.evaluator_name }} + +
+
+ {% endfor %} +
+ {% else %} +

{{ _("No Upcoming Evaluations") }}

+ {% endif %} +
\ No newline at end of file diff --git a/lms/www/classes/class.html b/lms/www/classes/class.html index 84b34ed1..b349ea3e 100644 --- a/lms/www/classes/class.html +++ b/lms/www/classes/class.html @@ -10,7 +10,7 @@ {{ BreadCrumb(class_info) }}
{{ ClassDetails(class_info) }} - {{ ClassSections(class_info, class_courses, class_students, published_courses) }} + {{ ClassSections(class_info, class_courses, class_students) }}
@@ -82,7 +82,7 @@ -{% macro ClassSections(class_info, class_courses, class_students, published_courses) %} +{% macro ClassSections(class_info, class_courses, class_students) %}
{% if is_moderator %} @@ -92,14 +92,17 @@ {% endif %}