@@ -38,7 +38,7 @@ If no error occurs, the webserver should be available on http://localhost:8080/ | |||||
Enjoy ! | Enjoy ! | ||||
sudo apt install virtualenv git python3-virtualenv | |||||
sudo apt install virtualenv git python3-virtualenv imagemagick | |||||
sudo mkdir -p /srv/jm2l | sudo mkdir -p /srv/jm2l | ||||
cd /srv/jm2l/ | cd /srv/jm2l/ | ||||
@@ -15,7 +15,6 @@ pyramid.debug_notfound = false | |||||
pyramid.debug_routematch = false | pyramid.debug_routematch = false | ||||
pyramid.default_locale_name = en | pyramid.default_locale_name = en | ||||
pyramid.includes = | pyramid.includes = | ||||
pyramid_mailer.testing | |||||
pyramid_debugtoolbar | pyramid_debugtoolbar | ||||
pyramid_tm | pyramid_tm | ||||
pyramid_mako | pyramid_mako | ||||
@@ -30,31 +30,31 @@ def add_renderer_globals(event): | |||||
event['CurrentYear'] = CurrentYear | event['CurrentYear'] = CurrentYear | ||||
# @sched.scheduled_job('cron', day_of_week='sun', hour=22, minute=07) | |||||
# @sched.scheduled_job('cron', day_of_week='sun', hour=22, minute=7) | |||||
def mailer_tasks(config): | def mailer_tasks(config): | ||||
# Send the Welcome Mail | # Send the Welcome Mail | ||||
mailer = config.registry['mailer'] | mailer = config.registry['mailer'] | ||||
Contact = DBSession.query(User).filter(User.uid == 1).one() | |||||
contact = DBSession.query(User).filter(User.uid == 1).one() | |||||
request = Request.blank('/', base_url='http://jm2l.linux-azur.org') | request = Request.blank('/', base_url='http://jm2l.linux-azur.org') | ||||
request.registry = config.registry | request.registry = config.registry | ||||
for StaffUser in DBSession.query(User).filter(User.Staff == True): | |||||
for staff_user in DBSession.query(User).filter(User.Staff is True): | |||||
# Skip mail to contact | # Skip mail to contact | ||||
if StaffUser == Contact: | |||||
if staff_user == contact: | |||||
continue | continue | ||||
# Skip those that have no task assigned | # Skip those that have no task assigned | ||||
if len(filter(lambda k: not k.closed, StaffUser.task_assoc)) == 0: | |||||
if len(filter(lambda k: not k.closed, staff_user.task_assoc)) == 0: | |||||
continue | continue | ||||
# Prepare Plain Text Message : | # Prepare Plain Text Message : | ||||
Mail_template = Template(filename='jm2l/templates/mail_plain.mako') | |||||
mail_plain = Mail_template.render(request=request, User=StaffUser, Contact=Contact, action="Tasks") | |||||
mail_template = Template(filename='jm2l/templates/mail_plain.mako') | |||||
mail_plain = mail_template.render(request=request, User=staff_user, Contact=contact, action="Tasks") | |||||
# Prepare HTML Message : | # Prepare HTML Message : | ||||
Mail_template = Template(filename='jm2l/templates/mail_html.mako') | |||||
mail_html = Mail_template.render(request=request, User=StaffUser, Contact=Contact, action="Tasks") | |||||
mail_template = Template(filename='jm2l/templates/mail_html.mako') | |||||
mail_html = mail_template.render(request=request, User=staff_user, Contact=contact, action="Tasks") | |||||
# Prepare Message | # Prepare Message | ||||
message = Message(subject="[JM2L] Le mail de rappel pour les JM2L !", | message = Message(subject="[JM2L] Le mail de rappel pour les JM2L !", | ||||
sender="contact@jm2l.linux-azur.org", | sender="contact@jm2l.linux-azur.org", | ||||
recipients=[StaffUser.mail], | |||||
recipients=[staff_user.mail], | |||||
body=mail_plain, html=mail_html) | body=mail_plain, html=mail_html) | ||||
message.add_bcc("spam@style-python.fr") | message.add_bcc("spam@style-python.fr") | ||||
@@ -81,8 +81,11 @@ def main(global_config, **settings): | |||||
authentication_policy=authentication_policy, | authentication_policy=authentication_policy, | ||||
authorization_policy=authorization_policy | authorization_policy=authorization_policy | ||||
) | ) | ||||
#config.include('pyramid_mailer') | |||||
config.include('pyramid_mailer.debug') | |||||
config.add_subscriber(add_renderer_globals, BeforeRender) | config.add_subscriber(add_renderer_globals, BeforeRender) | ||||
config.registry['mailer'] = mailer_factory_from_settings(settings) | |||||
print(settings) | |||||
# config.registry['mailer'] = mailer_factory_from_settings(settings) | |||||
config.registry['event_date'] = JM2L_Year.get_latest_jm2l_startdate() | config.registry['event_date'] = JM2L_Year.get_latest_jm2l_startdate() | ||||
sched = BackgroundScheduler() | sched = BackgroundScheduler() | ||||
sched.add_job(mailer_tasks, 'cron', day_of_week='fri', hour=18, args=[config]) | sched.add_job(mailer_tasks, 'cron', day_of_week='fri', hour=18, args=[config]) | ||||
@@ -154,7 +157,7 @@ def main(global_config, **settings): | |||||
config.add_route('edit_event', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}') | config.add_route('edit_event', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}') | ||||
config.add_route('delete_event', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}/delete') | config.add_route('delete_event', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}/delete') | ||||
## Entities | |||||
# Entities | |||||
config.add_route('entities', '/entities') # {sep:/*}{Nature:\w+?}') | config.add_route('entities', '/entities') # {sep:/*}{Nature:\w+?}') | ||||
config.add_route('add_entity', '/entity') | config.add_route('add_entity', '/entity') | ||||
config.add_route('delete_entity', r'/entity/{entity_id:(\d+)}/delete') | config.add_route('delete_entity', r'/entity/{entity_id:(\d+)}/delete') | ||||
@@ -162,7 +165,7 @@ def main(global_config, **settings): | |||||
config.add_route('edit_entity', r'/entity/{tiers_type:(\w+)}/{entity_id:([\w-]+)}/edit') | config.add_route('edit_entity', r'/entity/{tiers_type:(\w+)}/{entity_id:([\w-]+)}/edit') | ||||
config.add_route('edit_entity_cat', '/categorie/entity') | config.add_route('edit_entity_cat', '/categorie/entity') | ||||
## Users | |||||
# Users | |||||
config.add_route('pict_user', '/user_picture') | config.add_route('pict_user', '/user_picture') | ||||
config.add_route('show_user', r'/user/{user_slug:([\w-]+)?}') | config.add_route('show_user', r'/user/{user_slug:([\w-]+)?}') | ||||
config.add_route('badge_user', r'/user/{user_slug:([\w-]+)?}/badge') | config.add_route('badge_user', r'/user/{user_slug:([\w-]+)?}/badge') | ||||
@@ -6,6 +6,7 @@ try: | |||||
from StringIO import StringIO | from StringIO import StringIO | ||||
except ImportError: | except ImportError: | ||||
from io import StringIO | from io import StringIO | ||||
import io | |||||
from pyramid.view import view_config | from pyramid.view import view_config | ||||
from .models import DBSession, User | from .models import DBSession, User | ||||
from reportlab.pdfgen import canvas | from reportlab.pdfgen import canvas | ||||
@@ -25,38 +26,38 @@ ICONSIZE = 10 * mm | |||||
def JM2L_Logo(canvas, Offset=(0, 0)): | def JM2L_Logo(canvas, Offset=(0, 0)): | ||||
OffX, OffY = Offset | |||||
logoobject = canvas.beginText() | |||||
logoobject.setFont('Logo', 32) | |||||
logoobject.setFillColorRGB(.83, 0, .33) | |||||
logoobject.setTextOrigin(OffX + 5, OffY + 17) | |||||
logoobject.textLines("JM2L") | |||||
canvas.drawText(logoobject) | |||||
yearobject = canvas.beginText() | |||||
yearobject.setFont("Helvetica-Bold", 10) | |||||
yearobject.setFillColorRGB(1, 1, 1) | |||||
yearobject.setTextRenderMode(0) | |||||
yearobject.setTextOrigin(OffX + 12, OffY + 35) | |||||
yearobject.setWordSpace(13) | |||||
yearobject.textLines(" ".join(str(CurrentYear))) | |||||
canvas.drawText(yearobject) | |||||
def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0, 0)): | |||||
Border = 0 | |||||
OffX, OffY = Offset | |||||
if StartPos is None: | |||||
StartPos = (30 * mm, 2) | |||||
StartX, StartY = StartPos | |||||
MaxX, MaxY = 34 * mm, 18 * mm | |||||
off_x, off_y = Offset | |||||
logo_object = canvas.beginText() | |||||
logo_object.setFont('Logo', 32) | |||||
logo_object.setFillColorRGB(.83, 0, .33) | |||||
logo_object.setTextOrigin(off_x + 5, off_y + 17) | |||||
logo_object.textLines("JM2L") | |||||
canvas.drawText(logo_object) | |||||
year_object = canvas.beginText() | |||||
year_object.setFont("Helvetica-Bold", 10) | |||||
year_object.setFillColorRGB(1, 1, 1) | |||||
year_object.setTextRenderMode(0) | |||||
year_object.setTextOrigin(off_x + 12, off_y + 35) | |||||
year_object.setWordSpace(13) | |||||
year_object.textLines(" ".join(str(CurrentYear))) | |||||
canvas.drawText(year_object) | |||||
def Tiers_Logo(canvas, DispUser, start_pos=None, Offset=(0, 0)): | |||||
border = 0 | |||||
off_x, off_y = Offset | |||||
if start_pos is None: | |||||
start_pos = (30 * mm, 2) | |||||
start_x, start_y = start_pos | |||||
max_x, max_y = 34 * mm, 18 * mm | |||||
num = 0 | num = 0 | ||||
canvas.setStrokeColorRGB(0.5, 0.5, 0.5) | canvas.setStrokeColorRGB(0.5, 0.5, 0.5) | ||||
Logos = list() | |||||
list_logos = list() | |||||
for thumb in DispUser.tiers: | for thumb in DispUser.tiers: | ||||
if thumb.ThumbLinks: | if thumb.ThumbLinks: | ||||
Logos.append(thumb.ThumbLinks[:3]) | |||||
# Logos = list(filter(lambda x: x.ThumbLinks, DispUser.tiers)[:3]) | |||||
list_logos.append(thumb.ThumbLinks[:3]) | |||||
# list_logos = list(filter(lambda x: x.ThumbLinks, DispUser.tiers)[:3]) | |||||
# Should We compute a better positionning for logos ? | # Should We compute a better positionning for logos ? | ||||
DicPos = {} | DicPos = {} | ||||
DicPos[1] = {0: (1. / 2, 1. / 2)} | DicPos[1] = {0: (1. / 2, 1. / 2)} | ||||
@@ -75,25 +76,25 @@ def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0, 0)): | |||||
3: (7. / 8, 1. / 4), 4: (1. / 8, 3. / 4), 5: (3. / 8, 3. / 4), | 3: (7. / 8, 1. / 4), 4: (1. / 8, 3. / 4), 5: (3. / 8, 3. / 4), | ||||
6: (5. / 8, 3. / 4), 7: (7. / 8, 3. / 4)} | 6: (5. / 8, 3. / 4), 7: (7. / 8, 3. / 4)} | ||||
# draw overall border | # draw overall border | ||||
# canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True) | |||||
for tiers in Logos: | |||||
FileName = tiers.ThumbLinks.pop().split("/")[-1] | |||||
ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName) | |||||
PosX = OffX + StartX + DicPos[len(Logos)][num][0] * MaxX - (ICONSIZE + Border) / 2 | |||||
PosY = OffY + StartY + DicPos[len(Logos)][num][1] * MaxY - (ICONSIZE + Border) / 2 | |||||
# canvas.roundRect(start_x, start_y, max_x, max_y, radius=2, stroke=True) | |||||
for tiers in list_logos: | |||||
file_name = tiers.ThumbLinks.pop().split("/")[-1] | |||||
image_path = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, file_name) | |||||
pos_x = off_x + start_x + DicPos[len(list_logos)][num][0] * max_x - (ICONSIZE + border) / 2 | |||||
pos_y = off_y + start_y + DicPos[len(list_logos)][num][1] * max_y - (ICONSIZE + border) / 2 | |||||
canvas.setLineWidth(.1) | canvas.setLineWidth(.1) | ||||
if len(Logos) > 1: | |||||
if len(list_logos) > 1: | |||||
size = ICONSIZE | size = ICONSIZE | ||||
else: | else: | ||||
size = ICONSIZE * 1.5 | size = ICONSIZE * 1.5 | ||||
canvas.drawImage(ImagePath, | |||||
PosX, PosY, size, size, | |||||
canvas.drawImage(image_path, | |||||
pos_x, pos_y, size, size, | |||||
preserveAspectRatio=True, | preserveAspectRatio=True, | ||||
anchor='c', | anchor='c', | ||||
mask='auto' | mask='auto' | ||||
) | ) | ||||
# draw icon border | # draw icon border | ||||
# canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True) | |||||
# canvas.roundRect(pos_x, pos_y, ICONSIZE, ICONSIZE, radius=2, stroke=True) | |||||
num += 1 | num += 1 | ||||
@@ -114,37 +115,37 @@ def QRCode(DispUser): | |||||
def one_badge(c, DispUser, Offset=(0, 0)): | def one_badge(c, DispUser, Offset=(0, 0)): | ||||
# Logo on Top | # Logo on Top | ||||
JM2L_Logo(c, Offset) | JM2L_Logo(c, Offset) | ||||
OffX, OffY = Offset | |||||
off_x, off_y = Offset | |||||
c.rect(OffX - 3, OffY - 3, WIDTH + 6, HEIGHT + 6, fill=0, stroke=1) | |||||
c.rect(off_x - 3, off_y - 3, WIDTH + 6, HEIGHT + 6, fill=0, stroke=1) | |||||
if DispUser.Staff: | if DispUser.Staff: | ||||
# Staff | # Staff | ||||
c.setFillColorRGB(.83, 0, .33) | c.setFillColorRGB(.83, 0, .33) | ||||
c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.setFillColorRGB(1, 1, 1) | c.setFillColorRGB(1, 1, 1) | ||||
c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "STAFF") | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "STAFF") | |||||
elif DispUser.is_Intervenant: | elif DispUser.is_Intervenant: | ||||
# Intervenant | # Intervenant | ||||
c.setFillColorRGB(.21, .67, .78) | c.setFillColorRGB(.21, .67, .78) | ||||
c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.setFillColorRGB(1, 1, 1) | c.setFillColorRGB(1, 1, 1) | ||||
c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Intervenant") | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Intervenant") | |||||
elif DispUser.is_crew: | elif DispUser.is_crew: | ||||
# Benevole | # Benevole | ||||
c.setFillColorRGB(.18, .76, .23) | c.setFillColorRGB(.18, .76, .23) | ||||
c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.setFillColorRGB(1, 1, 1) | c.setFillColorRGB(1, 1, 1) | ||||
c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Bénévole") | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Bénévole") | |||||
else: | else: | ||||
# Visiteur | # Visiteur | ||||
c.setFillColorRGB(.8, .8, .8) | c.setFillColorRGB(.8, .8, .8) | ||||
c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
c.setFillColorRGB(1, 1, 1) | c.setFillColorRGB(1, 1, 1) | ||||
c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Visiteur") | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Visiteur") | |||||
c.restoreState() | c.restoreState() | ||||
@@ -154,25 +155,25 @@ def one_badge(c, DispUser, Offset=(0, 0)): | |||||
# Feed Name and SurName | # Feed Name and SurName | ||||
if DispUser.prenom and DispUser.nom and len(DispUser.prenom) + len(DispUser.nom) > 18: | if DispUser.prenom and DispUser.nom and len(DispUser.prenom) + len(DispUser.nom) > 18: | ||||
if DispUser.pseudo: | if DispUser.pseudo: | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 0 * mm, "%s" % DispUser.prenom) | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 0 * mm, "%s" % DispUser.prenom) | |||||
# c.setFont('Courier', 17) | # c.setFont('Courier', 17) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) | |||||
else: | else: | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 4 * mm, "%s" % DispUser.prenom) | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 4 * mm, "%s" % DispUser.prenom) | |||||
# c.setFont('Courier', 17) | # c.setFont('Courier', 17) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) | |||||
else: | else: | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 0 * mm, "%s %s" % (DispUser.prenom, DispUser.nom)) | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 0 * mm, "%s %s" % (DispUser.prenom, DispUser.nom)) | |||||
if DispUser.pseudo: | if DispUser.pseudo: | ||||
c.setFont("Helvetica-Oblique", 18) | c.setFont("Helvetica-Oblique", 18) | ||||
c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 10 * mm, "%s" % DispUser.pseudo) | |||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 10 * mm, "%s" % DispUser.pseudo) | |||||
# Put QR code to user profile | # Put QR code to user profile | ||||
c.drawInlineImage(QRCode(DispUser), \ | |||||
OffX + WIDTH - 20 * mm - 5, OffY + 5, \ | |||||
20 * mm, 20 * mm, \ | |||||
preserveAspectRatio=True, \ | |||||
c.drawInlineImage(QRCode(DispUser), | |||||
off_x + WIDTH - 20 * mm - 5, off_y + 5, | |||||
20 * mm, 20 * mm, | |||||
preserveAspectRatio=True, | |||||
anchor='s') | anchor='s') | ||||
Tiers_Logo(c, DispUser, None, Offset) | Tiers_Logo(c, DispUser, None, Offset) | ||||
@@ -192,14 +193,14 @@ def badge_user(request): | |||||
# Ok let's generate a PDF Badge | # Ok let's generate a PDF Badge | ||||
# Register LiberationMono font | # Register LiberationMono font | ||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | |||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file)) | |||||
# Import font | # Import font | ||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | |||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo)) | |||||
pdf = StringIO() | |||||
out_img = StringIO() | |||||
pdf = io.BytesIO() | |||||
out_img = io.BytesIO() | |||||
c = canvas.Canvas(pdf, pagesize=(WIDTH, HEIGHT)) | c = canvas.Canvas(pdf, pagesize=(WIDTH, HEIGHT)) | ||||
c.translate(mm, mm) | c.translate(mm, mm) | ||||
@@ -211,23 +212,21 @@ def badge_user(request): | |||||
c.saveState() | c.saveState() | ||||
one_badge(c, DispUser) | one_badge(c, DispUser) | ||||
OutPDF = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf') | |||||
out_pdf = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf') | |||||
c.showPage() | c.showPage() | ||||
c._filename = OutPDF | |||||
c.save() | c.save() | ||||
pdf.seek(0) | pdf.seek(0) | ||||
if isoutpng: | if isoutpng: | ||||
OutPNG = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png') | |||||
out_png = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png') | |||||
# Let's generate a png file for website | # Let's generate a png file for website | ||||
with open("./%s" % OutPDF, 'wb') as pdff: | |||||
pdff.write(bytes(pdf.read(), 'utf8')) # .encode('utf8')) | |||||
with open("./%s" % out_pdf, 'wb') as pdff: | |||||
pdff.write(pdf.read()) | |||||
Command = ["convert", "-density", "150x150", OutPDF, OutPNG] | |||||
Command = ["convert", "-density", "150x150", out_pdf, out_png] | |||||
subprocess.call(Command) | subprocess.call(Command) | ||||
with open("./%s" % OutPNG, 'r') as pngfile: | |||||
out_img.write(bytes(pngfile.read(), 'utf8')) # bytes(pngfile.read(), "utf8")) | |||||
with open("./%s" % out_png, 'rb') as pngfile: | |||||
out_img.write(pngfile.read()) # pngfile.read(), "utf8")) | |||||
out_img.seek(0) | out_img.seek(0) | ||||
return Response(app_iter=out_img, content_type='image/png') | return Response(app_iter=out_img, content_type='image/png') | ||||
@@ -246,13 +245,13 @@ def planche_badge(request): | |||||
# .filter(User_Event.year_uid == year) | # .filter(User_Event.year_uid == year) | ||||
# Register LiberationMono font | # Register LiberationMono font | ||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | |||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file)) | |||||
# Import font | # Import font | ||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | |||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo)) | |||||
pdf = StringIO.StringIO() | |||||
pdf = io.BytesIO() | |||||
FULLWIDTH = 210 * mm | FULLWIDTH = 210 * mm | ||||
FULLHEIGHT = 297 * mm | FULLHEIGHT = 297 * mm | ||||
@@ -264,11 +263,11 @@ def planche_badge(request): | |||||
c.setCreator("linux-azur.org") | c.setCreator("linux-azur.org") | ||||
c.setTitle("Badge") | c.setTitle("Badge") | ||||
t = 0 | t = 0 | ||||
ListUser = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users) | |||||
for num, DispUser in enumerate(ListUser): | |||||
list_user = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users) | |||||
for num, disp_user in enumerate(list_user): | |||||
c.saveState() | c.saveState() | ||||
Offsets = (((num - t) % 2) * (WIDTH + 40) + 40, ((num - t) / 2) * (HEIGHT + 25) + 40) | |||||
one_badge(c, DispUser, Offsets) | |||||
offsets = (((num - t) % 2) * (WIDTH + 40) + 40, int(((num - t) / 2)) * (HEIGHT + 25) + 40) | |||||
one_badge(c, disp_user, offsets) | |||||
if num % 8 == 7: | if num % 8 == 7: | ||||
t = num + 1 | t = num + 1 | ||||
c.showPage() | c.showPage() | ||||
@@ -115,8 +115,8 @@ class _PyCaptcha_SineWarp(_PyCaptcha_WarpBase): | |||||
@view_config(route_name='captcha') | @view_config(route_name='captcha') | ||||
def DoCaptcha(request): | def DoCaptcha(request): | ||||
ImgSize = (230, 100) | |||||
work_img = Image.new('RGBA', ImgSize, (255, 255, 255, 0)) | |||||
img_size = (230, 100) | |||||
work_img = Image.new('RGBA', img_size, (255, 255, 255, 0)) | |||||
Xmax, Ymax = work_img.size | Xmax, Ymax = work_img.size | ||||
# Write something on it | # Write something on it | ||||
draw = ImageDraw.Draw(work_img) | draw = ImageDraw.Draw(work_img) | ||||
@@ -129,7 +129,7 @@ def DoCaptcha(request): | |||||
# Choose a word for captcha | # Choose a word for captcha | ||||
text = random.choice(TabMots) | text = random.choice(TabMots) | ||||
Xt, Yt = font.getsize(text) | Xt, Yt = font.getsize(text) | ||||
OrX, OrY = (ImgSize[0] - Xt) / 2, (ImgSize[1] - Yt) / 2 | |||||
OrX, OrY = (img_size[0] - Xt) / 2, (img_size[1] - Yt) / 2 | |||||
draw.text((OrX, OrY), text, font=font, fill="#000000") | draw.text((OrX, OrY), text, font=font, fill="#000000") | ||||
# Apply a Blur | # Apply a Blur | ||||
# work_img=work_img.filter(ImageFilter.BLUR) | # work_img=work_img.filter(ImageFilter.BLUR) | ||||
@@ -140,7 +140,7 @@ def DoCaptcha(request): | |||||
tx, ty = (random.uniform(0, 0.0003), random.uniform(0, 0.0003)) | tx, ty = (random.uniform(0, 0.0003), random.uniform(0, 0.0003)) | ||||
bx, by = (random.uniform(0.5, 0.8), random.uniform(0, 0.2)) | bx, by = (random.uniform(0.5, 0.8), random.uniform(0, 0.2)) | ||||
# Apply perspective to Captcha | # Apply perspective to Captcha | ||||
work_img = work_img.transform(ImgSize, Image.PERSPECTIVE, (ax, bx, -25, by, ay, -10, tx, ty)) | |||||
work_img = work_img.transform(img_size, Image.PERSPECTIVE, (ax, bx, -25, by, ay, -10, tx, ty)) | |||||
# Apply SinWarp to Captcha | # Apply SinWarp to Captcha | ||||
tr = Captcha_Img(Xmax, Ymax) | tr = Captcha_Img(Xmax, Ymax) | ||||
tr._image = work_img | tr._image = work_img | ||||
@@ -11,17 +11,20 @@ from wtforms.csrf.session import SessionCSRF | |||||
from datetime import timedelta | from datetime import timedelta | ||||
from jm2l.const import CurrentYear | from jm2l.const import CurrentYear | ||||
# What about an helper function | # What about an helper function | ||||
#def strip_filter(x) | |||||
# if x is no | |||||
strip_filter = lambda x: x.strip() if x else None | |||||
def strip_filter(x): | |||||
# strip_filter = lambda x: x.strip() if x else None | |||||
if x: | |||||
return x.strip() | |||||
return None | |||||
# get random string password with letters, digits, and symbols | # get random string password with letters, digits, and symbols | ||||
def get_random_string(length): | def get_random_string(length): | ||||
csrf_characters = string.ascii_letters + string.digits + string.punctuation | csrf_characters = string.ascii_letters + string.digits + string.punctuation | ||||
csrf = ''.join(random.choice(password_characters) for i in range(length)) | |||||
return csrf | |||||
csrf = ''.join(random.choice(csrf_characters) for i in range(length)) | |||||
return bytes(csrf, 'utf8') | |||||
class MyBaseForm(Form): | class MyBaseForm(Form): | ||||
@@ -155,32 +158,38 @@ class ConfCreateForm(MyBaseForm): | |||||
start_time = HiddenField() | start_time = HiddenField() | ||||
end_time = HiddenField() | end_time = HiddenField() | ||||
start_sel = SelectField(u'Début', coerce=int, | |||||
description=u"C'est une heure indicative correspondant au mieux à vos préférences " + | |||||
u"personnelles. Vous pouvez prendre un créneau horaire déjà réservé si vous avez des contraintes " | |||||
u"particulières. L'équipe des JM2L mettra à disposition plus de salle si nécessaire. En cas de conflit," + | |||||
u"l'organisation se réserve le droit de changer la salle et l'heure avec votre accord." | |||||
) | |||||
duration = SelectField(u'Durée', coerce=int, | |||||
description=u"Précisez ici la durée de votre intervention" | |||||
) | |||||
salle_uid = SelectField(u'Salle', coerce=int, | |||||
description=u"Choisissez ici la salle en fonction " | |||||
u"du nombres de personnes potentiellement intéressé par votre intervention " + | |||||
u"l'organisation se réserve le droit de changer la salle (avec votre accord)." | |||||
) | |||||
name = StringField(u'Le nom de votre ', | |||||
[validators.DataRequired(u'Vous devez spécifier un nom pour votre intérvention'), | |||||
validators.Length(min=1, max=80, message='entre 1 et 80 car')], | |||||
filters=[strip_filter]) | |||||
description = TextAreaField(u'Décrivez ici quelques détails à propos de votre intervention ', | |||||
[validators.Optional(), validators.Length(max=1000000)], | |||||
filters=[strip_filter] | |||||
) | |||||
start_sel = SelectField( | |||||
u'Début', coerce=int, | |||||
description=u"C'est une heure indicative correspondant au mieux à vos préférences " | |||||
u"personnelles. Vous pouvez prendre un créneau horaire déjà réservé si vous avez des contraintes " | |||||
u"particulières. L'équipe des JM2L mettra à disposition plus de salle si nécessaire. " | |||||
u"En cas de conflit," | |||||
u"l'organisation se réserve le droit de changer la salle et l'heure avec votre accord." | |||||
) | |||||
duration = SelectField( | |||||
u'Durée', coerce=int, | |||||
description=u"Précisez ici la durée de votre intervention") | |||||
salle_uid = SelectField( | |||||
u'Salle', coerce=int, | |||||
description=u"Choisissez ici la salle en fonction du nombres de personnes potentiellement " | |||||
u"intéressé par votre intervention l'organisation se réserve le droit de changer" | |||||
u" la salle (avec votre accord)." | |||||
) | |||||
name = StringField( | |||||
u'Le nom de votre ', | |||||
[validators.DataRequired(u'Vous devez spécifier un nom pour votre intérvention'), | |||||
validators.Length(min=1, max=80, message='entre 1 et 80 car')], | |||||
filters=[strip_filter] | |||||
) | |||||
description = TextAreaField( | |||||
u'Décrivez ici quelques détails à propos de votre intervention ', | |||||
[validators.Optional(), validators.Length(max=1000000)], | |||||
filters=[strip_filter] | |||||
) | |||||
class ConfUpdateForm(ConfCreateForm): | class ConfUpdateForm(ConfCreateForm): | ||||
@@ -223,9 +232,10 @@ class PlaceCreateForm(MyBaseForm): | |||||
filters=[strip_filter]) | filters=[strip_filter]) | ||||
name = StringField('Nom Complet', [validators.Length(min=1, max=80)], | name = StringField('Nom Complet', [validators.Length(min=1, max=80)], | ||||
filters=[strip_filter]) | filters=[strip_filter]) | ||||
gps_coord = StringField(u'Coordonnées GPS', [validators.Length(max=30), | |||||
validators.Regexp("^[0-9]+\.?[0-9]+,[0-9]+\.?[0-9]+$", | |||||
message=u"Le GPS devrait être sous la forme 43.6158372,7.0723401")], | |||||
gps_coord = StringField(u'Coordonnées GPS', | |||||
[validators.Length(max=30), | |||||
validators.Regexp("^[0-9]+\.?[0-9]+,[0-9]+\.?[0-9]+$", | |||||
message=u"Le GPS devrait être sous la forme 43.6158372,7.0723401")], | |||||
filters=[strip_filter]) | filters=[strip_filter]) | ||||
adresse = TextAreaField('Adresse', [validators.Length(max=100)], | adresse = TextAreaField('Adresse', [validators.Length(max=100)], | ||||
filters=[strip_filter]) | filters=[strip_filter]) | ||||
@@ -600,13 +610,16 @@ class PropMForm(MyBaseForm): | |||||
message=u"doit être sous la forme HH:MM")], | message=u"doit être sous la forme HH:MM")], | ||||
filters=[strip_filter]) | filters=[strip_filter]) | ||||
end_time = HiddenField() | end_time = HiddenField() | ||||
exch_categ = SelectField(u'Catégorie de matériel', coerce=int, | |||||
description=u"Choisissez une catégorie de bien matériel" | |||||
) | |||||
description = TextAreaField(u'Ajoutez quelques mots autour du matériel que vous proposez', filters=[strip_filter], | |||||
description=u"Décrivez ici quelques détails sur le matériel que vous souhaitez " | |||||
+ u"proposer. N'hésitez pas à donner des détails." | |||||
) | |||||
exch_categ = SelectField( | |||||
u'Catégorie de matériel', coerce=int, | |||||
description=u"Choisissez une catégorie de bien matériel" | |||||
) | |||||
description = TextAreaField( | |||||
u'Ajoutez quelques mots autour du matériel que vous proposez', | |||||
filters=[strip_filter], | |||||
description=u"Décrivez ici quelques détails sur le matériel " | |||||
u"que vous souhaitez proposer. N'hésitez pas à donner des détails." | |||||
) | |||||
class UpdateAskCForm(AskCForm, UpdateExchangeForm): | class UpdateAskCForm(AskCForm, UpdateExchangeForm): | ||||
@@ -5,6 +5,11 @@ import itertools | |||||
from jm2l.const import CurrentYear | from jm2l.const import CurrentYear | ||||
def get_current_year(): | |||||
""" This function is intended to return the year of the next edition """ | |||||
return CurrentYear | |||||
class DummySejour(object): | class DummySejour(object): | ||||
def __init__(self, event): | def __init__(self, event): | ||||
@@ -29,78 +34,78 @@ class Sejour_helpers(DummySejour): | |||||
# This function return the start of the event | # This function return the start of the event | ||||
return self.CurrentYear | return self.CurrentYear | ||||
def PossibleDate(self, typedate="arrival"): | |||||
def PossibleDate(self, type_date="arrival"): | |||||
arrival, departure = False, False | arrival, departure = False, False | ||||
TabResult = list() | |||||
if typedate == "arrival": | |||||
tab_result = list() | |||||
if type_date == "arrival": | |||||
# Let's say people should arrive until 2 day before | # Let's say people should arrive until 2 day before | ||||
arrival = True | arrival = True | ||||
myDayRange = range(2, -1, -1) | |||||
elif typedate == "departure": | |||||
my_day_range = range(2, -1, -1) | |||||
elif type_date == "departure": | |||||
# Let's say people should go back home until 2 day after | # Let's say people should go back home until 2 day after | ||||
departure = True | departure = True | ||||
myDayRange = range(3) | |||||
my_day_range = range(3) | |||||
else: | else: | ||||
return TabResult | |||||
return tab_result | |||||
if self.Sejour: | if self.Sejour: | ||||
ArrDate = datetime.strftime(self.Sejour.arrival_time, "%d %B %Y") | |||||
DepDate = datetime.strftime(self.Sejour.depart_time, "%d %B %Y") | |||||
arr_date = datetime.strftime(self.Sejour.arrival_time, "%d %B %Y") | |||||
dep_date = datetime.strftime(self.Sejour.depart_time, "%d %B %Y") | |||||
else: | else: | ||||
ArrDate = datetime.strftime(self.CurrentEventYear.start_time, "%d %B %Y") | |||||
DepDate = datetime.strftime(self.CurrentEventYear.end_time, "%d %B %Y") | |||||
arr_date = datetime.strftime(self.CurrentEventYear.start_time, "%d %B %Y") | |||||
dep_date = datetime.strftime(self.CurrentEventYear.end_time, "%d %B %Y") | |||||
for oneday in myDayRange: | |||||
for one_day in my_day_range: | |||||
if arrival: | if arrival: | ||||
TmpDay = self.CurrentEventYear.end_time - timedelta(days=oneday) | |||||
tmp_day = self.CurrentEventYear.end_time - timedelta(days=one_day) | |||||
elif departure: | elif departure: | ||||
TmpDay = self.CurrentEventYear.start_time + timedelta(days=oneday) | |||||
DayName = datetime.strftime(TmpDay, "%A") | |||||
DayNum = datetime.strftime(TmpDay, "%d/%m/%y") | |||||
DayString = datetime.strftime(TmpDay, "%d %B %Y") | |||||
if arrival and ArrDate == DayString: | |||||
TabResult.append((DayNum, DayName, 'selected="selected"')) | |||||
elif departure and DepDate == DayString: | |||||
TabResult.append((DayNum, DayName, 'selected="selected"')) | |||||
tmp_day = self.CurrentEventYear.start_time + timedelta(days=one_day) | |||||
day_name = datetime.strftime(tmp_day, "%A") | |||||
day_num = datetime.strftime(tmp_day, "%d/%m/%y") | |||||
day_string = datetime.strftime(tmp_day, "%d %B %Y") | |||||
if arrival and arr_date == day_string: | |||||
tab_result.append((day_num, day_name, 'selected="selected"')) | |||||
elif departure and dep_date == day_string: | |||||
tab_result.append((day_num, day_name, 'selected="selected"')) | |||||
else: | else: | ||||
TabResult.append((DayNum, DayName, "")) | |||||
return TabResult | |||||
tab_result.append((day_num, day_name, "")) | |||||
return tab_result | |||||
def PossibleTime(self, typedate="arrival"): | |||||
ArrTime, DepTime = "10:00", "19:00" | |||||
TabResult = list() | |||||
def PossibleTime(self, type_date="arrival"): | |||||
arr_time, dep_time = "10:00", "19:00" | |||||
tab_result = list() | |||||
if self.Sejour: | if self.Sejour: | ||||
ArrTime = datetime.strftime(self.Sejour.arrival_time, "%H:%M") | |||||
DepTime = datetime.strftime(self.Sejour.depart_time, "%H:%M") | |||||
arr_time = datetime.strftime(self.Sejour.arrival_time, "%H:%M") | |||||
dep_time = datetime.strftime(self.Sejour.depart_time, "%H:%M") | |||||
for hour in range(24): | for hour in range(24): | ||||
for minutes in range(0, 60, 10): | for minutes in range(0, 60, 10): | ||||
StrTime = "%.2d:%.2d" % (hour, minutes) | |||||
DispTime = "%dh%.2d" % (hour, minutes) | |||||
if typedate == "arrival" and StrTime == ArrTime: | |||||
TabResult.append((StrTime, DispTime, 'selected="selected"')) | |||||
elif typedate == "departure" and StrTime == DepTime: | |||||
TabResult.append((StrTime, DispTime, 'selected="selected"')) | |||||
str_time = "%.2d:%.2d" % (hour, minutes) | |||||
disp_time = "%dh%.2d" % (hour, minutes) | |||||
if type_date == "arrival" and str_time == arr_time: | |||||
tab_result.append((str_time, disp_time, 'selected="selected"')) | |||||
elif type_date == "departure" and str_time == dep_time: | |||||
tab_result.append((str_time, disp_time, 'selected="selected"')) | |||||
else: | else: | ||||
TabResult.append((StrTime, DispTime, "")) | |||||
return TabResult | |||||
tab_result.append((str_time, disp_time, "")) | |||||
return tab_result | |||||
def IsCheck(self, InputControl): | def IsCheck(self, InputControl): | ||||
ListControlA = ['Arrival', 'Departure'] | |||||
ListControlB = ['PMR', 'Cov', 'Bras', 'Other'] | |||||
if InputControl not in map(':'.join, itertools.product(ListControlA, ListControlB)): | |||||
list_control_a = ['Arrival', 'Departure'] | |||||
list_control_b = ['PMR', 'Cov', 'Bras', 'Other'] | |||||
if InputControl not in map(':'.join, itertools.product(list_control_a, list_control_b)): | |||||
return "" | return "" | ||||
if self.Sejour: | if self.Sejour: | ||||
if InputControl.startswith('Arrival'): | if InputControl.startswith('Arrival'): | ||||
CtrlVal = 2 ** ListControlB.index(InputControl[8:]) | |||||
if self.Sejour.arrival_check & CtrlVal == CtrlVal: | |||||
ctrl_val = 2 ** list_control_b.index(InputControl[8:]) | |||||
if self.Sejour.arrival_check & ctrl_val == ctrl_val: | |||||
return "checked=\"checked\"" | return "checked=\"checked\"" | ||||
else: | else: | ||||
return "" | return "" | ||||
elif InputControl.startswith('Departure'): | elif InputControl.startswith('Departure'): | ||||
CtrlVal = 2 ** ListControlB.index(InputControl[10:]) | |||||
if self.Sejour.depart_check & CtrlVal == CtrlVal: | |||||
ctrl_val = 2 ** list_control_b.index(InputControl[10:]) | |||||
if self.Sejour.depart_check & ctrl_val == ctrl_val: | |||||
return "checked=\"checked\"" | return "checked=\"checked\"" | ||||
else: | else: | ||||
return "" | return "" | ||||
@@ -146,9 +151,9 @@ class Orga_helpers(DummySejour): | |||||
def ChoosedList(self): | def ChoosedList(self): | ||||
""" Return choice validated by user """ | """ Return choice validated by user """ | ||||
ListOrga = [] | |||||
list_orga = [] | |||||
for num in range(0, len(self.Orga_tasks)): | for num in range(0, len(self.Orga_tasks)): | ||||
curs = 2 ** num | curs = 2 ** num | ||||
if self.Sejour.orga_part & curs == curs: | if self.Sejour.orga_part & curs == curs: | ||||
ListOrga.append(self.Orga_tasks[num]) | |||||
return ListOrga | |||||
list_orga.append(self.Orga_tasks[num]) | |||||
return list_orga |
@@ -1,9 +1,6 @@ | |||||
# -*- coding: utf8 -*- | # -*- coding: utf8 -*- | ||||
import io | |||||
from pyramid.response import Response | from pyramid.response import Response | ||||
try: | |||||
from StringIO import StringIO | |||||
except ImportError: | |||||
from io import StringIO | |||||
from pyramid.view import view_config | from pyramid.view import view_config | ||||
from .models import DBSession, Event, Salles | from .models import DBSession, Event, Salles | ||||
from reportlab.pdfgen import canvas | from reportlab.pdfgen import canvas | ||||
@@ -14,174 +11,174 @@ from .upload import MediaPath | |||||
from jm2l.const import CurrentYear | from jm2l.const import CurrentYear | ||||
# Create PDF container | # Create PDF container | ||||
EXPIRATION_TIME = 300 # seconds | |||||
EXPIRATION_TIME = 300 # seconds | |||||
WIDTH = 210 * mm | WIDTH = 210 * mm | ||||
HEIGHT = 297 * mm | HEIGHT = 297 * mm | ||||
ICONSIZE = 10 * mm | ICONSIZE = 10 * mm | ||||
def JM2L_large_Logo(canvas, Offset=(0,0)): | |||||
def JM2L_large_Logo(canvas, Offset=(0, 0)): | |||||
OffX, OffY = Offset | OffX, OffY = Offset | ||||
canvas.setFont('Logo', 110) | canvas.setFont('Logo', 110) | ||||
canvas.setFillColorRGB(.83,0,.33) | |||||
canvas.drawCentredString(WIDTH/2-OffY, HEIGHT-100-OffX, "JM2L") | |||||
canvas.setFillColorRGB(.83, 0, .33) | |||||
canvas.drawCentredString(WIDTH / 2 - OffY, HEIGHT - 100 - OffX, "JM2L") | |||||
canvas.setFont("Helvetica-Bold", 30) | canvas.setFont("Helvetica-Bold", 30) | ||||
yearobject = canvas.beginText() | |||||
yearobject.setFillColorRGB(1,1,1) | |||||
yearobject.setTextRenderMode(0) | |||||
yearobject.setTextOrigin(WIDTH/2-OffY-120, HEIGHT-36-OffX) | |||||
yearobject.setWordSpace(48) | |||||
yearobject.textLines("2 0 1 5") | |||||
yearobject.setWordSpace(1) | |||||
canvas.drawText(yearobject) | |||||
year_object = canvas.beginText() | |||||
year_object.setFillColorRGB(1, 1, 1) | |||||
year_object.setTextRenderMode(0) | |||||
year_object.setTextOrigin(WIDTH / 2 - OffY - 120, HEIGHT - 36 - OffX) | |||||
year_object.setWordSpace(48) | |||||
year_object.textLines("2 0 1 5") | |||||
year_object.setWordSpace(1) | |||||
canvas.drawText(year_object) | |||||
def one_time_step(canvas, str, hour, max_size, offset): | def one_time_step(canvas, str, hour, max_size, offset): | ||||
max_x, max_y = max_size | max_x, max_y = max_size | ||||
off_x, off_y = offset | off_x, off_y = offset | ||||
step_y = max_y/9 | |||||
half_step = step_y/2 | |||||
canvas.drawCentredString(off_x-30, max_y-step_y*hour+off_y-3, str) | |||||
hour_place = step_y*hour+off_y | |||||
canvas.line(off_x-5, hour_place, off_x, hour_place) | |||||
if hour<9: | |||||
canvas.line(off_x-2, hour_place+half_step, off_x, hour_place+half_step) | |||||
step_y = max_y / 9 | |||||
half_step = step_y / 2 | |||||
canvas.drawCentredString(off_x - 30, max_y - step_y * hour + off_y - 3, str) | |||||
hour_place = step_y * hour + off_y | |||||
canvas.line(off_x - 5, hour_place, off_x, hour_place) | |||||
if hour < 9: | |||||
canvas.line(off_x - 2, hour_place + half_step, off_x, hour_place + half_step) | |||||
@view_config(route_name='stand_print', http_cache = (EXPIRATION_TIME, {'public':True})) | |||||
@view_config(route_name='stand_print', http_cache=(EXPIRATION_TIME, {'public': True})) | |||||
def stand_print(request): | def stand_print(request): | ||||
# Ok let's generate a print for place schedule | # Ok let's generate a print for place schedule | ||||
# Register LiberationMono font | # Register LiberationMono font | ||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | |||||
# Import font | |||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | |||||
pdf = StringIO.StringIO() | |||||
c = canvas.Canvas( pdf, pagesize=(HEIGHT, WIDTH) ) | |||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file)) | |||||
# Import font | |||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo)) | |||||
pdf = io.BytesIO() | |||||
c = canvas.Canvas(pdf, pagesize=(HEIGHT, WIDTH)) | |||||
c.translate(mm, mm) | c.translate(mm, mm) | ||||
# Feed some metadata | # Feed some metadata | ||||
c.setCreator("linux-azur.org") | c.setCreator("linux-azur.org") | ||||
c.setTitle("Affiches stand") | c.setTitle("Affiches stand") | ||||
c.saveState() | c.saveState() | ||||
year = int(request.matchdict.get('year', CurrentYear)) | year = int(request.matchdict.get('year', CurrentYear)) | ||||
Events = DBSession.query(Event)\ | |||||
.filter(Event.for_year == year)\ | |||||
Events = DBSession.query(Event) \ | |||||
.filter(Event.for_year == year) \ | |||||
.filter(Event.event_type == "Stand") | .filter(Event.event_type == "Stand") | ||||
for ev in Events: | for ev in Events: | ||||
c.setFont('Logo', 50) | c.setFont('Logo', 50) | ||||
c.setFillColorRGB(.5,.5,.5) | |||||
c.drawString(HEIGHT-150, 30, "JM2L") | |||||
c.setFillColorRGB(.5, .5, .5) | |||||
c.drawString(HEIGHT - 150, 30, "JM2L") | |||||
c.setFont('Logo', 100) | c.setFont('Logo', 100) | ||||
c.setFillColorRGB(0.5,0.5,0.5) | |||||
c.drawCentredString(HEIGHT/2, WIDTH-90, "STAND", 0) | |||||
c.setFillColorRGB(0,0,0) | |||||
c.setFillColorRGB(0.5, 0.5, 0.5) | |||||
c.drawCentredString(HEIGHT / 2, WIDTH - 90, "STAND", 0) | |||||
c.setFillColorRGB(0, 0, 0) | |||||
c.setFont('Helvetica', 42) | c.setFont('Helvetica', 42) | ||||
c.drawCentredString(HEIGHT/2, WIDTH/2, ev.name, 0) | |||||
c.drawCentredString(HEIGHT / 2, WIDTH / 2, ev.name, 0) | |||||
c.showPage() | c.showPage() | ||||
c.save() | c.save() | ||||
pdf.seek(0) | pdf.seek(0) | ||||
return Response(app_iter=pdf, content_type = 'application/pdf' ) | |||||
return Response(app_iter=pdf, content_type='application/pdf') | |||||
@view_config(route_name='place_print', http_cache = (EXPIRATION_TIME, {'public':True})) | |||||
@view_config(route_name='place_print', http_cache=(EXPIRATION_TIME, {'public': True})) | |||||
def place_print(request): | def place_print(request): | ||||
# Ok let's generate a print for place schedule | # Ok let's generate a print for place schedule | ||||
# Register LiberationMono font | # Register LiberationMono font | ||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | |||||
# Import font | |||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | |||||
pdf = StringIO.StringIO() | |||||
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) ) | |||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf" | |||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file)) | |||||
# Import font | |||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf" | |||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo)) | |||||
pdf = io.BytesIO() | |||||
c = canvas.Canvas(pdf, pagesize=(WIDTH, HEIGHT)) | |||||
c.translate(mm, mm) | c.translate(mm, mm) | ||||
# Feed some metadata | # Feed some metadata | ||||
c.setCreator("linux-azur.org") | c.setCreator("linux-azur.org") | ||||
c.setTitle("Planning Salle") | c.setTitle("Planning Salle") | ||||
c.saveState() | c.saveState() | ||||
year = int(request.matchdict.get('year', CurrentYear)) | year = int(request.matchdict.get('year', CurrentYear)) | ||||
# Initialization | # Initialization | ||||
# Compute days used by all events matching the specified input year | # Compute days used by all events matching the specified input year | ||||
place_used = DBSession.query(Event.salle_uid)\ | |||||
.filter(Event.for_year == year)\ | |||||
.filter(Event.event_type != 'Stand')\ | |||||
.group_by(Event.salle_uid) | |||||
place_used = DBSession.query(Event.salle_uid) \ | |||||
.filter(Event.for_year == year) \ | |||||
.filter(Event.event_type != 'Stand') \ | |||||
.group_by(Event.salle_uid) | |||||
for place in place_used: | for place in place_used: | ||||
place_uid = place[0] | |||||
place_uid = place[0] | |||||
place_obj = Salles.by_id(place_uid) | place_obj = Salles.by_id(place_uid) | ||||
# Logo on Top | # Logo on Top | ||||
JM2L_large_Logo(c) | JM2L_large_Logo(c) | ||||
max_size = (WIDTH-110, HEIGHT-300) | |||||
max_size = (WIDTH - 110, HEIGHT - 300) | |||||
offset = (70, 90) | offset = (70, 90) | ||||
c.setFillColorRGB(.5,.5,.5) | |||||
c.setFillColorRGB(.5, .5, .5) | |||||
c.setFont('Liberation', 40) | c.setFont('Liberation', 40) | ||||
c.drawCentredString(WIDTH/2, HEIGHT-190, place_obj.name, 1) | |||||
c.drawCentredString(WIDTH / 2, HEIGHT - 190, place_obj.name, 1) | |||||
c.setFont('Liberation', 35) | c.setFont('Liberation', 35) | ||||
c.drawCentredString(WIDTH/2, HEIGHT-145, place_obj.place_type, 0 ) | |||||
c.setFont('Helvetica', 20) | |||||
c.drawCentredString(WIDTH/2, 55, place_obj.phy.name, 0) | |||||
c.drawCentredString(WIDTH / 2, HEIGHT - 145, place_obj.place_type, 0) | |||||
c.setFont('Helvetica', 20) | |||||
c.drawCentredString(WIDTH / 2, 55, place_obj.phy.name, 0) | |||||
# Timetable container | # Timetable container | ||||
c.setLineWidth(.1) | c.setLineWidth(.1) | ||||
c.setLineCap(2) | c.setLineCap(2) | ||||
#c.setFillColorRGB(0,0,1) | |||||
# c.setFillColorRGB(0,0,1) | |||||
c.rect(offset[0], offset[1], max_size[0], max_size[1], fill=0, stroke=1) | c.rect(offset[0], offset[1], max_size[0], max_size[1], fill=0, stroke=1) | ||||
c.setLineWidth(.5) | |||||
c.setLineWidth(.5) | |||||
# create time mark | # create time mark | ||||
c.setFillColorRGB(0,0,0) | |||||
c.setFillColorRGB(0, 0, 0) | |||||
c.setFont('Helvetica', 10) | c.setFont('Helvetica', 10) | ||||
for i in range(0,10): | |||||
one_time_step(c, "%.2dh00" % (i+10), i, max_size, offset) | |||||
#c.setFont('Helvetica', 12) | |||||
Events = DBSession.query(Event)\ | |||||
.filter(Event.for_year == year)\ | |||||
.filter(Event.salle_uid == place_uid)\ | |||||
.order_by(Event.start_time) | |||||
for i in range(0, 10): | |||||
one_time_step(c, "%.2dh00" % (i + 10), i, max_size, offset) | |||||
# c.setFont('Helvetica', 12) | |||||
Events = DBSession.query(Event) \ | |||||
.filter(Event.for_year == year) \ | |||||
.filter(Event.salle_uid == place_uid) \ | |||||
.order_by(Event.start_time) | |||||
for ev in Events: | for ev in Events: | ||||
place_time(c, ev, max_size, offset) | place_time(c, ev, max_size, offset) | ||||
#c.rect(70, 50, WIDTH-100, HEIGHT-250, fill=0, stroke=1) | |||||
# c.rect(70, 50, WIDTH-100, HEIGHT-250, fill=0, stroke=1) | |||||
c.showPage() | c.showPage() | ||||
c.save() | c.save() | ||||
pdf.seek(0) | pdf.seek(0) | ||||
return Response(app_iter=pdf, content_type = 'application/pdf' ) | |||||
return Response(app_iter=pdf, content_type='application/pdf') | |||||
def place_time(c, ev, max_size, offset): | def place_time(c, ev, max_size, offset): | ||||
max_x, max_y = max_size | max_x, max_y = max_size | ||||
off_x, off_y = offset | off_x, off_y = offset | ||||
minute = max_y/(9*60) | |||||
start_pos_y = ((int( ev.start_time.strftime('%H') )-10)*60 + int( ev.start_time.strftime('%M') )) * minute | |||||
stop_pos_y = ((int( ev.end_time.strftime('%H') )-10)*60 + int( ev.end_time.strftime('%M') )) * minute | |||||
c.setFillColorRGB(0.98,0.98,0.98) | |||||
c.rect(offset[0], max_y + off_y - start_pos_y, max_size[0], start_pos_y-stop_pos_y, fill=1, stroke=1) | |||||
c.setFillColorRGB(0,0,0) | |||||
#c.drawString(off_x+5, max_y + off_y - 15 - start_pos_y, ev.start_time.strftime('%H:%M'), 0) | |||||
c.setFont('Helvetica', 12) | |||||
c.drawCentredString(WIDTH/2, max_y + off_y - 35 - start_pos_y, ev.name, 0) | |||||
intervs = ', '.join( [x.slug for x in ev.intervenants] ) | |||||
c.setFont('Helvetica', 10) | |||||
c.drawCentredString(WIDTH/2, max_y + off_y - 55 - start_pos_y, intervs, 0) | |||||
minute = max_y / (9 * 60) | |||||
start_pos_y = ((int(ev.start_time.strftime('%H')) - 10) * 60 + int(ev.start_time.strftime('%M'))) * minute | |||||
stop_pos_y = ((int(ev.end_time.strftime('%H')) - 10) * 60 + int(ev.end_time.strftime('%M'))) * minute | |||||
c.setFillColorRGB(0.98, 0.98, 0.98) | |||||
c.rect(offset[0], max_y + off_y - start_pos_y, max_size[0], start_pos_y - stop_pos_y, fill=1, stroke=1) | |||||
c.setFillColorRGB(0, 0, 0) | |||||
# c.drawString(off_x+5, max_y + off_y - 15 - start_pos_y, ev.start_time.strftime('%H:%M'), 0) | |||||
c.setFont('Helvetica', 12) | |||||
c.drawCentredString(WIDTH / 2, max_y + off_y - 35 - start_pos_y, ev.name, 0) | |||||
intervs = ', '.join([x.slug for x in ev.intervenants]) | |||||
c.setFont('Helvetica', 10) | |||||
c.drawCentredString(WIDTH / 2, max_y + off_y - 55 - start_pos_y, intervs, 0) |
@@ -29,6 +29,7 @@ try: | |||||
from StringIO import StringIO | from StringIO import StringIO | ||||
except ImportError: | except ImportError: | ||||
from io import StringIO | from io import StringIO | ||||
import io | |||||
import paginate | import paginate | ||||
import unicodedata | import unicodedata | ||||
import datetime | import datetime | ||||
@@ -1002,7 +1003,7 @@ def list_users_csv(request): | |||||
.outerjoin(adalias) \ | .outerjoin(adalias) \ | ||||
.order_by(User.slug) \ | .order_by(User.slug) \ | ||||
.all() | .all() | ||||
FileHandle = StringIO.StringIO() | |||||
FileHandle = io.BytesIO() | |||||
fileWriter = csv.writer(FileHandle, delimiter=',', quotechar='"', quoting=csv.QUOTE_NONNUMERIC) | fileWriter = csv.writer(FileHandle, delimiter=',', quotechar='"', quoting=csv.QUOTE_NONNUMERIC) | ||||
fileWriter.writerow(["Identifiant_JM2L", "Nom", "Prenom", "Status_%s" % for_year]) | fileWriter.writerow(["Identifiant_JM2L", "Nom", "Prenom", "Status_%s" % for_year]) | ||||
for user, sejour in Data: | for user, sejour in Data: | ||||
@@ -1358,7 +1359,8 @@ def participer(request): | |||||
NewUser = TmpUsr | NewUser = TmpUsr | ||||
# Send the Welcome Mail | # Send the Welcome Mail | ||||
mailer = request.registry['mailer'] | |||||
# mailer = request.registry['mailer'] | |||||
mailer = request.mailer | |||||
# Prepare Plain Text Message : | # Prepare Plain Text Message : | ||||
Mail_template = Template(filename='jm2l/templates/mail_plain.mako') | Mail_template = Template(filename='jm2l/templates/mail_plain.mako') | ||||
mail_plain = Mail_template.render(request=request, User=NewUser, action="Welcome") | mail_plain = Mail_template.render(request=request, User=NewUser, action="Welcome") | ||||
@@ -11,6 +11,7 @@ with open(os.path.join(here, 'CHANGES.txt')) as f: | |||||
## Do not forget to run for lxml dependencies | ## Do not forget to run for lxml dependencies | ||||
## apt-get install libxml2-dev libxslt1-dev | ## apt-get install libxml2-dev libxslt1-dev | ||||
requires = [ | requires = [ | ||||
'pyramid', | 'pyramid', | ||||
'pyramid_chameleon', | 'pyramid_chameleon', | ||||
@@ -36,9 +37,11 @@ requires = [ | |||||
'passlib', | 'passlib', | ||||
'argon2_cffi', | 'argon2_cffi', | ||||
'paginate', | 'paginate', | ||||
'markupsafe' | |||||
'markupsafe', | |||||
'webhelpers2', | |||||
'email_validator', | |||||
'pyramid-scheduler' | |||||
] | ] | ||||
setup(name='JM2L', | setup(name='JM2L', | ||||
version='0.1', | version='0.1', | ||||
description='JM2L', | description='JM2L', | ||||