Commit 5c764c29 by Omar Al-Ithawi

Working Edraak certificates

Conflicts:
	lms/templates/dashboard.html
parent 2b3e1acc
# -*- coding: utf-8 -*-
__author__ = 'omar'
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from reportlab.lib.pagesizes import landscape, A4
import arabicreshaper
from bidi.algorithm import get_display
import re
from os import path
from django.core.files.temp import NamedTemporaryFile
static_dir = path.join(path.dirname(__file__), 'assets')
light_font_url = path.join(static_dir, "DINNextLTArabic-Light.ttf")
pdfmetrics.registerFont(TTFont("DIN Next LT Arabic Light", light_font_url, validate=True))
bold_font_url = path.join(static_dir, "DinTextArabic-Bold.ttf")
pdfmetrics.registerFont(TTFont("DIN Next LT Arabic Bold", bold_font_url, validate=True))
SIZE = landscape(A4)
def course_org_to_logo(course_org):
if course_org == 'MITX' or course_org == 'HarvardX':
return 'edx.png'
elif course_org == u'بيت.كوم':
return 'bayt-logo2-en.png'
elif course_org == u'إدراك':
return 'qrta_logo.jpg'
elif course_org == 'AUB':
return 'Full-AUB-Seal.jpg'
else:
return ''
def text_to_bidi(text):
text = normalize_spaces(text)
reshaped_text = arabicreshaper.reshape(text)
bidi_text = get_display(reshaped_text)
return bidi_text
def course_org_disclaimer(course_org):
if course_org == 'MITX':
return (u'تم طرح هذا المساق من قبل إدراك تحت إشراف فريق من الأكاديمين الذين اشرفوا' +
u' على تعليم وإدارة النقاش وتقييم الأجوبة والإمتحانات، و ذلك بالتعاون مع معهد' +
u' ماسشوستس للتكنولوجيا .')
else:
return (u'تم طرح هذا المساق من قبل إدراك وتحت إشراف فريق من الأكاديمين ' +
u'الذين اشرفوا على تعليم وإدارة النقاش وتقييم الأجوبة والإمتحانات.')
def normalize_spaces(text):
return re.sub(' +', ' ', text)
class EdraakCertificate(object):
def __init__(self, user_profile_name, course_name, course_desc, instructor, course_end_date, course_org=None):
self.user_profile_name = user_profile_name
self.course_name = course_name
self.course_desc = course_desc
self.instructor = instructor
self.course_end_date = course_end_date
self.course_org = course_org
self.temp_file = NamedTemporaryFile(suffix='-cert.pdf')
self.ctx = None
def init_context(self):
ctx = canvas.Canvas(self.temp_file.name)
ctx.setPageSize(SIZE)
self.ctx = ctx
def add_certificate_bg(self):
width, height = SIZE
bg_path = path.join(static_dir, 'certificate_layout3.jpg')
self.ctx.drawImage(bg_path, 0, 0, width, height)
def _set_font(self, size, is_bold):
if is_bold:
font = "DIN Next LT Arabic Bold"
else:
font = "DIN Next LT Arabic Light"
self.ctx.setFont(font, size)
self.ctx.setFillColorRGB(66 / 255.0, 74 / 255.0, 82 / 255.0)
def draw_single_line_bidi_text(self, text, x, y, size, bold=False, max_width=7.494):
x *= inch
y *= inch
size *= inch
max_width *= inch
text = text_to_bidi(text)
while True:
self._set_font(size, bold)
lines = list(self._wrap_text(text, max_width))
if len(lines) > 1:
size *= 0.9 # reduce font size by 10%
else:
self.ctx.drawRightString(x, y, lines[0])
break
def draw_bidi_text(self, text, x, y, size, bold=False, max_width=7.494, lh_factor=1.3):
x *= inch
y *= inch
size *= inch
max_width *= inch
line_height = size * lh_factor
self._set_font(size, bold)
text = text_to_bidi(text)
for line in self._wrap_text(text, max_width):
self.ctx.drawRightString(x, y, line)
y -= line_height
def add_course_org_logo(self, course_org):
if course_org:
image = path.join(static_dir, course_org_to_logo(course_org))
self.ctx.drawImage(image, 3.519 * inch, 6.444 * inch, 2.467 * inch, 1.378 * inch)
def _wrap_text(self, text, max_width):
words = reversed(text.split(u' '))
def de_reverse(text_to_reverse):
return u' '.join(reversed(text_to_reverse.split(u' ')))
line = u''
for next_word in words:
next_width = self.ctx.stringWidth(line + u' ' + next_word)
if next_width >= max_width:
yield de_reverse(line).strip()
line = next_word
else:
line += u' ' + next_word
if line:
yield de_reverse(line).strip()
def save(self):
self.ctx.showPage()
self.ctx.save()
def generate_and_save(self):
self.init_context()
x = 10.8
self.add_certificate_bg()
self.add_course_org_logo(self.course_org)
self.draw_bidi_text(u'تم منح شهادة إتمام المساق هذﮦ إلى:', x, 5.8, size=0.25)
self.draw_single_line_bidi_text(self.user_profile_name, x, 5.124, size=0.5, bold=True)
self.draw_bidi_text(u'لإتمام المساق التالي بنجاح:', x, 4.63, size=0.25)
self.draw_bidi_text(self.course_name, x, 4.1, size=0.33, bold=True)
self.draw_bidi_text(self.course_desc, x, 3.78, size=0.16)
self.draw_single_line_bidi_text(self.instructor, x, 1.8, size=0.26, bold=True)
self.draw_bidi_text(course_org_disclaimer(self.course_org), x, 1.48, size=0.16)
self.draw_bidi_text(self.course_end_date, 2.7, 4.82, size=0.27)
self.save()
\ No newline at end of file
from django.conf import settings
from django.conf.urls import patterns, url
from django.core.urlresolvers import LocaleRegexURLResolver
urlpatterns = patterns('', # nopep8
url(r'^issue$', 'edraak_certificates.views.issue', name='edraak_certificates_issue'),
url(r'^download/(?P<course_id>[^/]+/[^/]+/[^/]+)$', 'edraak_certificates.views.download',
name='edraak_certificates_download'),
url(r'^preview/(?P<course_id>[^/]+/[^/]+/[^/]+)$', 'edraak_certificates.views.preview',
name='edraak_certificates_preview'),
)
import logging
from xmodule.modulestore.django import modulestore
from student.roles import CourseInstructorRole
from student.models import UserProfile
from courseware.courses import get_course_about_section
from .edraakcertificate import EdraakCertificate
from opaque_keys.edx import locator
logger = logging.getLogger(__name__)
def generate_certificate(request, course_id):
user = request.user
course_key = locator.CourseLocator.from_string(course_id)
course = modulestore().get_course(course_key)
course_name = course.display_name
course_end_date = ''
if course.end:
course_end_date = str(course.end.date())
course_short_desc = get_course_about_section(course, 'short_description')
instructor_name = ''
role = CourseInstructorRole(course_key)
if role.users_with_role():
instructor_user = role.users_with_role()[0]
instructor_name = UserProfile.objects.get(user=instructor_user).name
cert = EdraakCertificate(course_name=course_name,
user_profile_name=user.profile.name,
course_org=course.display_organization,
course_end_date=course_end_date,
course_desc=course_short_desc,
instructor=instructor_name)
cert.generate_and_save()
return cert.temp_file
\ No newline at end of file
import logging
import os
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.core.servers.basehttp import FileWrapper
from django.core.files.temp import NamedTemporaryFile
from django.contrib.auth.decorators import login_required
from edxmako.shortcuts import render_to_response
from wand.image import Image
from .utils import generate_certificate
logger = logging.getLogger(__name__)
@csrf_exempt
@login_required
def issue(request):
course_id = request.POST['certificate_course_id']
if request.session.get('course_pass_%s' % course_id):
user = request.user
return render_to_response('edraak_certificates/issue.html', {'user': user,
'course_id': course_id})
else:
return redirect(reverse('dashboard'))
@login_required
def download(request, course_id):
if request.session.get('course_pass_%s' % course_id):
pdf_file = generate_certificate(request, course_id)
wrapper = FileWrapper(pdf_file)
# `application/octet-stream` is to force download
response = HttpResponse(wrapper, content_type='application/octet-stream')
response['Content-Length'] = os.path.getsize(pdf_file.name)
response['Content-Disposition'] = "attachment; filename=Edraak-Certificate.pdf"
return response
else:
return redirect(reverse('dashboard'))
@login_required
def preview(request, course_id):
if request.session.get('course_pass_%s' % course_id):
pdf_file = generate_certificate(request, course_id)
image_file = NamedTemporaryFile(suffix='-cert.png')
with Image(filename=pdf_file.name) as img:
with img.clone() as i:
i.resize(445, 315)
i.save(filename=image_file.name)
wrapper = FileWrapper(image_file)
response = HttpResponse(wrapper, content_type='image/png')
response['Content-Length'] = os.path.getsize(image_file.name)
return response
else:
return redirect(reverse('dashboard'))
\ No newline at end of file
......@@ -1485,6 +1485,7 @@ INSTALLED_APPS = (
'edraak_misc',
'edraak_contact',
'edraak_bayt',
'edraak_certificates',
)
######################### MARKETING SITE ###############################
......
......@@ -42,6 +42,30 @@
verifyToggleBannerFailedOff: "${reverse('verify_student_toggle_failed_banner_off')}",
});
});
})(this);
$(function(){
accessible_modal(".edit-name", "#apply_name_change .close-modal", "#apply_name_change", "#dashboard-main");
accessible_modal(".edit-email", "#change_email .close-modal", "#change_email", "#dashboard-main");
accessible_modal("#pwd_reset_button", "#password_reset_complete .close-modal", "#password_reset_complete", "#dashboard-main");
$(".email-settings").each(function(index){
$(this).attr("id", "unenroll-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger
var trigger = "#" + $(this).attr("id");
accessible_modal(trigger, "#email-settings-modal .close-modal", "#email-settings-modal", "#dashboard-main");
});
$(".unenroll").each(function(index){
$(this).attr("id", "email-settings-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger
var trigger = "#" + $(this).attr("id");
accessible_modal(trigger, "#unenroll-modal .close-modal", "#unenroll-modal", "#dashboard-main");
});
});
</script>
</%block>
......@@ -405,3 +429,4 @@
## Available in Edraak theme
<%include file="bayt/_dashboard_popups.html" />
<%include file="edraak_certificates/_dashboard_popups.html" />
......@@ -226,6 +226,7 @@
## Available in Edraak theme
<%include file="../bayt/_dashboard_certificate_link.html" args="course=course" />
<%include file="../edraak_certificates/_dashboard_certificate_link.html" args="course=course" />
</section>
......
<%!
import logging
log = logging.getLogger(__name__)
log.error('Edraak theme is required for this module to work. Please use Edraak theme.')
%>
## Just an empty placeholder
## Actual implementation is available in Edraak theme
<%!
import logging
log = logging.getLogger(__name__)
log.error('Edraak theme is required for this module to work. Please use Edraak theme.')
%>
## Just an empty placeholder
## Actual implementation is available in Edraak theme
<%!
import logging
log = logging.getLogger(__name__)
log.error('Edraak theme is required for this module to work. Please use Edraak theme.')
%>
## Just an empty placeholder
## Actual implementation is available in Edraak theme
......@@ -71,6 +71,7 @@ urlpatterns = ('', # nopep8
url(r'', include('edraak_misc.urls')),
url(r'', include('edraak_contact.urls')),
url(r'', include('edraak_bayt.urls')),
url(r'^certificate/', include('edraak_certificates.urls')),
url(r'^embargo$', 'student.views.embargo', name="embargo"),
......
......@@ -143,3 +143,6 @@ git+https://github.com/mitocw/django-cas.git
# edX packages
edx-submissions==0.0.8
# Edraak packages
-r edraak/certificates.txt
\ No newline at end of file
# Used for printing the certificates
python-bidi==0.3.4
reportlab==3.1.8
wand==0.3.7
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment