From 27c01b3b0c742faeb96129c42b7e10d9c77531de Mon Sep 17 00:00:00 2001 From: pateljannat Date: Thu, 8 Jul 2021 10:55:03 +0530 Subject: [PATCH] fix: course details interactions --- community/lms/doctype/lesson/lesson.py | 35 ++-- .../lms/doctype/lms_course/lms_course.py | 9 ++ community/lms/widgets/ChapterTeaser.html | 34 +++- community/lms/widgets/MemberCard.html | 1 + community/lms/widgets/Reviews.html | 2 +- community/public/css/style.css | 117 ++++++++++++-- community/public/icons/white-tick.svg | 3 + community/www/batch/learn.html | 29 +++- community/www/batch/learn.js | 152 +++++++++++------- community/www/batch/utils.py | 2 +- community/www/courses/course.html | 6 +- community/www/courses/course.js | 2 +- community/www/courses/index.html | 17 +- 13 files changed, 307 insertions(+), 102 deletions(-) create mode 100644 community/public/icons/white-tick.svg diff --git a/community/lms/doctype/lesson/lesson.py b/community/lms/doctype/lesson/lesson.py index d90fa2c1..3b66ac0c 100644 --- a/community/lms/doctype/lesson/lesson.py +++ b/community/lms/doctype/lesson/lesson.py @@ -63,32 +63,35 @@ class Lesson(Document): return @frappe.whitelist() -def save_progress(lesson, course): +def save_progress(lesson, course, status): if not frappe.db.exists("LMS Batch Membership", { "member": frappe.session.user, "course": course }): return + if frappe.db.exists("LMS Course Progress", { "lesson": lesson, - "owner": frappe.session.user + "owner": frappe.session.user, + "course": course }): - return - - lesson_details = frappe.get_doc("Lesson", lesson) - dynamic_content = find_macros(lesson_details.body) - - status = "Complete" - if dynamic_content: - status = "Partially Complete" - - frappe.get_doc({ - "doctype": "LMS Course Progress", - "lesson": lesson_details.name, - "status": status - }).save(ignore_permissions=True) + doc = frappe.get_doc("LMS Course Progress", + { + "lesson": lesson, + "owner": frappe.session.user, + "course": course + }) + doc.status = status + doc.save(ignore_permissions=True) + else: + frappe.get_doc({ + "doctype": "LMS Course Progress", + "lesson": lesson, + "status": status, + }).save(ignore_permissions=True) + return "OK" def update_progress(lesson): user = frappe.session.user diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index 29b6bb8d..db38d76a 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -283,6 +283,15 @@ class LMSCourse(Document): def get_outline(self): return CourseOutline(self) + def get_progress(self, lesson): + return frappe.db.get_value("LMS Course Progress", + { + "course": self.name, + "owner": frappe.session.user, + "lesson": lesson + }, + ["status"]) + class CourseOutline: def __init__(self, course): self.course = course diff --git a/community/lms/widgets/ChapterTeaser.html b/community/lms/widgets/ChapterTeaser.html index e813f03e..a7b89ac7 100644 --- a/community/lms/widgets/ChapterTeaser.html +++ b/community/lms/widgets/ChapterTeaser.html @@ -1,21 +1,34 @@
+ +
+ {% if index != course.get_chapters() | length %}
{% endif %} @@ -36,16 +52,28 @@ diff --git a/community/lms/widgets/MemberCard.html b/community/lms/widgets/MemberCard.html index 87cb60b8..6889b5d4 100644 --- a/community/lms/widgets/MemberCard.html +++ b/community/lms/widgets/MemberCard.html @@ -11,4 +11,5 @@ Created {{ course_count }} {{ suffix }} {% endif %} + diff --git a/community/lms/widgets/Reviews.html b/community/lms/widgets/Reviews.html index 2d64ae20..0b365ef0 100644 --- a/community/lms/widgets/Reviews.html +++ b/community/lms/widgets/Reviews.html @@ -77,7 +77,7 @@ diff --git a/community/public/css/style.css b/community/public/css/style.css index 13e22076..b5455fa8 100644 --- a/community/public/css/style.css +++ b/community/public/css/style.css @@ -489,6 +489,7 @@ div.custom-checkbox>label>input:checked+img { padding: 24px; background: #E2E6E9; border-radius: 12px; + margin-top: 16px; } @media (max-width: 768px) { @@ -543,8 +544,8 @@ div.custom-checkbox>label>input:checked+img { @media (max-width: 768px) { .course-home-page { - padding: 0px; - width: 688px; + padding: 0px 0px 30px; + width: 90%; } } @@ -605,17 +606,26 @@ div.custom-checkbox>label>input:checked+img { } } -.wide-button { +.button { box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.13), 0px 0px 0.5px rgba(0, 0, 0, 0.5); border-radius: 6px; - padding: 12px 24px 12px; - margin-right: 16px; - height: 48px; cursor: pointer; display: flex; align-items: center; justify-content: center; width: fit-content; + padding: 8px 12px 8px; + font-size: 12px; + line-height: 135%; + letter-spacing: -0.011em; +} + +.wide-button { + padding: 12px 24px 12px; + height: 48px; + margin-right: 16px; + font-size: 16px; + line-height: 150%; } @media (max-width: 375px) { @@ -634,7 +644,7 @@ div.custom-checkbox>label>input:checked+img { } @media (max-width: 375px) { - .is-secondary { + .video-preview { margin-top: 16px; } } @@ -712,6 +722,7 @@ div.custom-checkbox>label>input:checked+img { line-height: 250%; letter-spacing: -0.011em; margin-bottom: 2px; + padding-left: 10px; } .chapter-content { @@ -910,11 +921,24 @@ div.custom-checkbox>label>input:checked+img { } .breadcrumb { - margin: 16px 10px 16px; + margin: 16px 10px 0px; } .course-details-outline { width: 352px; + margin-top: 16px; +} + +@media (max-width: 768px) { + .course-details-outline { + width: 688px; + } +} + +@media (max-width: 375px) { + .course-details-outline { + width: 312px; + } } .lesson-content-card { @@ -922,13 +946,20 @@ div.custom-checkbox>label>input:checked+img { flex-direction: column; } -.lesson-content { - width: 736px; -} - .course-content-parent { display: flex; justify-content: space-between; + flex-wrap: wrap-reverse; +} + +@media (max-width: 375px) { + .course-content-parent { + justify-content: center; + } +} + +.course-content-parent .course-home-headings { + margin: 0px 0px 16px; } .lesson-pagination { @@ -936,3 +967,65 @@ div.custom-checkbox>label>input:checked+img { justify-content: space-between; margin: 24px 0px 0px; } + +.lesson-pagination-parent { + width: 736px; + margin-top: 16px; +} + +@media (max-width: 768px) { + .lesson-pagination-parent { + width: 690px; + } +} + +@media (max-width: 375px) { + .lesson-pagination-parent { + width: 312px; + } +} + +.course-details-page { + padding: 0px 0px 80px; + display: flex; + flex-direction: column; + width: 1120px; + margin: 0 auto; +} + +@media (max-width: 768px) { + .course-details-page { + padding: 24px 0px 24px; + width: 90%; + } +} + +@media (max-width: 375px) { + .course-details-page { + width: 100%; + } +} + +.active-lesson { + background-color: #EBF5FF; + border-radius: 4px; +} + +.lesson-progress { + background: #BFDDF7; + padding: 4px 8px 4px; + font-size: 10px; + line-height: 120%; + margin: 0px 10px 20px; + border-radius: 4px; + font-weight: bold; +} + +.lesson-progress-tick { + width: 16px; + height: 16px; + background: #4C5A67; + border-radius: 2px; + padding: 2px; + margin: 0px 4px 4px; +} diff --git a/community/public/icons/white-tick.svg b/community/public/icons/white-tick.svg new file mode 100644 index 00000000..91da7b6d --- /dev/null +++ b/community/public/icons/white-tick.svg @@ -0,0 +1,3 @@ + + + diff --git a/community/www/batch/learn.html b/community/www/batch/learn.html index 945f7f7e..b9fa6506 100644 --- a/community/www/batch/learn.html +++ b/community/www/batch/learn.html @@ -21,7 +21,7 @@ {% block content %}
-
+
{{ widgets.Breadcrumb(course=course, lesson=lesson) }}
@@ -40,9 +40,10 @@ {% macro LessonContent(lesson) %}
-
{{ lesson.title }}
+
+ {{ lesson.title }} + COMPLETED +
{% if membership or lesson.include_in_preview %}
{{ lesson.render_html() }}
@@ -52,6 +53,7 @@ Checkout Course Details.
{% endif %} +
{% endmacro %} @@ -59,22 +61,33 @@
{% if prev_url %} - + Prev {% endif %} -
+ {% if not course.is_mentor(frappe.session.user) and membership %} + + {% if course.get_progress(lesson.name) != "Complete" %} +
Mark as Complete
+ {% else %} +
+ Mark as Incomplete +
+ {% endif %} + + {% endif %} {% if next_url %} - + Next - + {% endif %} +
{% endmacro %} diff --git a/community/www/batch/learn.js b/community/www/batch/learn.js index 69699ac4..eaf124d0 100644 --- a/community/www/batch/learn.js +++ b/community/www/batch/learn.js @@ -1,69 +1,111 @@ frappe.ready(() => { - /* Save Lesson Progress */ - if ($(".title").attr("data-membership") && !$(".title").hasClass("is_mentor")) { - frappe.call({ - method: "community.lms.doctype.lesson.lesson.save_progress", - args: { - lesson: $(".title").attr("data-lesson"), - course: $(".title").attr("data-course") - } - }) - } + highlight_active_lesson(); - /* Save Current Lesson */ + save_current_lesson(); + + $("#progress").click((e) => { + mark_progress(e); + }); + + $("#submit-quiz").click((e) => { + submit_quiz(e); + }); + + $("#try-again").click((e) => { + try_quiz_again(e); + }); + +}) + +var highlight_active_lesson = () => { + var selector = $(`a[href="${decodeURIComponent(window.location.pathname)}"]`).parent(); + if (selector.length) { + selector.addClass('active-lesson'); + } +} + +var save_current_lesson = () => { if ($(".title").attr("data-membership")) { frappe.call("community.lms.api.save_current_lesson", { course_name: $(".title").attr("data-course"), lesson_name: $(".title").attr("data-lesson") }) } +} - /* Submit Quiz */ - $("#submit-quiz").click((e) => { - e.preventDefault(); - console.log("click") - var result = []; - $('.question').each((i, element) => { - var options = $(element).find(".option"); - var answers = []; - options.filter((i, op) => $(op).prop("checked")).each((i, elem) => answers.push(decodeURIComponent(elem.value))); - result.push({ - "question": element.dataset.question, - "answer": answers - }); - }); - frappe.call({ - method: "community.lms.doctype.lms_quiz.lms_quiz.submit", - args: { - quiz: $("#title").text(), - result: result - }, - callback: (data) => { - $("#submit-quiz").addClass("hide"); - $("#try-again").removeClass("hide"); - $(":input[type='checkbox']").prop("disabled", true); - $(":input[type='radio']").prop("disabled", true); - if (data.message == result.length) { - $(".success-message").text("Congratulations, you cleared the quiz!"); - } - else { - $(".success-message").text("Some of your answers weren't correct. You can give it another shot."); - } - $(".score").text(`Score: ${data.message}/${result.length}`); +var mark_progress = (e) => { + var status = $(e.currentTarget).attr("data-progress"); + frappe.call({ + method: "community.lms.doctype.lesson.lesson.save_progress", + args: { + lesson: $(".title").attr("data-lesson"), + course: $(".title").attr("data-course"), + status: status + }, + callback: (data) => { + if (data.message == "OK") { + change_progress_indicators(status, e); } - }) + } }) +} - /* Try the quiz again */ - $("#try-again").click((e) => { - e.preventDefault(); - $(":input[type='checkbox']").prop("disabled", false); - $(":input[type='radio']").prop("disabled", false); - $("#quiz-form").trigger("reset"); - $(".success-message").text(""); - $(".score").text(""); - $("#submit-quiz").removeClass("hide"); - $("#try-again").addClass("hide"); +var change_progress_indicators = (status, e) => { + if (status == "Complete") { + $(".lesson-progress").removeClass("hide"); + $(".active-lesson .lesson-progress-tick").removeClass("hide"); + } + else { + $(".lesson-progress").addClass("hide"); + $(".active-lesson .lesson-progress-tick").addClass("hide"); + } + var label = status != "Complete" ? "Mark as Complete" : "Mark as Incomplete"; + var data_progress = status != "Complete" ? "Complete" : "Incomplete"; + $(e.currentTarget).text(label).attr("data-progress", data_progress); +} + +var submit_quiz = (e) => { + e.preventDefault(); + var result = []; + $('.question').each((i, element) => { + var options = $(element).find(".option"); + var answers = []; + options.filter((i, op) => $(op).prop("checked")).each((i, elem) => answers.push(decodeURIComponent(elem.value))); + result.push({ + "question": element.dataset.question, + "answer": answers + }); + }); + frappe.call({ + method: "community.lms.doctype.lms_quiz.lms_quiz.submit", + args: { + quiz: $("#title").text(), + result: result + }, + callback: (data) => { + $("#submit-quiz").addClass("hide"); + $("#try-again").removeClass("hide"); + $(":input[type='checkbox']").prop("disabled", true); + $(":input[type='radio']").prop("disabled", true); + if (data.message == result.length) { + $(".success-message").text("Congratulations, you cleared the quiz!"); + } + else { + $(".success-message").text("Some of your answers weren't correct. You can give it another shot."); + } + $(".score").text(`Score: ${data.message}/${result.length}`); + } }) -}) +} + +var try_quiz_again = (e) => { + e.preventDefault(); + $(":input[type='checkbox']").prop("disabled", false); + $(":input[type='radio']").prop("disabled", false); + $("#quiz-form").trigger("reset"); + $(".success-message").text(""); + $(".score").text(""); + $("#submit-quiz").removeClass("hide"); + $("#try-again").addClass("hide"); +} diff --git a/community/www/batch/utils.py b/community/www/batch/utils.py index ea8845c7..23060680 100644 --- a/community/www/batch/utils.py +++ b/community/www/batch/utils.py @@ -27,7 +27,7 @@ def get_common_context(context): context.members = course.get_mentors(membership.batch) + course.get_students(membership.batch) context.member_count = len(context.members) - context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else " " + context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" context.livecode_url = get_livecode_url() def get_livecode_url(): diff --git a/community/www/courses/course.html b/community/www/courses/course.html index 32afa4b6..3afb68c8 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -40,7 +40,7 @@
{% if not course.disable_self_learning and not membership %} -
+
Start Learning
@@ -49,13 +49,13 @@ {% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and membership.current_lesson else '1.1' %} - Continue Learning {% endif %} {% if course.video_link %} -
+
Watch Video Preview
diff --git a/community/www/courses/course.js b/community/www/courses/course.js index df100e71..5ce00524 100644 --- a/community/www/courses/course.js +++ b/community/www/courses/course.js @@ -132,7 +132,7 @@ var join_course = (e) => { if (data.message == "OK") { frappe.msgprint(__("You are now a student of this course.")); setTimeout(function () { - window.location.href = `/courses/${course}/home`; + window.location.href = `/courses/${course}/learn/1.1`; }, 2000); } } diff --git a/community/www/courses/index.html b/community/www/courses/index.html index 15c0c413..199a6625 100644 --- a/community/www/courses/index.html +++ b/community/www/courses/index.html @@ -65,17 +65,30 @@ {% endif %}
- {% if course.get_membership(frappe.session.user) %} + {% set membership = course.get_membership(frappe.session.user) %} + + {% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and + membership.current_lesson + else '1.1' %} + + {% set query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" %} + + {% if membership %} + + + {% else %} + + + {% endif %}
-
{% endmacro %}