From c8dbc18179c1b278fa7fa3c684f230365dd6de11 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 10 Nov 2022 20:21:43 +0530 Subject: [PATCH] feat: statistics page --- .../lesson_completion/lesson_completion.json | 33 +++++++ .../lms_batch_membership.json | 6 +- lms/lms/utils.py | 21 +++++ lms/lms/workspace/lms/lms.json | 4 +- lms/patches.txt | 3 +- lms/patches/v0_0/convert_progress_to_float.py | 8 ++ lms/patches/v0_0/set_member_in_progress.py | 1 + lms/public/css/style.css | 2 +- lms/public/js/common_functions.js | 89 ++++++++++++++----- lms/templates/statistics.html | 2 +- lms/templates/stats.html | 19 ---- lms/www/courses/index.html | 9 -- lms/www/courses/index.js | 40 +-------- lms/www/statistics/__init__.py | 0 lms/www/statistics/index.html | 46 ++++++++++ 15 files changed, 186 insertions(+), 97 deletions(-) create mode 100644 lms/lms/dashboard_chart/lesson_completion/lesson_completion.json create mode 100644 lms/patches/v0_0/convert_progress_to_float.py delete mode 100644 lms/templates/stats.html create mode 100644 lms/www/statistics/__init__.py create mode 100644 lms/www/statistics/index.html diff --git a/lms/lms/dashboard_chart/lesson_completion/lesson_completion.json b/lms/lms/dashboard_chart/lesson_completion/lesson_completion.json new file mode 100644 index 00000000..f38ccc2a --- /dev/null +++ b/lms/lms/dashboard_chart/lesson_completion/lesson_completion.json @@ -0,0 +1,33 @@ +{ + "based_on": "creation", + "chart_name": "Lesson Completion", + "chart_type": "Count", + "color": "#4463F0", + "creation": "2022-11-09 16:52:19.021695", + "custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}", + "docstatus": 0, + "doctype": "Dashboard Chart", + "document_type": "LMS Course Progress", + "dynamic_filters_json": "[]", + "filters_json": "[]", + "group_by_type": "Count", + "idx": 0, + "is_public": 1, + "is_standard": 1, + "modified": "2022-11-09 16:52:52.241756", + "modified_by": "Administrator", + "module": "LMS", + "name": "Lesson Completion", + "number_of_groups": 0, + "owner": "Administrator", + "parent_document_type": "", + "roles": [], + "source": "", + "time_interval": "Daily", + "timeseries": 1, + "timespan": "Last Month", + "type": "Line", + "use_report_chart": 0, + "value_based_on": "", + "y_axis": [] +} \ No newline at end of file diff --git a/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json b/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json index 1efcf744..903f66ce 100644 --- a/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json +++ b/lms/lms/doctype/lms_batch_membership/lms_batch_membership.json @@ -89,7 +89,7 @@ }, { "fieldname": "progress", - "fieldtype": "Data", + "fieldtype": "Float", "label": "Progress", "read_only": 1 }, @@ -116,7 +116,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2022-10-10 12:38:17.839525", + "modified": "2022-10-10 12:38:17.839526", "modified_by": "Administrator", "module": "LMS", "name": "LMS Batch Membership", @@ -141,4 +141,4 @@ "sort_order": "DESC", "states": [], "title_field": "member_name" -} \ No newline at end of file +} diff --git a/lms/lms/utils.py b/lms/lms/utils.py index f42d2b26..cada6ea3 100644 --- a/lms/lms/utils.py +++ b/lms/lms/utils.py @@ -654,3 +654,24 @@ def get_chart_data(chart_name, timespan, timegrain, from_date, to_date): ], "datasets": [{"name": chart.name, "values": [r[1] for r in result]}], } + + +@frappe.whitelist(allow_guest=True) +def get_course_completion_data(): + all_membership = frappe.db.count("LMS Batch Membership") + completed = frappe.db.count("LMS Batch Membership", { + "progress": ["like", "%100%"] + }) + + return { + "labels": ["Completed", "In Progress"], + "datasets": [ + { + "name": "Course Completion", + "values": [ + completed, + all_membership - completed + ], + } + ], + } diff --git a/lms/lms/workspace/lms/lms.json b/lms/lms/workspace/lms/lms.json index 3964ac72..02924879 100644 --- a/lms/lms/workspace/lms/lms.json +++ b/lms/lms/workspace/lms/lms.json @@ -143,7 +143,7 @@ "type": "Link" } ], - "modified": "2022-11-07 18:49:38.954136", + "modified": "2022-11-09 17:16:03.973258", "modified_by": "Administrator", "module": "LMS", "name": "LMS", @@ -169,7 +169,7 @@ "format": "{} Completed", "label": "Course Completed", "link_to": "LMS Batch Membership", - "stats_filter": "{\"progress\":[\"=\",\"100\"]}", + "stats_filter": "{\"progress\":[\"like\",\"%100%\"]}", "type": "DocType" }, { diff --git a/lms/patches.txt b/lms/patches.txt index 9438129d..9a0d5fec 100644 --- a/lms/patches.txt +++ b/lms/patches.txt @@ -34,4 +34,5 @@ lms.patches.v0_0.create_course_instructor_role #29-08-2022 lms.patches.v0_0.create_course_moderator_role lms.patches.v0_0.set_dashboard #11-10-2022 lms.patches.v0_0.set_courses_page_as_home -lms.patches.v0_0.set_member_in_progress +lms.patches.v0_0.set_member_in_progress #09-11-2022 +lms.patches.v0_0.convert_progress_to_float diff --git a/lms/patches/v0_0/convert_progress_to_float.py b/lms/patches/v0_0/convert_progress_to_float.py new file mode 100644 index 00000000..62489f45 --- /dev/null +++ b/lms/patches/v0_0/convert_progress_to_float.py @@ -0,0 +1,8 @@ +import frappe +from frappe.utils import flt + +def execute(): + frappe.reload_doc("lms", "doctype", "lms_course_progress") + progress_records = frappe.get_all("LMS Batch Membership", fields=["name", "progress"]) + for progress in progress_records: + frappe.db.set_value("LMS Batch Membership", progress.name, "progress", flt(progress.progress)) diff --git a/lms/patches/v0_0/set_member_in_progress.py b/lms/patches/v0_0/set_member_in_progress.py index e67f688a..7c9cff75 100644 --- a/lms/patches/v0_0/set_member_in_progress.py +++ b/lms/patches/v0_0/set_member_in_progress.py @@ -2,6 +2,7 @@ import frappe def execute(): + frappe.reload_doc("lms", "doctype", "lms_course_progress") progress_records = frappe.get_all("LMS Course Progress", fields=["name", "owner"]) for progress in progress_records: diff --git a/lms/public/css/style.css b/lms/public/css/style.css index a1be2240..65ef4106 100644 --- a/lms/public/css/style.css +++ b/lms/public/css/style.css @@ -1715,7 +1715,7 @@ li { grid-gap: 2rem; } -.tab-pane .stats-parent { +.statistics .stats-parent { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 1rem; } diff --git a/lms/public/js/common_functions.js b/lms/public/js/common_functions.js index a5e4bfe5..f8f9c2ef 100644 --- a/lms/public/js/common_functions.js +++ b/lms/public/js/common_functions.js @@ -16,6 +16,14 @@ frappe.ready(() => { $(document).on("click", ".btn-save-chapter", (e) => { save_chapter(e); }); + + if (window.location.pathname == "/statistics") { + generate_graph("New Signups", "#new-signups"); + generate_graph("Course Enrollments", "#course-enrollments"); + generate_graph("Lesson Completion", "#lesson-completion"); + generate_course_completion_graph(); + } + }); const setup_file_size = () => { @@ -51,13 +59,10 @@ const join_course = (e) => { callback: (data) => { if (data.message == "OK") { $(".no-preview-modal").modal("hide"); - frappe.show_alert( - { - message: __("Enrolled successfully"), - indicator: "green", - }, - 3 - ); + frappe.show_alert({ + message: __("Enrolled successfully"), + indicator: "green", + }, 3); setTimeout(function () { window.location.href = `/courses/${course}/learn/1.1`; }, 1000); @@ -81,15 +86,12 @@ const notify_user = (e) => { }, callback: (data) => { $(".no-preview-modal").modal("hide"); - frappe.show_alert( - { - message: __( - "You have opted to be notified for this course. You will receive an email when the course becomes available." - ), - indicator: "green", - }, - 3 - ); + frappe.show_alert({ + message: __( + "You have opted to be notified for this course. You will receive an email when the course becomes available." + ), + indicator: "green", + }, 3); setTimeout(() => { window.location.reload(); }, 3000); @@ -121,16 +123,15 @@ const add_chapter = (e) => { scroll_to_chapter_container(); }; + const scroll_to_chapter_container = () => { - $([document.documentElement, document.body]).animate( - { - scrollTop: $(".new-chapter").offset().top, - }, - 1000 - ); + $([document.documentElement, document.body]).animate({ + scrollTop: $(".new-chapter").offset().top, + }, 1000); $(".new-chapter").find(".chapter-title-main").focus(); }; + const save_chapter = (e) => { let target = $(e.currentTarget); let parent = target.closest(".chapter-parent"); @@ -155,3 +156,47 @@ const save_chapter = (e) => { }, }); }; + +const generate_graph = (chart_name, element, type="line") => { + let date = frappe.datetime; + + frappe.call({ + method: "lms.lms.utils.get_chart_data", + args: { + chart_name: chart_name, + timespan: "Select Date Range", + timegrain: "Daily", + from_date: date.add_days(date.get_today(), -30), + to_date: date.add_days(date.get_today(), +1) + }, + callback: (data) => { + render_chart(data.message, chart_name, element, type); + }, + }); +}; + +const render_chart = (data, chart_name, element, type) => { + const chart = new frappe.Chart(element, { + title: chart_name, + data: data, + type: type, + height: 250, + colors: ["#4563f1"], + axisOptions: { + xIsSeries: 1, + }, + lineOptions: { + regionFill: 1, + }, + }); +}; + + +const generate_course_completion_graph = () => { + frappe.call({ + method: "lms.lms.utils.get_course_completion_data", + callback: (data) => { + render_chart(data.message, "Course Completion", "#course-completion", "pie") + } + }) +} diff --git a/lms/templates/statistics.html b/lms/templates/statistics.html index 94ea9c1c..347107c4 100644 --- a/lms/templates/statistics.html +++ b/lms/templates/statistics.html @@ -48,7 +48,7 @@ {% if course_completion %} {% set course_completion_count = frappe.db.count("LMS Batch Membership", { - "progress":["=","100"] + "progress":["like","%100%"] }) %}
diff --git a/lms/templates/stats.html b/lms/templates/stats.html deleted file mode 100644 index e0f25fd1..00000000 --- a/lms/templates/stats.html +++ /dev/null @@ -1,19 +0,0 @@ -{% set published_courses = True %} -{% set total_signups = True %} -{% set enrollment_count = True %} -{% set course_completion = True %} -{% set lesson_completion = True %} -{% set quiz_completion = True %} - -
- {% include "lms/templates/statistics.html" %} - -
-
-
-
-
-
-
-
-
diff --git a/lms/www/courses/index.html b/lms/www/courses/index.html index a69c62ff..4940c100 100644 --- a/lms/www/courses/index.html +++ b/lms/www/courses/index.html @@ -84,11 +84,6 @@ {% endif %} -
@@ -126,10 +121,6 @@
{% endif %} -
- {% include "lms/templates/stats.html" %} -
-
{% endif %} diff --git a/lms/www/courses/index.js b/lms/www/courses/index.js index 3c4e9c8a..7d75a3d0 100644 --- a/lms/www/courses/index.js +++ b/lms/www/courses/index.js @@ -1,6 +1,4 @@ frappe.ready(() => { - generate_graph("New Signups"); - generate_graph("Course Enrollments"); $(".nav-link").click((e) => { change_hash(e); @@ -9,45 +7,9 @@ frappe.ready(() => { if (window.location.hash) { open_tab(); } + }); -const generate_graph = (chart_name) => { - let date = frappe.datetime; - - frappe.call({ - method: "lms.lms.utils.get_chart_data", - args: { - chart_name: chart_name, - timespan: "Select Date Range", - timegrain: "Daily", - from_date: date.add_days(date.get_today(), -30), - to_date: date.add_days(date.get_today(), +1), - }, - callback: (data) => { - render_chart(data.message, chart_name); - }, - }); -}; - -const render_chart = (data, chart_name) => { - let dom_element = - chart_name == "Course Enrollments" - ? "#course-enrollments" - : "#new-signups"; - const chart = new frappe.Chart(dom_element, { - title: chart_name, - data: data, - type: "line", - height: 250, - colors: ["#4563f1"], - axisOptions: { - xIsSeries: 1, - }, - lineOptions: { - regionFill: 1, - }, - }); -}; const change_hash = (e) => { window.location.hash = $(e.currentTarget).attr("href"); diff --git a/lms/www/statistics/__init__.py b/lms/www/statistics/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lms/www/statistics/index.html b/lms/www/statistics/index.html new file mode 100644 index 00000000..27881531 --- /dev/null +++ b/lms/www/statistics/index.html @@ -0,0 +1,46 @@ +{% extends "templates/base.html" %} + + +{% block title %} +{{ _("Statistics") }} +{% endblock %} + + +{% block content %} +
+
+
+ {{ _("Statistics") }} +
+ {% set published_courses = True %} + {% set total_signups = True %} + {% set enrollment_count = True %} + {% set course_completion = True %} + {% set lesson_completion = True %} + {% set quiz_completion = True %} + +
+ {% include "lms/templates/statistics.html" %} + +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+{% endblock %}