feat: certification
This commit is contained in:
@@ -63,7 +63,7 @@
|
||||
|
||||
<div>
|
||||
{% if prev_url %}
|
||||
<a class="button is-secondary dark-links" href="{{ prev_url }}">
|
||||
<a class="button is-secondary dark-links prev" href="{{ prev_url }}">
|
||||
<img class="mr-2" src="/assets/community/icons/left-arrow.svg">
|
||||
Prev
|
||||
</a>
|
||||
@@ -87,10 +87,14 @@
|
||||
|
||||
<div>
|
||||
{% if next_url %}
|
||||
<a class="button is-primary" href="{{ next_url }}">
|
||||
<a class="button is-primary next" href="{{ next_url }}">
|
||||
Next
|
||||
<img class="ml-2" src="/assets/community/icons/side-arrow-white.svg">
|
||||
</a>
|
||||
{% elif course.enable_certification %}
|
||||
<div class="button is-primary {% if course.get_course_progress() != 100 %} hide {% endif %}" id="certification">
|
||||
Get Certificate
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ frappe.ready(() => {
|
||||
try_quiz_again(e);
|
||||
});
|
||||
|
||||
$("#certification").click((e) => {
|
||||
create_certificate(e);
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
var save_current_lesson = () => {
|
||||
@@ -71,8 +75,9 @@ var mark_progress = (e) => {
|
||||
status: status
|
||||
},
|
||||
callback: (data) => {
|
||||
if (data.message == "OK") {
|
||||
change_progress_indicators(status, e);
|
||||
change_progress_indicators(status, e);
|
||||
if (data.message == 100 && !$(".next").length && $("#certification").hasClass("hide")) {
|
||||
$("#certification").removeClass("hide");
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -166,3 +171,17 @@ var add_to_local_storage = (quiz_name, current_index, answer, is_correct) => {
|
||||
quiz_stored ? quiz_stored.push(quiz_obj) : quiz_stored = [quiz_obj]
|
||||
localStorage.setItem(quiz_name, JSON.stringify(quiz_stored))
|
||||
}
|
||||
|
||||
var create_certificate = (e) => {
|
||||
e.preventDefault();
|
||||
course = $(".title").attr("data-course");
|
||||
frappe.call({
|
||||
method: "community.lms.doctype.lms_certification.lms_certification.create_certificate",
|
||||
args: {
|
||||
"course": course
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.href = `/courses/${course}/${data.message}`;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
23
community/www/courses/certificate.html
Normal file
23
community/www/courses/certificate.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends "templates/base.html" %}
|
||||
{% from "www/macros/common_macro.html" import MentorsSection %}
|
||||
|
||||
{% block title %} {{ student.full_name }} - {{ course.title }} {% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="common-page-style">
|
||||
<div class="container certificate-page">
|
||||
|
||||
<div class="breadcrumb">
|
||||
<a class="dark-links" href="/courses">All Courses</a>
|
||||
<img class="ml-1 mr-1" src="/assets/community/icons/chevron-right.svg">
|
||||
<a class="dark-links" href="/courses/{{ course.name }}">{{ course.title }}</a>
|
||||
</div>
|
||||
|
||||
<div class="comment-footer mb-5">
|
||||
<div class="button is-secondary pull-right" id="export-as-pdf" data-certificate="{{ certificate.name }}"
|
||||
data-certificate-name="{{ student.full_name }} - {{ course.title }}">Export as PDF</div>
|
||||
</div>
|
||||
{% include "community/templates/certificate.html" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
29
community/www/courses/certificate.js
Normal file
29
community/www/courses/certificate.js
Normal file
@@ -0,0 +1,29 @@
|
||||
frappe.ready(() => {
|
||||
|
||||
if ($(document).width() <= 550) {
|
||||
$(".certificate-footer").css("flex-direction", "column");
|
||||
$(".certificate-footer").children().addClass("mb-5");
|
||||
}
|
||||
|
||||
$("#export-as-pdf").click((e) => {
|
||||
export_as_pdf(e);
|
||||
})
|
||||
})
|
||||
|
||||
var export_as_pdf = (e) => {
|
||||
var button = $(e.currentTarget);
|
||||
button.text(__("Exporting..."));
|
||||
|
||||
html2canvas(document.querySelector('.common-card-style'), {
|
||||
scrollY: -window.scrollY,
|
||||
scrollX: 0
|
||||
}).then(function(canvas) {
|
||||
let dataURL = canvas.toDataURL('image/png');
|
||||
let a = document.createElement('a');
|
||||
a.href = dataURL;
|
||||
a.download = button.attr("data-certificate-name");
|
||||
a.click();
|
||||
}).finally(() => {
|
||||
button.text(__("Export as PDF"))
|
||||
});
|
||||
}
|
||||
31
community/www/courses/certificate.py
Normal file
31
community/www/courses/certificate.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import frappe
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
|
||||
try:
|
||||
course_name = frappe.form_dict["course"]
|
||||
certificate_name = frappe.form_dict["certificate"]
|
||||
except KeyError:
|
||||
redirect_to_course_list()
|
||||
|
||||
context.certificate = frappe.db.get_value("LMS Certification", certificate_name,
|
||||
["name", "student", "issue_date", "expiry_date", "course"], as_dict=True)
|
||||
|
||||
if context.certificate.course != course_name:
|
||||
redirect_to_course_list()
|
||||
|
||||
context.course = frappe.db.get_value("LMS Course", course_name,
|
||||
["owner", "title", "name"], as_dict=True)
|
||||
|
||||
context.instructor = frappe.db.get_value("User", context.course.owner,
|
||||
["full_name", "username"], as_dict=True)
|
||||
|
||||
context.student = frappe.db.get_value("User", context.certificate.student,
|
||||
["full_name"], as_dict=True)
|
||||
|
||||
context.logo = frappe.db.get_single_value("Website Settings", "banner_image")
|
||||
|
||||
def redirect_to_course_list():
|
||||
frappe.local.flags.redirect_location = "/courses"
|
||||
raise frappe.Redirect
|
||||
@@ -70,6 +70,10 @@
|
||||
<img class="ml-2" src="/assets/community/images/play.png" />
|
||||
</div>
|
||||
{% endif %}
|
||||
{% set certificate = course.is_certified() %}
|
||||
{% if certificate %}
|
||||
<a class="button wide-button is-secondary dark-links" href="/courses/{{ course.name }}/{{ certificate }}">Get Certificate</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,7 +123,7 @@
|
||||
{% if progress != 100 %}
|
||||
Great work so far!
|
||||
{% else %}
|
||||
Excellent Work on completing this course 👏
|
||||
Excellent work on completing this course 👏
|
||||
{% endif %}
|
||||
</p>
|
||||
<p class="progress-text">
|
||||
|
||||
Reference in New Issue
Block a user