From 69f322d34cb3b4187036c63cccede6b4e0853e60 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 11:38:27 +0530 Subject: [PATCH 1/7] fix: certification flow --- .../lms_certification/lms_certification.py | 4 ++-- school/public/css/style.css | 15 ++++++------ school/public/icons/search.svg | 2 +- school/www/courses/course.html | 12 ++++++++++ school/www/courses/course.js | 24 +++++++++++++++++-- school/www/courses/course.py | 2 +- 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/school/lms/doctype/lms_certification/lms_certification.py b/school/lms/doctype/lms_certification/lms_certification.py index 4f57c484..f0b29ee5 100644 --- a/school/lms/doctype/lms_certification/lms_certification.py +++ b/school/lms/doctype/lms_certification/lms_certification.py @@ -23,13 +23,13 @@ class LMSCertification(Document): @frappe.whitelist() def create_certificate(course): - certificate = is_certified() + certificate = is_certified(course) if certificate: return certificate else: - expires_after_yrs = int(course_details.expiry) + expires_after_yrs = int(frappe.db.get_value("LMS Course", course, "expiry")) expiry_date = None if expires_after_yrs: expiry_date = add_years(nowdate(), expires_after_yrs) diff --git a/school/public/css/style.css b/school/public/css/style.css index d7deff62..eb327077 100644 --- a/school/public/css/style.css +++ b/school/public/css/style.css @@ -92,8 +92,7 @@ input[type=checkbox] { background: #FFFFFF; border-radius: var(--border-radius-md); position: relative; - border: 1px solid #EEF0F2; - box-shadow: var(--shadow-base); + box-shadow: var(--shadow-sm); } .course-card { @@ -400,7 +399,6 @@ input[type=checkbox] { display: flex; align-items: center; justify-content: center; - width: fit-content; padding: 0.25rem 1.25rem; font-size: var(--text-md); line-height: 20px; @@ -424,6 +422,7 @@ input[type=checkbox] { .is-secondary { background: #FFFFFF; + color: inherit; } .is-secondary:hover { @@ -1274,17 +1273,17 @@ pre { } .search { background-image: url(/assets/frappe/icons/timeless/search.svg); - border: 1px solid #C8CFD5; - box-sizing: border-box; - border-radius: var(--border-radius); - font-size: 0.75rem; + border: none; + border-radius: var(--border-radius-md); + font-size: var(--text-sm); padding: 0.625rem 0.75rem; height: 36px; background-repeat: no-repeat; text-indent: 1.5rem; - background-position: 1rem 0.65rem; + background-position: 1rem 0.6rem; float: right; width: 25%; + background-color: var(--gray-100); } .section-heading { diff --git a/school/public/icons/search.svg b/school/public/icons/search.svg index 2cd7407c..287edd66 100644 --- a/school/public/icons/search.svg +++ b/school/public/icons/search.svg @@ -1,3 +1,3 @@ - + diff --git a/school/www/courses/course.html b/school/www/courses/course.html index 3cc0c72e..6412e64a 100644 --- a/school/www/courses/course.html +++ b/school/www/courses/course.html @@ -176,6 +176,18 @@ {% endif %} + {% set certificate = is_certified(course.name) %} + {% set progress = frappe.utils.cint(membership.progress) %} + {% if certificate %} + + {{ _("Get Certificate") }} + + {% elif course.enable_certification and progress == 100 %} +
+ {{ _("Get Certificate") }} +
+ {% endif %} +
{{ _("Course Include:") }}
{% if get_lessons(course.name) | length %}
diff --git a/school/www/courses/course.js b/school/www/courses/course.js index 511f09d8..f726eeb9 100644 --- a/school/www/courses/course.js +++ b/school/www/courses/course.js @@ -41,6 +41,10 @@ frappe.ready(() => { notify_user(e); }) + $("#certification").click((e) => { + create_certificate(e); + }); + }) var check_mentor_request = () => { @@ -196,7 +200,7 @@ var submit_review = (e) => { } } }) -} +}; var notify_user = (e) => { e.preventDefault(); @@ -216,4 +220,20 @@ var notify_user = (e) => { $("#notify-me").addClass("hide"); } }) -} +}; + +const create_certificate = (e) => { + e.preventDefault(); + course = $(e.currentTarget).attr("data-course"); + console.log(course) + console.log($(e.currentTarget)) + frappe.call({ + method: "school.lms.doctype.lms_certification.lms_certification.create_certificate", + args: { + "course": course + }, + callback: (data) => { + window.location.href = `/courses/${course}/${data.message}`; + } + }) +}; diff --git a/school/www/courses/course.py b/school/www/courses/course.py index 612088ef..2a55baae 100644 --- a/school/www/courses/course.py +++ b/school/www/courses/course.py @@ -13,7 +13,7 @@ def get_context(context): course = frappe.db.get_value("LMS Course", course_name, ["name", "title", "image", "short_introduction", "description", "is_published", "upcoming", - "disable_self_learning", "video_link"], + "disable_self_learning", "video_link", "enable_certification"], as_dict=True) related_courses = frappe.get_all("Related Courses", {"parent": course.name}, ["course"]) From ee9f858933720d5ad9201dbd02500bedfba13108 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 12:46:35 +0530 Subject: [PATCH 2/7] test: certificate creation --- .../lms_certification/lms_certification.py | 2 +- .../test_lms_certification.py | 20 ++++++++++++-- .../lms/doctype/lms_course/test_lms_course.py | 27 ++++++++++--------- school/www/batch/learn.js | 2 +- school/www/courses/course.js | 2 +- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/school/lms/doctype/lms_certification/lms_certification.py b/school/lms/doctype/lms_certification/lms_certification.py index f0b29ee5..d633d13d 100644 --- a/school/lms/doctype/lms_certification/lms_certification.py +++ b/school/lms/doctype/lms_certification/lms_certification.py @@ -42,4 +42,4 @@ def create_certificate(course): "expiry_date": expiry_date }) certificate.save(ignore_permissions=True) - return certificate.name + return certificate diff --git a/school/lms/doctype/lms_certification/test_lms_certification.py b/school/lms/doctype/lms_certification/test_lms_certification.py index 62df184a..e67ee33b 100644 --- a/school/lms/doctype/lms_certification/test_lms_certification.py +++ b/school/lms/doctype/lms_certification/test_lms_certification.py @@ -1,8 +1,24 @@ # Copyright (c) 2021, FOSS United and Contributors # See license.txt -# import frappe +import frappe import unittest +from school.lms.doctype.lms_course.lms_course import new_course +from school.lms.doctype.lms_certification.lms_certification import create_certificate class TestLMSCertification(unittest.TestCase): - pass + + def setup(self): + self.course = new_course("Test Certificate") + + def test_certificate_creation(self): + self.certificate = create_certificate(self.course.name) + self.assertEqual(self.certificate.student, "Administrator") + self.assertEqual(self.certificate.course, self.course.name) + self.assertEqual(self.certificate.issue_date, frappe.utils.nowdate()) + self.assertEqual(self.certificate.expiry_date, None) + + def tearDown(self): + frappe.db.delete("LMS Course", self.course.name) + frappe.db.delete("LMS Certification", self.certificate.name) + diff --git a/school/lms/doctype/lms_course/test_lms_course.py b/school/lms/doctype/lms_course/test_lms_course.py index 2cf891eb..7b592d69 100644 --- a/school/lms/doctype/lms_course/test_lms_course.py +++ b/school/lms/doctype/lms_course/test_lms_course.py @@ -12,18 +12,10 @@ class TestLMSCourse(unittest.TestCase): frappe.db.sql('delete from `tabLMS Course Mentor Mapping`') frappe.db.sql('delete from `tabLMS Course`') - def new_course(self, title): - doc = frappe.get_doc({ - "doctype": "LMS Course", - "title": title, - "short_introduction": title, - "description": title - }) - doc.insert(ignore_permissions=True) - return doc + def test_new_course(self): - course = self.new_course("Test Course") + course = new_course("Test Course") assert course.title == "Test Course" assert course.name == "test-course" @@ -32,7 +24,7 @@ class TestLMSCourse(unittest.TestCase): assert courses == [] # new couse, but not published - course = self.new_course("Test Course") + course = new_course("Test Course") assert courses == [] # publish the course @@ -45,7 +37,7 @@ class TestLMSCourse(unittest.TestCase): # disabled this test as it is failing def _test_add_mentors(self): - course = self.new_course("Test Course") + course = new_course("Test Course") assert course.get_mentors() == [] user = new_user("Tester", "tester@example.com") @@ -66,3 +58,14 @@ def new_user(name, email): first_name=name)) doc.insert() return doc + +def new_course(title, certificate=0): + doc = frappe.get_doc({ + "doctype": "LMS Course", + "title": title, + "short_introduction": title, + "description": title, + "enable_certificate": certificate + }) + doc.insert(ignore_permissions=True) + return doc diff --git a/school/www/batch/learn.js b/school/www/batch/learn.js index 25824704..7260a9a7 100644 --- a/school/www/batch/learn.js +++ b/school/www/batch/learn.js @@ -246,7 +246,7 @@ const create_certificate = (e) => { "course": course }, callback: (data) => { - window.location.href = `/courses/${course}/${data.message}`; + window.location.href = `/courses/${course}/${data.message.name}`; } }) }; diff --git a/school/www/courses/course.js b/school/www/courses/course.js index f726eeb9..cd2e62a2 100644 --- a/school/www/courses/course.js +++ b/school/www/courses/course.js @@ -233,7 +233,7 @@ const create_certificate = (e) => { "course": course }, callback: (data) => { - window.location.href = `/courses/${course}/${data.message}`; + window.location.href = `/courses/${course}/${data.message.name}`; } }) }; From 7e2f473e228253fc496ec9a88b3ca505616e18fd Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 13:05:47 +0530 Subject: [PATCH 3/7] fix: import statement --- school/lms/doctype/lms_certification/test_lms_certification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/school/lms/doctype/lms_certification/test_lms_certification.py b/school/lms/doctype/lms_certification/test_lms_certification.py index e67ee33b..3743d061 100644 --- a/school/lms/doctype/lms_certification/test_lms_certification.py +++ b/school/lms/doctype/lms_certification/test_lms_certification.py @@ -3,7 +3,7 @@ import frappe import unittest -from school.lms.doctype.lms_course.lms_course import new_course +from school.lms.doctype.lms_course.test_lms_course import new_course from school.lms.doctype.lms_certification.lms_certification import create_certificate class TestLMSCertification(unittest.TestCase): From 4b8cb5a4e45555f50131a1de52012103a4e92ef1 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 13:37:29 +0530 Subject: [PATCH 4/7] fix: test data --- .../test_lms_certification.py | 19 ++++++++----------- .../lms/doctype/lms_course/test_lms_course.py | 1 + 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/school/lms/doctype/lms_certification/test_lms_certification.py b/school/lms/doctype/lms_certification/test_lms_certification.py index 3743d061..1c800306 100644 --- a/school/lms/doctype/lms_certification/test_lms_certification.py +++ b/school/lms/doctype/lms_certification/test_lms_certification.py @@ -8,17 +8,14 @@ from school.lms.doctype.lms_certification.lms_certification import create_certif class TestLMSCertification(unittest.TestCase): - def setup(self): - self.course = new_course("Test Certificate") - def test_certificate_creation(self): - self.certificate = create_certificate(self.course.name) - self.assertEqual(self.certificate.student, "Administrator") - self.assertEqual(self.certificate.course, self.course.name) - self.assertEqual(self.certificate.issue_date, frappe.utils.nowdate()) - self.assertEqual(self.certificate.expiry_date, None) + course = new_course("Test Certificate", 1) + certificate = create_certificate(course.name) - def tearDown(self): - frappe.db.delete("LMS Course", self.course.name) - frappe.db.delete("LMS Certification", self.certificate.name) + self.assertEqual(certificate.student, "Administrator") + self.assertEqual(certificate.course, course.name) + self.assertEqual(certificate.issue_date, frappe.utils.nowdate()) + self.assertEqual(certificate.expiry_date, None) + frappe.db.delete("LMS Course", course.name) + frappe.db.delete("LMS Certification", certificate.name) diff --git a/school/lms/doctype/lms_course/test_lms_course.py b/school/lms/doctype/lms_course/test_lms_course.py index 7b592d69..3d0ae20e 100644 --- a/school/lms/doctype/lms_course/test_lms_course.py +++ b/school/lms/doctype/lms_course/test_lms_course.py @@ -60,6 +60,7 @@ def new_user(name, email): return doc def new_course(title, certificate=0): + print(title) doc = frappe.get_doc({ "doctype": "LMS Course", "title": title, From 9834c83126e38d8f0197928b374dfcf58351d532 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 13:43:11 +0530 Subject: [PATCH 5/7] revert: print statement --- school/lms/doctype/lms_course/test_lms_course.py | 1 - 1 file changed, 1 deletion(-) diff --git a/school/lms/doctype/lms_course/test_lms_course.py b/school/lms/doctype/lms_course/test_lms_course.py index 3d0ae20e..7b592d69 100644 --- a/school/lms/doctype/lms_course/test_lms_course.py +++ b/school/lms/doctype/lms_course/test_lms_course.py @@ -60,7 +60,6 @@ def new_user(name, email): return doc def new_course(title, certificate=0): - print(title) doc = frappe.get_doc({ "doctype": "LMS Course", "title": title, From cc0c1cc320e49c01ac59cc214825effff9a972ec Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 14:40:33 +0530 Subject: [PATCH 6/7] fix: removed console statements --- school/www/courses/course.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/school/www/courses/course.js b/school/www/courses/course.js index cd2e62a2..f59c3552 100644 --- a/school/www/courses/course.js +++ b/school/www/courses/course.js @@ -225,8 +225,6 @@ var notify_user = (e) => { const create_certificate = (e) => { e.preventDefault(); course = $(e.currentTarget).attr("data-course"); - console.log(course) - console.log($(e.currentTarget)) frappe.call({ method: "school.lms.doctype.lms_certification.lms_certification.create_certificate", args: { From 96c24e8e5fb24215008a14de1ad0ecf977499686 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 17 Feb 2022 14:56:33 +0530 Subject: [PATCH 7/7] test: certificate with expiry --- .../doctype/lms_certification/test_lms_certification.py | 9 +++++---- school/lms/doctype/lms_course/test_lms_course.py | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/school/lms/doctype/lms_certification/test_lms_certification.py b/school/lms/doctype/lms_certification/test_lms_certification.py index 1c800306..1585c79f 100644 --- a/school/lms/doctype/lms_certification/test_lms_certification.py +++ b/school/lms/doctype/lms_certification/test_lms_certification.py @@ -5,17 +5,18 @@ import frappe import unittest from school.lms.doctype.lms_course.test_lms_course import new_course from school.lms.doctype.lms_certification.lms_certification import create_certificate +from frappe.utils import nowdate, add_years, cint class TestLMSCertification(unittest.TestCase): def test_certificate_creation(self): - course = new_course("Test Certificate", 1) + course = new_course("Test Certificate", 1, 2) certificate = create_certificate(course.name) self.assertEqual(certificate.student, "Administrator") self.assertEqual(certificate.course, course.name) - self.assertEqual(certificate.issue_date, frappe.utils.nowdate()) - self.assertEqual(certificate.expiry_date, None) + self.assertEqual(certificate.issue_date, nowdate()) + self.assertEqual(certificate.expiry_date, add_years(nowdate(), cint(course.expiry))) - frappe.db.delete("LMS Course", course.name) frappe.db.delete("LMS Certification", certificate.name) + frappe.db.delete("LMS Course", course.name) diff --git a/school/lms/doctype/lms_course/test_lms_course.py b/school/lms/doctype/lms_course/test_lms_course.py index 7b592d69..64d27695 100644 --- a/school/lms/doctype/lms_course/test_lms_course.py +++ b/school/lms/doctype/lms_course/test_lms_course.py @@ -59,13 +59,14 @@ def new_user(name, email): doc.insert() return doc -def new_course(title, certificate=0): +def new_course(title, certificate=0, expiry=0): doc = frappe.get_doc({ "doctype": "LMS Course", "title": title, "short_introduction": title, "description": title, - "enable_certificate": certificate + "enable_certificate": certificate, + "expiry": expiry }) doc.insert(ignore_permissions=True) return doc