| @@ -19,7 +19,7 @@ from pyramid.request import Request | |||||
| from mako.template import Template | from mako.template import Template | ||||
| from .models import User | from .models import User | ||||
| from jm2l.const import CurrentYear | from jm2l.const import CurrentYear | ||||
| from models import JM2L_Year | |||||
| from .models import JM2L_Year | |||||
| import logging | import logging | ||||
| @@ -80,7 +80,7 @@ def main(global_config, **settings): | |||||
| authorization_policy=authorization_policy | authorization_policy=authorization_policy | ||||
| ) | ) | ||||
| config.add_subscriber(add_renderer_globals, BeforeRender) | config.add_subscriber(add_renderer_globals, BeforeRender) | ||||
| config.registry['mailer'] = mailer_factory_from_settings(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 ]) | ||||
| @@ -8,7 +8,7 @@ from pyramid_mailer import get_mailer | |||||
| from pyramid_mailer.message import Attachment, Message | from pyramid_mailer.message import Attachment, Message | ||||
| from .forms import UserPasswordForm | from .forms import UserPasswordForm | ||||
| from passlib.hash import argon2 | from passlib.hash import argon2 | ||||
| from security import check_logged | |||||
| from .security import check_logged | |||||
| import datetime | import datetime | ||||
| import re | import re | ||||
| @@ -1,7 +1,11 @@ | |||||
| # -*- coding: utf8 -*- | # -*- coding: utf8 -*- | ||||
| from pyramid.httpexceptions import HTTPNotFound, HTTPForbidden | from pyramid.httpexceptions import HTTPNotFound, HTTPForbidden | ||||
| from pyramid.response import Response | from pyramid.response import Response | ||||
| import cStringIO as StringIO | |||||
| 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, User | from .models import DBSession, User | ||||
| from reportlab.pdfgen import canvas | from reportlab.pdfgen import canvas | ||||
| @@ -12,78 +16,86 @@ import qrcode | |||||
| import subprocess | import subprocess | ||||
| from .upload import MediaPath | 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 = 85 * mm | WIDTH = 85 * mm | ||||
| HEIGHT = 60 * mm | HEIGHT = 60 * mm | ||||
| ICONSIZE = 10 * mm | ICONSIZE = 10 * mm | ||||
| def JM2L_Logo(canvas, Offset=(0,0)): | |||||
| def JM2L_Logo(canvas, Offset=(0, 0)): | |||||
| OffX, OffY = Offset | OffX, OffY = Offset | ||||
| logoobject = canvas.beginText() | logoobject = canvas.beginText() | ||||
| logoobject.setFont('Logo', 32) | logoobject.setFont('Logo', 32) | ||||
| logoobject.setFillColorRGB(.83,0,.33) | |||||
| logoobject.setTextOrigin(OffX+5, OffY+17) | |||||
| logoobject.setFillColorRGB(.83, 0, .33) | |||||
| logoobject.setTextOrigin(OffX + 5, OffY + 17) | |||||
| logoobject.textLines("JM2L") | logoobject.textLines("JM2L") | ||||
| canvas.drawText(logoobject) | canvas.drawText(logoobject) | ||||
| yearobject = canvas.beginText() | yearobject = canvas.beginText() | ||||
| yearobject.setFont("Helvetica-Bold", 10) | yearobject.setFont("Helvetica-Bold", 10) | ||||
| yearobject.setFillColorRGB(1,1,1) | |||||
| yearobject.setFillColorRGB(1, 1, 1) | |||||
| yearobject.setTextRenderMode(0) | yearobject.setTextRenderMode(0) | ||||
| yearobject.setTextOrigin(OffX+12 , OffY+35) | |||||
| yearobject.setTextOrigin(OffX + 12, OffY + 35) | |||||
| yearobject.setWordSpace(13) | yearobject.setWordSpace(13) | ||||
| yearobject.textLines(" ".join(str(CurrentYear))) | yearobject.textLines(" ".join(str(CurrentYear))) | ||||
| canvas.drawText(yearobject) | canvas.drawText(yearobject) | ||||
| def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0,0)): | |||||
| def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0, 0)): | |||||
| Border = 0 | Border = 0 | ||||
| OffX, OffY = Offset | OffX, OffY = Offset | ||||
| if StartPos is None: | if StartPos is None: | ||||
| StartPos = ( 30 * mm, 2 ) | |||||
| StartPos = (30 * mm, 2) | |||||
| StartX, StartY = StartPos | StartX, StartY = StartPos | ||||
| MaxX, MaxY = 34*mm, 18*mm | |||||
| MaxX, MaxY = 34 * mm, 18 * mm | |||||
| num = 0 | num = 0 | ||||
| canvas.setStrokeColorRGB(0.5,0.5,0.5) | |||||
| Logos = filter(lambda x:x.ThumbLinks, DispUser.tiers)[:3] | |||||
| canvas.setStrokeColorRGB(0.5, 0.5, 0.5) | |||||
| Logos = list() | |||||
| for thumb in DispUser.tiers: | |||||
| if thumb.ThumbLinks: | |||||
| Logos.append(thumb.ThumbLinks[:3]) | |||||
| # 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[2] = { 0:(1./3, 1./2), 1:(2./3, 1./2) } | |||||
| DicPos[3] = { 0:(1./2, 1./4), 1:(1./3, 3./4), 2:(2./3, 3./4) } | |||||
| DicPos[4] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./3, 3./4), | |||||
| 3:(2./3, 3./4) } | |||||
| DicPos[5] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./6, 3./4), | |||||
| 3:(3./6, 3./4), 4:(5./6, 3./4) } | |||||
| DicPos[6] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4), | |||||
| 3:(1./6, 3./4), 4:(3./6, 3./4), 5:(5./6, 3./4) } | |||||
| DicPos[7] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4), | |||||
| 3:(1./8, 3./4), 4:(3./8, 3./4), 5:(5./8, 3./4), | |||||
| 6:(7./8, 3./4) } | |||||
| DicPos[8] = { 0:(1./8, 1./4), 1:(3./8, 1./4), 2:(5./8, 1./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) } | |||||
| DicPos[1] = {0: (1. / 2, 1. / 2)} | |||||
| DicPos[2] = {0: (1. / 3, 1. / 2), 1: (2. / 3, 1. / 2)} | |||||
| DicPos[3] = {0: (1. / 2, 1. / 4), 1: (1. / 3, 3. / 4), 2: (2. / 3, 3. / 4)} | |||||
| DicPos[4] = {0: (1. / 3, 1. / 4), 1: (2. / 3, 1. / 4), 2: (1. / 3, 3. / 4), | |||||
| 3: (2. / 3, 3. / 4)} | |||||
| DicPos[5] = {0: (1. / 3, 1. / 4), 1: (2. / 3, 1. / 4), 2: (1. / 6, 3. / 4), | |||||
| 3: (3. / 6, 3. / 4), 4: (5. / 6, 3. / 4)} | |||||
| DicPos[6] = {0: (1. / 6, 1. / 4), 1: (3. / 6, 1. / 4), 2: (5. / 6, 1. / 4), | |||||
| 3: (1. / 6, 3. / 4), 4: (3. / 6, 3. / 4), 5: (5. / 6, 3. / 4)} | |||||
| DicPos[7] = {0: (1. / 6, 1. / 4), 1: (3. / 6, 1. / 4), 2: (5. / 6, 1. / 4), | |||||
| 3: (1. / 8, 3. / 4), 4: (3. / 8, 3. / 4), 5: (5. / 8, 3. / 4), | |||||
| 6: (7. / 8, 3. / 4)} | |||||
| DicPos[8] = {0: (1. / 8, 1. / 4), 1: (3. / 8, 1. / 4), 2: (5. / 8, 1. / 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)} | |||||
| # draw overall border | # draw overall border | ||||
| # canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True) | # canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True) | ||||
| for tiers in Logos: | for tiers in Logos: | ||||
| FileName = tiers.ThumbLinks.pop().split("/")[-1] | 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 | |||||
| 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.setLineWidth(.1) | canvas.setLineWidth(.1) | ||||
| if len(Logos)>1: | |||||
| if len(Logos) > 1: | |||||
| size = ICONSIZE | size = ICONSIZE | ||||
| else: | else: | ||||
| size = ICONSIZE*1.5 | |||||
| canvas.drawImage(ImagePath, | |||||
| PosX, PosY, size, size,\ | |||||
| preserveAspectRatio=True, | |||||
| anchor='c', | |||||
| mask='auto' | |||||
| ) | |||||
| size = ICONSIZE * 1.5 | |||||
| canvas.drawImage(ImagePath, | |||||
| PosX, PosY, size, size, | |||||
| preserveAspectRatio=True, | |||||
| anchor='c', | |||||
| mask='auto' | |||||
| ) | |||||
| # draw icon border | # draw icon border | ||||
| # canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True) | # canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True) | ||||
| num+=1 | |||||
| num += 1 | |||||
| def QRCode(DispUser): | def QRCode(DispUser): | ||||
| qr = qrcode.QRCode( | qr = qrcode.QRCode( | ||||
| @@ -98,78 +110,79 @@ def QRCode(DispUser): | |||||
| return qr.make_image() | return qr.make_image() | ||||
| 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 | OffX, OffY = Offset | ||||
| c.rect(OffX-3, OffY-3, WIDTH+6, HEIGHT+6, fill=0, stroke=1) | |||||
| c.rect(OffX - 3, OffY - 3, WIDTH + 6, HEIGHT + 6, fill=0, stroke=1) | |||||
| if DispUser.Staff: | if DispUser.Staff: | ||||
| # Staff | # Staff | ||||
| c.setFillColorRGB(.83,0,.33) | |||||
| c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1,1,1) | |||||
| c.setFillColorRGB(.83, 0, .33) | |||||
| c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1, 1, 1) | |||||
| c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
| c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "STAFF") | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "STAFF") | |||||
| elif DispUser.is_Intervenant: | elif DispUser.is_Intervenant: | ||||
| # Intervenant | # Intervenant | ||||
| c.setFillColorRGB(.21,.67,.78) | |||||
| c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1,1,1) | |||||
| c.setFillColorRGB(.21, .67, .78) | |||||
| c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1, 1, 1) | |||||
| c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
| c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Intervenant") | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Intervenant") | |||||
| elif DispUser.is_crew: | elif DispUser.is_crew: | ||||
| # Benevole | # Benevole | ||||
| c.setFillColorRGB(.18,.76,.23) | |||||
| c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1,1,1) | |||||
| c.setFillColorRGB(.18, .76, .23) | |||||
| c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
| 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(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Bénévole") | |||||
| else: | else: | ||||
| # Visiteur | # Visiteur | ||||
| c.setFillColorRGB(.8,.8,.8) | |||||
| c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1,1,1) | |||||
| c.setFillColorRGB(.8, .8, .8) | |||||
| c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0) | |||||
| c.setFillColorRGB(1, 1, 1) | |||||
| c.setFont('Liberation', 30) | c.setFont('Liberation', 30) | ||||
| c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Visiteur") | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Visiteur") | |||||
| c.restoreState() | c.restoreState() | ||||
| c.setFont('Liberation', 18) | c.setFont('Liberation', 18) | ||||
| c.setStrokeColorRGB(0,0,0) | |||||
| c.setFillColorRGB(0,0,0) | |||||
| c.setStrokeColorRGB(0, 0, 0) | |||||
| c.setFillColorRGB(0, 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.setFont('Courier', 17) | |||||
| c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom ) | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 0 * mm, "%s" % DispUser.prenom) | |||||
| # c.setFont('Courier', 17) | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom) | |||||
| else: | else: | ||||
| c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom ) | |||||
| #c.setFont('Courier', 17) | |||||
| c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom ) | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 4 * mm, "%s" % DispUser.prenom) | |||||
| # c.setFont('Courier', 17) | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + 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(OffX + WIDTH / 2, OffY + 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 ) | |||||
| # Put QR code to user profile | |||||
| c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 10 * mm, "%s" % DispUser.pseudo) | |||||
| # Put QR code to user profile | |||||
| c.drawInlineImage(QRCode(DispUser), \ | c.drawInlineImage(QRCode(DispUser), \ | ||||
| OffX+WIDTH - 20 * mm -5, OffY+5, \ | |||||
| 20 * mm, 20 * mm, \ | |||||
| preserveAspectRatio=True, \ | |||||
| anchor='s') | |||||
| Tiers_Logo(c, DispUser, None, Offset) | |||||
| @view_config(route_name='badge_user', http_cache = (EXPIRATION_TIME, {'public':True})) | |||||
| OffX + WIDTH - 20 * mm - 5, OffY + 5, \ | |||||
| 20 * mm, 20 * mm, \ | |||||
| preserveAspectRatio=True, \ | |||||
| anchor='s') | |||||
| Tiers_Logo(c, DispUser, None, Offset) | |||||
| @view_config(route_name='badge_user') # , http_cache=(EXPIRATION_TIME, {'public': True})) | |||||
| def badge_user(request): | def badge_user(request): | ||||
| isoutpng = request.params.get('png') | isoutpng = request.params.get('png') | ||||
| user_slug = request.matchdict.get('user_slug', None) | user_slug = request.matchdict.get('user_slug', None) | ||||
| if user_slug is None or len(user_slug)==0: | |||||
| if user_slug is None or len(user_slug) == 0: | |||||
| raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu") | raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu") | ||||
| # Query database | # Query database | ||||
| DispUser = User.by_slug(user_slug) | DispUser = User.by_slug(user_slug) | ||||
| @@ -177,48 +190,49 @@ def badge_user(request): | |||||
| raise HTTPNotFound() | raise HTTPNotFound() | ||||
| # 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" | ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | ||||
| pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | ||||
| # Import font | |||||
| # Import font | |||||
| ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | ||||
| pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | ||||
| pdf = StringIO.StringIO() | |||||
| out_img = StringIO.StringIO() | |||||
| c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) ) | |||||
| pdf = StringIO() | |||||
| out_img = StringIO() | |||||
| 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("Badge") | c.setTitle("Badge") | ||||
| c.saveState() | c.saveState() | ||||
| one_badge(c, DispUser) | |||||
| one_badge(c, DispUser) | |||||
| OutPDF = 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: | ||||
| OutPDF = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf') | |||||
| OutPNG = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png') | OutPNG = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png') | ||||
| # Let's generate a png file for website | |||||
| with open( OutPDF ,'wb') as pdff: | |||||
| pdff.write(pdf.read()) | |||||
| Command = ["convert","-density","150x150", OutPDF, OutPNG] | |||||
| # Let's generate a png file for website | |||||
| with open("./%s" % OutPDF, 'wb') as pdff: | |||||
| pdff.write(bytes(pdf.read(), 'utf8')) # .encode('utf8')) | |||||
| Command = ["convert", "-density", "150x150", OutPDF, OutPNG] | |||||
| subprocess.call(Command) | subprocess.call(Command) | ||||
| with open( OutPNG, 'rb') as pngfile: | |||||
| out_img.write(pngfile.read()) | |||||
| with open("./%s" % OutPNG, 'r') as pngfile: | |||||
| out_img.write(bytes(pngfile.read(), 'utf8')) # bytes(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') | |||||
| else: | else: | ||||
| return Response(app_iter=pdf, content_type = 'application/pdf' ) | |||||
| return Response(app_iter=pdf, content_type='application/pdf') | |||||
| @view_config(route_name='all_badges') | @view_config(route_name='all_badges') | ||||
| @@ -234,32 +248,32 @@ def planche_badge(request): | |||||
| # Register LiberationMono font | # Register LiberationMono font | ||||
| ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf" | ||||
| pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | pdfmetrics.registerFont(TTFont("Liberation", ttfFile)) | ||||
| # Import font | |||||
| # Import font | |||||
| ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf" | ||||
| pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo)) | ||||
| pdf = StringIO.StringIO() | pdf = StringIO.StringIO() | ||||
| FULLWIDTH = 210 * mm | FULLWIDTH = 210 * mm | ||||
| FULLHEIGHT = 297 * mm | FULLHEIGHT = 297 * mm | ||||
| c = canvas.Canvas( pdf, pagesize=(FULLWIDTH, FULLHEIGHT) ) | |||||
| c = canvas.Canvas(pdf, pagesize=(FULLWIDTH, FULLHEIGHT)) | |||||
| 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("Badge") | c.setTitle("Badge") | ||||
| t=0 | |||||
| t = 0 | |||||
| ListUser = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users) | ListUser = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users) | ||||
| for num, DispUser in enumerate(ListUser): | for num, DispUser in enumerate(ListUser): | ||||
| c.saveState() | c.saveState() | ||||
| Offsets = (((num-t)%2)*(WIDTH+40)+40, ((num-t)/2)*(HEIGHT+25)+40) | |||||
| Offsets = (((num - t) % 2) * (WIDTH + 40) + 40, ((num - t) / 2) * (HEIGHT + 25) + 40) | |||||
| one_badge(c, DispUser, Offsets) | one_badge(c, DispUser, Offsets) | ||||
| if num%8==7: | |||||
| t=num+1 | |||||
| if num % 8 == 7: | |||||
| t = num + 1 | |||||
| c.showPage() | c.showPage() | ||||
| 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') | |||||
| @@ -3,7 +3,10 @@ | |||||
| import random | import random | ||||
| from PIL import Image, ImageDraw, ImageFont, ImageFilter | from PIL import Image, ImageDraw, ImageFont, ImageFilter | ||||
| import cStringIO as StringIO | |||||
| try: | |||||
| from StringIO import StringIO | |||||
| except ImportError: | |||||
| from io import StringIO | |||||
| import math | import math | ||||
| from pyramid.view import view_config | from pyramid.view import view_config | ||||
| from .words import TabMots | from .words import TabMots | ||||
| @@ -1 +1 @@ | |||||
| CurrentYear = 2018 | |||||
| CurrentYear = 2020 | |||||
| @@ -4,61 +4,63 @@ from datetime import timedelta, datetime | |||||
| import itertools | import itertools | ||||
| from jm2l.const import CurrentYear | from jm2l.const import CurrentYear | ||||
| class DummySejour(object): | class DummySejour(object): | ||||
| def __init__(self, event): | def __init__(self, event): | ||||
| self.Me = event['request'].user | self.Me = event['request'].user | ||||
| self.CurrentEventYear = DBSession.query(JM2L_Year).filter(JM2L_Year.state=='Ongoing').first() | |||||
| self.CurrentEventYear = DBSession.query(JM2L_Year).filter(JM2L_Year.state == 'Ongoing').first() | |||||
| self.Sejour = None | self.Sejour = None | ||||
| if self.Me: | if self.Me: | ||||
| self.Sejour = DBSession.query(Sejour)\ | |||||
| .filter(Sejour.user_id==self.Me.uid)\ | |||||
| .filter(Sejour.for_year==self.CurrentEventYear.year_uid)\ | |||||
| self.Sejour = DBSession.query(Sejour) \ | |||||
| .filter(Sejour.user_id == self.Me.uid) \ | |||||
| .filter(Sejour.for_year == self.CurrentEventYear.year_uid) \ | |||||
| .first() | .first() | ||||
| class Sejour_helpers(DummySejour): | class Sejour_helpers(DummySejour): | ||||
| def __init__(self, event): | def __init__(self, event): | ||||
| super(Sejour_helpers, self).__init__(event) | super(Sejour_helpers, self).__init__(event) | ||||
| if self.Sejour and self.Sejour.arrival_time is None: | if self.Sejour and self.Sejour.arrival_time is None: | ||||
| self.Sejour = None | self.Sejour = None | ||||
| def StartEvent(self): | def StartEvent(self): | ||||
| # 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, typedate="arrival"): | ||||
| arrival, departure = False, False | arrival, departure = False, False | ||||
| TabResult = list() | TabResult = list() | ||||
| if typedate == "arrival": | if typedate == "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 = xrange(2,-1,-1) | |||||
| myDayRange = range(2, -1, -1) | |||||
| elif typedate == "departure": | elif typedate == "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 | |||||
| myDayRange = xrange(3) | |||||
| departure = True | |||||
| myDayRange = range(3) | |||||
| else: | else: | ||||
| return TabResult | return TabResult | ||||
| if self.Sejour: | if self.Sejour: | ||||
| ArrDate = datetime.strftime(self.Sejour.arrival_time,"%d %B %Y").decode('utf-8') | |||||
| DepDate = datetime.strftime(self.Sejour.depart_time,"%d %B %Y").decode('utf-8') | |||||
| ArrDate = datetime.strftime(self.Sejour.arrival_time, "%d %B %Y") | |||||
| DepDate = datetime.strftime(self.Sejour.depart_time, "%d %B %Y") | |||||
| else: | else: | ||||
| ArrDate = datetime.strftime( self.CurrentEventYear.start_time,"%d %B %Y" ).decode('utf-8') | |||||
| DepDate = datetime.strftime( self.CurrentEventYear.end_time,"%d %B %Y" ).decode('utf-8') | |||||
| ArrDate = datetime.strftime(self.CurrentEventYear.start_time, "%d %B %Y") | |||||
| DepDate = datetime.strftime(self.CurrentEventYear.end_time, "%d %B %Y") | |||||
| for oneday in myDayRange: | for oneday in myDayRange: | ||||
| if arrival: | if arrival: | ||||
| TmpDay = self.CurrentEventYear.end_time - timedelta(days=oneday) | TmpDay = self.CurrentEventYear.end_time - timedelta(days=oneday) | ||||
| elif departure: | elif departure: | ||||
| TmpDay = self.CurrentEventYear.start_time + timedelta(days=oneday) | 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").decode('utf-8') | |||||
| if arrival and ArrDate==DayString: | |||||
| 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"')) | TabResult.append((DayNum, DayName, 'selected="selected"')) | ||||
| elif departure and DepDate==DayString: | |||||
| elif departure and DepDate == DayString: | |||||
| TabResult.append((DayNum, DayName, 'selected="selected"')) | TabResult.append((DayNum, DayName, 'selected="selected"')) | ||||
| else: | else: | ||||
| TabResult.append((DayNum, DayName, "")) | TabResult.append((DayNum, DayName, "")) | ||||
| @@ -67,21 +69,21 @@ class Sejour_helpers(DummySejour): | |||||
| def PossibleTime(self, typedate="arrival"): | def PossibleTime(self, typedate="arrival"): | ||||
| ArrTime, DepTime = "10:00", "19:00" | ArrTime, DepTime = "10:00", "19:00" | ||||
| TabResult = list() | TabResult = 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") | |||||
| ArrTime = datetime.strftime(self.Sejour.arrival_time, "%H:%M") | |||||
| DepTime = 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) | StrTime = "%.2d:%.2d" % (hour, minutes) | ||||
| DispTime = "%dh%.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"') ) | |||||
| if typedate == "arrival" and StrTime == ArrTime: | |||||
| TabResult.append((StrTime, DispTime, 'selected="selected"')) | |||||
| elif typedate == "departure" and StrTime == DepTime: | |||||
| TabResult.append((StrTime, DispTime, 'selected="selected"')) | |||||
| else: | else: | ||||
| TabResult.append( (StrTime, DispTime, "") ) | |||||
| TabResult.append((StrTime, DispTime, "")) | |||||
| return TabResult | return TabResult | ||||
| def IsCheck(self, InputControl): | def IsCheck(self, InputControl): | ||||
| @@ -91,13 +93,13 @@ class Sejour_helpers(DummySejour): | |||||
| return "" | return "" | ||||
| if self.Sejour: | if self.Sejour: | ||||
| if InputControl.startswith('Arrival'): | if InputControl.startswith('Arrival'): | ||||
| CtrlVal = 2**ListControlB.index(InputControl[8:]) | |||||
| CtrlVal = 2 ** ListControlB.index(InputControl[8:]) | |||||
| if self.Sejour.arrival_check & CtrlVal == CtrlVal: | if self.Sejour.arrival_check & CtrlVal == CtrlVal: | ||||
| return "checked=\"checked\"" | return "checked=\"checked\"" | ||||
| else: | else: | ||||
| return "" | return "" | ||||
| elif InputControl.startswith('Departure'): | elif InputControl.startswith('Departure'): | ||||
| CtrlVal = 2**ListControlB.index(InputControl[10:]) | |||||
| CtrlVal = 2 ** ListControlB.index(InputControl[10:]) | |||||
| if self.Sejour.depart_check & CtrlVal == CtrlVal: | if self.Sejour.depart_check & CtrlVal == CtrlVal: | ||||
| return "checked=\"checked\"" | return "checked=\"checked\"" | ||||
| else: | else: | ||||
| @@ -107,6 +109,7 @@ class Sejour_helpers(DummySejour): | |||||
| else: | else: | ||||
| return "" | return "" | ||||
| class Orga_helpers(DummySejour): | class Orga_helpers(DummySejour): | ||||
| def __init__(self, event): | def __init__(self, event): | ||||
| @@ -129,10 +132,10 @@ class Orga_helpers(DummySejour): | |||||
| u"Faire du café et s'assurer de sa disponibilité.", | u"Faire du café et s'assurer de sa disponibilité.", | ||||
| u"Participer à la publication / au montage des vidéos des conférenciers.", | u"Participer à la publication / au montage des vidéos des conférenciers.", | ||||
| u"Autres" | u"Autres" | ||||
| ] | |||||
| ] | |||||
| def IsChecked(self, nb): | def IsChecked(self, nb): | ||||
| nb = 2**nb | |||||
| nb = 2 ** nb | |||||
| if self.Sejour and self.Sejour.orga_part: | if self.Sejour and self.Sejour.orga_part: | ||||
| if self.Sejour.orga_part & nb == nb: | if self.Sejour.orga_part & nb == nb: | ||||
| return "checked=\"checked\"" | return "checked=\"checked\"" | ||||
| @@ -140,12 +143,12 @@ class Orga_helpers(DummySejour): | |||||
| return "" | return "" | ||||
| else: | else: | ||||
| return "" | return "" | ||||
| def ChoosedList(self): | def ChoosedList(self): | ||||
| """ Return choice validated by user """ | """ Return choice validated by user """ | ||||
| ListOrga = [] | ListOrga = [] | ||||
| for num in range(0,len(self.Orga_tasks)): | |||||
| curs = 2**num | |||||
| for num in range(0, len(self.Orga_tasks)): | |||||
| curs = 2 ** num | |||||
| if self.Sejour.orga_part & curs == curs: | if self.Sejour.orga_part & curs == curs: | ||||
| ListOrga.append(self.Orga_tasks[num]) | ListOrga.append(self.Orga_tasks[num]) | ||||
| return ListOrga | |||||
| return ListOrga | |||||
| @@ -48,14 +48,14 @@ def pull_data(from_db, to_db, tables): | |||||
| destination, dengine = make_session(to_db) | destination, dengine = make_session(to_db) | ||||
| for table_name in tables: | for table_name in tables: | ||||
| print 'Processing', table_name | |||||
| print 'Pulling schema from source server' | |||||
| print('Processing', table_name) | |||||
| print('Pulling schema from source server') | |||||
| table = Table(table_name, smeta, autoload=True) | table = Table(table_name, smeta, autoload=True) | ||||
| print 'Creating table on destination server' | |||||
| print('Creating table on destination server') | |||||
| table.metadata.create_all(dengine) | table.metadata.create_all(dengine) | ||||
| NewRecord = quick_mapper(table) | NewRecord = quick_mapper(table) | ||||
| columns = table.columns.keys() | columns = table.columns.keys() | ||||
| print 'Transferring records' | |||||
| print('Transferring records') | |||||
| for record in source.query(table).all(): | for record in source.query(table).all(): | ||||
| data = dict( | data = dict( | ||||
| [(str(column), getattr(record, column)) for column in columns] | [(str(column), getattr(record, column)) for column in columns] | ||||
| @@ -69,20 +69,20 @@ def pull_data(from_db, to_db, tables): | |||||
| try: | try: | ||||
| destination.merge(NewRecord(**data)) | destination.merge(NewRecord(**data)) | ||||
| except: | except: | ||||
| print data | |||||
| print(data) | |||||
| pass | pass | ||||
| print 'Committing changes' | |||||
| print('Committing changes') | |||||
| destination.commit() | destination.commit() | ||||
| def main(argv=sys.argv): | def main(argv=sys.argv): | ||||
| connection_string = "sqlite:////home/tr4ck3ur/Dev/jm2l/JM2L.sqlite" | |||||
| connection_string = "sqlite:////home/tr4ck3ur/git_repository/jm2l/JM2L.sqlite" | |||||
| engine = create_engine(connection_string, echo=False, convert_unicode=True) | engine = create_engine(connection_string, echo=False, convert_unicode=True) | ||||
| DBSession.configure(bind=engine) | DBSession.configure(bind=engine) | ||||
| Users = DBSession.query(User) | Users = DBSession.query(User) | ||||
| ListUser = filter(lambda x: x.is_Intervenant, Users) | ListUser = filter(lambda x: x.is_Intervenant, Users) | ||||
| for i in ListUser: | for i in ListUser: | ||||
| print i.mail | |||||
| print(i.mail) | |||||
| def main4(argv=sys.argv): | def main4(argv=sys.argv): | ||||
| import csv | import csv | ||||
| @@ -116,7 +116,7 @@ def main4(argv=sys.argv): | |||||
| u.wifi_user = w_user | u.wifi_user = w_user | ||||
| u.wifi_pass = w_pass | u.wifi_pass = w_pass | ||||
| DBSession.merge(u) | DBSession.merge(u) | ||||
| print row, u | |||||
| print(row, u) | |||||
| finally: | finally: | ||||
| f.close() | f.close() | ||||
| @@ -130,7 +130,7 @@ def main_3(argv=sys.argv): | |||||
| connection_string = "sqlite:////home/tr4ck3ur/Dev/jm2l/JM2L.sqlite" | connection_string = "sqlite:////home/tr4ck3ur/Dev/jm2l/JM2L.sqlite" | ||||
| engine = create_engine(connection_string, echo=True, convert_unicode=True) | engine = create_engine(connection_string, echo=True, convert_unicode=True) | ||||
| DBSession.configure(bind=engine) | DBSession.configure(bind=engine) | ||||
| p0, p1 = orm.aliased(User,name="p0"), orm.aliased(User ,name="p1") | |||||
| p0, p1 = orm.aliased(User, name="p0"), orm.aliased(User , name="p1") | |||||
| import pprint | import pprint | ||||
| ## permtation | ## permtation | ||||
| @@ -141,7 +141,7 @@ def main_3(argv=sys.argv): | |||||
| .filter(p0.last_logged<p1.last_logged)\ | .filter(p0.last_logged<p1.last_logged)\ | ||||
| .with_entities(p0.slug,p0.uid,p1.uid).all() | .with_entities(p0.slug,p0.uid,p1.uid).all() | ||||
| for slug, idsrc, iddst in Datas: | for slug, idsrc, iddst in Datas: | ||||
| print slug | |||||
| print(slug) | |||||
| # Events | # Events | ||||
| Events = DBSession.query(User_Event)\ | Events = DBSession.query(User_Event)\ | ||||
| .filter(User_Event.user_uid==idsrc) | .filter(User_Event.user_uid==idsrc) | ||||
| @@ -238,5 +238,4 @@ def Initialize(): | |||||
| u.password = password | u.password = password | ||||
| u.Staff = 0 | u.Staff = 0 | ||||
| DBSession.merge(u) | DBSession.merge(u) | ||||
| print u.nom, u.prenom, u.Staff | |||||
| print(u.nom, u.prenom, u.Staff) | |||||
| @@ -58,7 +58,7 @@ | |||||
| % if reason: | % if reason: | ||||
| <p>${reason}</p> | <p>${reason}</p> | ||||
| % else: | % else: | ||||
| <p>Vous n'êtes pas authentifié, ou n'avez pas les authorisations nécessaires.</p> | |||||
| <p>Vous n'êtes pas authentifié, ou n'avez pas les authorisations nécessaires.</p> | |||||
| % endif | % endif | ||||
| </body> | </body> | ||||
| </html> | </html> | ||||
| @@ -54,7 +54,7 @@ | |||||
| </head> | </head> | ||||
| <body> | <body> | ||||
| <img src="/img/error404.png" width="200px" /> | <img src="/img/error404.png" width="200px" /> | ||||
| <h1>Page non trouvée</h1> | |||||
| <h1>Page non trouvée</h1> | |||||
| % if reason: | % if reason: | ||||
| <p>${reason}</p> | <p>${reason}</p> | ||||
| % else: | % else: | ||||
| @@ -10,7 +10,7 @@ | |||||
| </thead> | </thead> | ||||
| <tbody> | <tbody> | ||||
| <tr> | <tr> | ||||
| <td>Conférences</td> <td style="text-align:center"> | |||||
| <td>Conférences</td> <td style="text-align:center"> | |||||
| % if len( request.user.year_events('Conference') ): | % if len( request.user.year_events('Conference') ): | ||||
| % for evt in request.user.year_events('Conference'): | % for evt in request.user.year_events('Conference'): | ||||
| % endfor | % endfor | ||||
| @@ -106,11 +106,11 @@ elif Type=='T': | |||||
| %> | %> | ||||
| % if Type!='O': | % if Type!='O': | ||||
| <fieldset> | <fieldset> | ||||
| <legend class="lowshadow">Vos ${CurTitles} programmés pour ${CurrentYear}</legend> | |||||
| <legend class="lowshadow">Vos ${CurTitles} programmés pour ${CurrentYear}</legend> | |||||
| <% | <% | ||||
| Selection = filter(lambda x:(x.event_type==CurEventType and x.for_year==CurrentYear), uprofil.events) | |||||
| Selection = list(filter(lambda x:(x.event_type==CurEventType and x.for_year==CurrentYear), uprofil.events)) | |||||
| HeadHistTitle = u"L'historique de vos %s ( %d ) " % ( CurTitles, len(Selection) ) | HeadHistTitle = u"L'historique de vos %s ( %d ) " % ( CurTitles, len(Selection) ) | ||||
| NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent | |||||
| NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent | |||||
| %> | %> | ||||
| ${helpers.show_Interventions(Selection, "Sujet", NothingTitle )} | ${helpers.show_Interventions(Selection, "Sujet", NothingTitle )} | ||||
| </fieldset> | </fieldset> | ||||
| @@ -118,21 +118,21 @@ NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent | |||||
| % if Type=='C': | % if Type=='C': | ||||
| <p> | <p> | ||||
| <strong>Proposer une conférence / un lighting talk</strong><br/> | |||||
| <strong>Proposer une conférence / un lighting talk</strong><br/> | |||||
| <ul> | <ul> | ||||
| <li>Si vous avez une expérience particulière avec les logiciels libres | |||||
| <li>Si vous avez une expérience particulière avec les logiciels libres | |||||
| que vous souhaitez partager.</li> | que vous souhaitez partager.</li> | ||||
| <li>Si vous êtes acteur d’un des sujets actuels qui menacent ou qui | <li>Si vous êtes acteur d’un des sujets actuels qui menacent ou qui | ||||
| promeuvent le logiciel libre.</li> | promeuvent le logiciel libre.</li> | ||||
| <li>Si vous voulez présenter un logiciel libre dont vous êtes l’auteur.</li> | |||||
| <li>Si vous voulez présenter un logiciel libre dont vous êtes l’auteur.</li> | |||||
| </ul> | </ul> | ||||
| Nous serons heureux de vous écouter. | |||||
| Nous serons heureux de vous écouter. | |||||
| <br> | <br> | ||||
| Nous souhaitons proposer des conférences pour un public débutant | |||||
| Nous souhaitons proposer des conférences pour un public débutant | |||||
| autant que pour des visiteurs avertis. Les sujets ne doivent pas | autant que pour des visiteurs avertis. Les sujets ne doivent pas | ||||
| forcément être techniques, mais aussi d’ordre général avec la seule | |||||
| forcément être techniques, mais aussi d’ordre général avec la seule | |||||
| contrainte de traiter de près ou de loin des logiciels libres, de la | contrainte de traiter de près ou de loin des logiciels libres, de la | ||||
| communauté ou de vos propres expériences d’utilisateur quotidien. <br> | |||||
| communauté ou de vos propres expériences d’utilisateur quotidien. <br> | |||||
| Le but de ces conférences est double : | Le but de ces conférences est double : | ||||
| <ul> | <ul> | ||||
| <li>donner confiance aux futurs utilisateurs de logiciels libres</li> | <li>donner confiance aux futurs utilisateurs de logiciels libres</li> | ||||
| @@ -205,7 +205,7 @@ NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent | |||||
| <fieldset> | <fieldset> | ||||
| <legend class="lowshadow">Historique</legend> | <legend class="lowshadow">Historique</legend> | ||||
| <% | <% | ||||
| Selection = filter(lambda x:(x.event_type==CurEventType and x.for_year!=CurrentYear), uprofil.events) | |||||
| Selection = list(filter(lambda x:(x.event_type==CurEventType and x.for_year!=CurrentYear), uprofil.events)) | |||||
| HeadHistTitle = u"L'historique de vos %s ( %d ) " % ( CurTitles, len(Selection) ) | HeadHistTitle = u"L'historique de vos %s ( %d ) " % ( CurTitles, len(Selection) ) | ||||
| NothingTitle = u"Désolé, Il n'y a rien dans l'historique vous concernant." | NothingTitle = u"Désolé, Il n'y a rien dans l'historique vous concernant." | ||||
| %> | %> | ||||
| @@ -30,7 +30,7 @@ | |||||
| </tbody> | </tbody> | ||||
| </table> | </table> | ||||
| <div class="center"> | <div class="center"> | ||||
| Pour un co-voiturage le <u>${Exch.start_time.strftime("%a %d %b").decode('utf-8')}</u> | |||||
| Pour un co-voiturage le <u>${Exch.start_time.strftime("%a %d %b")}</u> | |||||
| vers <strong>${Exch.start_time.strftime("%H:%M")}</strong> | vers <strong>${Exch.start_time.strftime("%H:%M")}</strong> | ||||
| </div> | </div> | ||||
| Temps de voyage estimé à <span id="summary"></span> | Temps de voyage estimé à <span id="summary"></span> | ||||
| @@ -12,7 +12,7 @@ | |||||
| <dd>Un hébergement</dd> | <dd>Un hébergement</dd> | ||||
| % endif | % endif | ||||
| <dt>Quand </dt> | <dt>Quand </dt> | ||||
| <dd>La nuit du ${Exch.start_time.strftime('%A %d %b %Y').decode('utf-8')} jusqu'au lendemain</dd> | |||||
| <dd>La nuit du ${Exch.start_time.strftime('%A %d %b %Y')} jusqu'au lendemain</dd> | |||||
| % if Exch.description: | % if Exch.description: | ||||
| <dt>Détails </dt> | <dt>Détails </dt> | ||||
| <dd>${Exch.description}</dd> | <dd>${Exch.description}</dd> | ||||
| @@ -8,8 +8,8 @@ | |||||
| <dt>Catégorie</dt> | <dt>Catégorie</dt> | ||||
| <dd>${Exch.Category.exch_subtype}</dd> | <dd>${Exch.Category.exch_subtype}</dd> | ||||
| <dt>Quand </dt> | <dt>Quand </dt> | ||||
| <dd>de ${Exch.start_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${Exch.start_time.strftime('%Hh%M')} | |||||
| à ${Exch.end_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${Exch.end_time.strftime('%Hh%M')} | |||||
| <dd>de ${Exch.start_time.strftime('%A %d %b %Y')} vers ${Exch.start_time.strftime('%Hh%M')} | |||||
| à ${Exch.end_time.strftime('%A %d %b %Y')} vers ${Exch.end_time.strftime('%Hh%M')} | |||||
| </dd> | </dd> | ||||
| <dt>Détails </dt> | <dt>Détails </dt> | ||||
| <dd>${Exch.description}</dd> | <dd>${Exch.description}</dd> | ||||
| @@ -8,11 +8,11 @@ DicExch = Exchanges.get_overview( request.user.uid ) | |||||
| <div class="tabbable tabs-left" id="Intendance_tab"> | <div class="tabbable tabs-left" id="Intendance_tab"> | ||||
| <ul class="nav nav-tabs navbar" style="margin-bottom:0;background-color: #f7f7f7;"> | <ul class="nav nav-tabs navbar" style="margin-bottom:0;background-color: #f7f7f7;"> | ||||
| <li class="active"> <a href="#ResumeInt" data-toggle="tab">Resumé</a> </li> | |||||
| <li class="active"> <a href="#ResumeInt" data-toggle="tab">Resumé</a> </li> | |||||
| <li> <a href="#Miam" data-toggle="tab"><span style="font-size:1.8em;">🍽</span> Miam</a> </li> | <li> <a href="#Miam" data-toggle="tab"><span style="font-size:1.8em;">🍽</span> Miam</a> </li> | ||||
| <li> <a href="#Covoiturage" data-toggle="tab"><span style="font-size:1.8em;">🚘</span> Covoiturage</a> </li> | <li> <a href="#Covoiturage" data-toggle="tab"><span style="font-size:1.8em;">🚘</span> Covoiturage</a> </li> | ||||
| <li> <a href="#Hebergement" data-toggle="tab"><span style="font-size:1.8em;">🏚</span> Hébergement</a> </li> | |||||
| <li> <a href="#Materiel" data-toggle="tab"><span style="font-size:1.8em;">🛒</span> Matériel</a> </li> | |||||
| <li> <a href="#Hebergement" data-toggle="tab"><span style="font-size:1.8em;">🏚</span> Hébergement</a> </li> | |||||
| <li> <a href="#Materiel" data-toggle="tab"><span style="font-size:1.8em;">🛒</span> Matériel</a> </li> | |||||
| </ul> | </ul> | ||||
| <div class="tab-content"> | <div class="tab-content"> | ||||
| @@ -30,7 +30,7 @@ DicExch = Exchanges.get_overview( request.user.uid ) | |||||
| ${tables.DoTable(Type, 'Ask', DicExch)} | ${tables.DoTable(Type, 'Ask', DicExch)} | ||||
| ${tables.DoTable(Type, 'Proposal', DicExch)} | ${tables.DoTable(Type, 'Proposal', DicExch)} | ||||
| <fieldset> | <fieldset> | ||||
| <legend>Tous les échanges</legend> | |||||
| <legend>Tous les échanges</legend> | |||||
| ${Missing(Type, DicExch['Missing'])} | ${Missing(Type, DicExch['Missing'])} | ||||
| </fieldset> | </fieldset> | ||||
| </%def> | </%def> | ||||
| @@ -59,23 +59,23 @@ DicForm = { | |||||
| </td> | </td> | ||||
| <td> | <td> | ||||
| <p> | <p> | ||||
| Complétez dès à présent votre partie repas afin que l'on puisse faire les réservations nécessaires ! | |||||
| Complétez dès à présent votre partie repas afin que l'on puisse faire les réservations nécessaires ! | |||||
| </p> | </p> | ||||
| <u>Vendredi soir :</u> | <u>Vendredi soir :</u> | ||||
| <p> | <p> | ||||
| Certains conférenciers viennent de très loin et seront présent dés le vendredi.<br /> | |||||
| Nous vous proposons de nous retrouver à proximité, à la CASA.<br /> | |||||
| Certains conférenciers viennent de très loin et seront présent dés le vendredi.<br /> | |||||
| Nous vous proposons de nous retrouver à proximité, à la CASA.<br /> | |||||
| <a href="http://groupelacasa.com/la-carte-et-les-menus-1-2-75"> La carte CASA </a> | <a href="http://groupelacasa.com/la-carte-et-les-menus-1-2-75"> La carte CASA </a> | ||||
| le vendredi soir autour d'un verre et d'un bon repas ! | le vendredi soir autour d'un verre et d'un bon repas ! | ||||
| </p> | </p> | ||||
| <u>Samedi Midi :</u> | <u>Samedi Midi :</u> | ||||
| <p> | <p> | ||||
| À la pause du midi, nous vous proposons un repas avec le food-truck 'les frères toqués' qui sera présent sur le parking de PolyTech<br /> | |||||
| À la pause du midi, nous vous proposons un repas avec le food-truck 'les frères toqués' qui sera présent sur le parking de PolyTech<br /> | |||||
| </p> | </p> | ||||
| <u>Samedi Soir :</u> | <u>Samedi Soir :</u> | ||||
| <p> | <p> | ||||
| Pour conclure la journée nous avons l'habitude de nous retrouver au repas de cloture.<br /> | |||||
| Pour conclure la journée nous avons l'habitude de nous retrouver au repas de cloture.<br /> | |||||
| Nous vous proposons de nous retrouver à Antibes au restaurant Les Tonnelles<br /> | Nous vous proposons de nous retrouver à Antibes au restaurant Les Tonnelles<br /> | ||||
| <a href="https://fr-fr.facebook.com/lestonnellesantibes/?_fb_noscript=1"> Les Tonnelles </a> | <a href="https://fr-fr.facebook.com/lestonnellesantibes/?_fb_noscript=1"> Les Tonnelles </a> | ||||
| </p> | </p> | ||||
| @@ -100,7 +100,7 @@ elif Type=='M': | |||||
| <thead> | <thead> | ||||
| <tr> | <tr> | ||||
| <th colspan="5"> | <th colspan="5"> | ||||
| Les échanges ${CurTitle} | |||||
| Les échanges ${CurTitle} | |||||
| % if 0: | % if 0: | ||||
| <span style="float:right;"> | <span style="float:right;"> | ||||
| <a data-original-title="Afficher les demandes" data-toggle="tooltip" id="${Type}_Demande"> | <a data-original-title="Afficher les demandes" data-toggle="tooltip" id="${Type}_Demande"> | ||||
| @@ -124,7 +124,7 @@ elif Type=='M': | |||||
| <tr> | <tr> | ||||
| <th style="width:1em;"></th> | <th style="width:1em;"></th> | ||||
| <th>Détails</th> | |||||
| <th>Détails</th> | |||||
| <th style="width:1em;"></th> | <th style="width:1em;"></th> | ||||
| <tr> | <tr> | ||||
| </thead> | </thead> | ||||
| @@ -132,7 +132,7 @@ elif Type=='M': | |||||
| % if len(Selection)==0: | % if len(Selection)==0: | ||||
| <tr> | <tr> | ||||
| <td colspan="5" style="text-align:center;"> | <td colspan="5" style="text-align:center;"> | ||||
| <i>Il n'y a aucun échange ${CurTitle} proposé actuellement...</i> | |||||
| <i>Il n'y a aucun échange ${CurTitle} proposé actuellement...</i> | |||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| % else: | % else: | ||||
| @@ -155,7 +155,7 @@ elif Type=='M': | |||||
| <a href="/user/${item.provider.slug}"> ${item.provider.prenom} ${item.provider.nom} </a> offre | <a href="/user/${item.provider.slug}"> ${item.provider.prenom} ${item.provider.nom} </a> offre | ||||
| % endif | % endif | ||||
| % if item.exch_type=="C": | % if item.exch_type=="C": | ||||
| un co-voiturage le ${item.start_time.strftime('%a %d %b vers %Hh%M').decode('utf-8')} | |||||
| un co-voiturage le ${item.start_time.strftime('%a %d %b vers %Hh%M')} | |||||
| de <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.start.place_id}')">${item.Itin.start.display_name}</a> | de <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.start.place_id}')">${item.Itin.start.display_name}</a> | ||||
| à <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.arrival.place_id}')">${item.Itin.arrival.display_name}</a> | à <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.arrival.place_id}')">${item.Itin.arrival.display_name}</a> | ||||
| % elif item.exch_type=="M": | % elif item.exch_type=="M": | ||||
| @@ -165,8 +165,8 @@ elif Type=='M': | |||||
| % if item.description: | % if item.description: | ||||
| ${item.description[:30]} | ${item.description[:30]} | ||||
| % endif | % endif | ||||
| de ${item.start_time.strftime('%a %d %b %Hh%M').decode('utf-8')} | |||||
| à ${item.end_time.strftime('%a %d %b %Hh%M').decode('utf-8')} | |||||
| de ${item.start_time.strftime('%a %d %b %Hh%M')} | |||||
| à ${item.end_time.strftime('%a %d %b %Hh%M')} | |||||
| % else: | % else: | ||||
| % if item.Category: | % if item.Category: | ||||
| <i>${item.Category.exch_subtype}</i> | <i>${item.Category.exch_subtype}</i> | ||||
| @@ -174,7 +174,7 @@ elif Type=='M': | |||||
| % if item.description: | % if item.description: | ||||
| ${item.description[:30]} | ${item.description[:30]} | ||||
| % endif | % endif | ||||
| ${item.start_time.strftime('%a %d %b').decode('utf-8')} soir | |||||
| ${item.start_time.strftime('%a %d %b')} soir | |||||
| % endif | % endif | ||||
| </p> | </p> | ||||
| </td> | </td> | ||||
| @@ -284,7 +284,7 @@ ListWrap = ["Co-voiturage",u"Hébergement","Matos"] | |||||
| </div> | </div> | ||||
| <div class="accordion-group"> | <div class="accordion-group"> | ||||
| <div class="accordion-heading"> | <div class="accordion-heading"> | ||||
| <a class="accordion-toggle" data-toggle="collapse" data-parent="#AccordionCounter" href="#collapseAll">Les compteurs de l´événement</a> | |||||
| <a class="accordion-toggle" data-toggle="collapse" data-parent="#AccordionCounter" href="#collapseAll">Les compteurs de l´événement</a> | |||||
| </div> | </div> | ||||
| <div id="collapseAll" class="accordion-body collapse"> | <div id="collapseAll" class="accordion-body collapse"> | ||||
| <div class="accordion-inner"> | <div class="accordion-inner"> | ||||
| @@ -97,17 +97,17 @@ elif Type=='M': | |||||
| </td> | </td> | ||||
| <td> | <td> | ||||
| %if Type=='C': | %if Type=='C': | ||||
| ${item.start_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${item.start_time.strftime('%Hh%M')} | |||||
| ${item.start_time.strftime('%A %d %b %Y')} vers ${item.start_time.strftime('%Hh%M')} | |||||
| de <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.start.place_id}')">${item.Itin.start.display_name}</a> | de <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.start.place_id}')">${item.Itin.start.display_name}</a> | ||||
| à <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.arrival.place_id}')">${item.Itin.arrival.display_name}</a> | à <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.arrival.place_id}')">${item.Itin.arrival.display_name}</a> | ||||
| %elif Type=='H': | %elif Type=='H': | ||||
| % if item.Category: | % if item.Category: | ||||
| <i>${item.Category.exch_subtype}</i>, | <i>${item.Category.exch_subtype}</i>, | ||||
| % endif | % endif | ||||
| La nuit du ${item.start_time.strftime('%A %d %b %Y').decode('utf-8')}<br> | |||||
| La nuit du ${item.start_time.strftime('%A %d %b %Y')}<br> | |||||
| %elif Type=='M': | %elif Type=='M': | ||||
| de ${item.start_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${item.start_time.strftime('%Hh%M')} | |||||
| à ${item.end_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${item.end_time.strftime('%Hh%M')}<br> | |||||
| de ${item.start_time.strftime('%A %d %b %Y')} vers ${item.start_time.strftime('%Hh%M')} | |||||
| à ${item.end_time.strftime('%A %d %b %Y')} vers ${item.end_time.strftime('%Hh%M')}<br> | |||||
| ${item.Category.exch_subtype} | ${item.Category.exch_subtype} | ||||
| %endif | %endif | ||||
| %if item.description: | %if item.description: | ||||
| @@ -23,12 +23,12 @@ | |||||
| <% | <% | ||||
| DicFormA = { | DicFormA = { | ||||
| 'nom': {'PlaceHolder':u"Mon Nom", 'ContainerClass':"span6", 'next':False}, | 'nom': {'PlaceHolder':u"Mon Nom", 'ContainerClass':"span6", 'next':False}, | ||||
| 'prenom': {'PlaceHolder':u"Mon Prénom", 'ContainerClass':"span6", 'next':True}, | |||||
| 'prenom': {'PlaceHolder':u"Mon Prénom", 'ContainerClass':"span6", 'next':True}, | |||||
| 'pseudo': {'PlaceHolder':u"Mon Pseudo", 'ContainerClass':"span6", 'next':False}, | 'pseudo': {'PlaceHolder':u"Mon Pseudo", 'ContainerClass':"span6", 'next':False}, | ||||
| 'mail': {'PlaceHolder':u"mon.mail@fqdn.tld", 'ContainerClass':"span6", 'next':True}, | 'mail': {'PlaceHolder':u"mon.mail@fqdn.tld", 'ContainerClass':"span6", 'next':True}, | ||||
| 'phone': {'PlaceHolder':u"0612345678", 'ContainerClass':"span6", 'next':False}, | 'phone': {'PlaceHolder':u"0612345678", 'ContainerClass':"span6", 'next':False}, | ||||
| 'website': {'PlaceHolder':u"http://ma-page-web.moi",'ContainerClass':"span6", 'next':True}, | 'website': {'PlaceHolder':u"http://ma-page-web.moi",'ContainerClass':"span6", 'next':True}, | ||||
| 'gpg_key': {'PlaceHolder':u"Ma clé gpg", 'ContainerClass':"span6", 'next':False}, | |||||
| 'gpg_key': {'PlaceHolder':u"Ma clé gpg", 'ContainerClass':"span6", 'next':False}, | |||||
| 'soc_link':{'PlaceHolder':u"#jm2l sur irc.freenode.org",'ContainerClass':"span6", 'next':True}, | 'soc_link':{'PlaceHolder':u"#jm2l sur irc.freenode.org",'ContainerClass':"span6", 'next':True}, | ||||
| 'bio': {'Ignore':True}, | 'bio': {'Ignore':True}, | ||||
| 'tiersship': {'Ignore':True}, | 'tiersship': {'Ignore':True}, | ||||
| @@ -52,12 +52,12 @@ DicFormB = { | |||||
| DicForm2 = { | DicForm2 = { | ||||
| 'nom': {'PlaceHolder':u"Mon Nom", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"}, | 'nom': {'PlaceHolder':u"Mon Nom", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"}, | ||||
| 'prenom': {'PlaceHolder':u"Mon Prénom", "FieldStyle":"width:16em;"}, | |||||
| 'prenom': {'PlaceHolder':u"Mon Prénom", "FieldStyle":"width:16em;"}, | |||||
| 'pseudo': {'PlaceHolder':u"Mon Pseudo", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"}, | 'pseudo': {'PlaceHolder':u"Mon Pseudo", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"}, | ||||
| 'mail': {'PlaceHolder':u"mon.mail@fqdn.tld", "FieldStyle":"width:16em;"}, | 'mail': {'PlaceHolder':u"mon.mail@fqdn.tld", "FieldStyle":"width:16em;"}, | ||||
| 'phone': {'PlaceHolder':u"0612345678", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"}, | 'phone': {'PlaceHolder':u"0612345678", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"}, | ||||
| 'website': {'PlaceHolder':u"http://ma-page-web.moi","FieldStyle":"width:16em;"}, | 'website': {'PlaceHolder':u"http://ma-page-web.moi","FieldStyle":"width:16em;"}, | ||||
| 'gpg_key': {'PlaceHolder':u"Ma clé gpg", "FieldStyle":"width:90%;"}, | |||||
| 'gpg_key': {'PlaceHolder':u"Ma clé gpg", "FieldStyle":"width:90%;"}, | |||||
| 'soc_link':{'PlaceHolder':u"#jm2l sur irc.freenode.org","FieldStyle":"width:90%;"}, | 'soc_link':{'PlaceHolder':u"#jm2l sur irc.freenode.org","FieldStyle":"width:90%;"}, | ||||
| 'bio': {'PlaceHolder':u"Ma Bilibiographie", "FieldStyle":"width:95%;min-height:150px;", "fieldset":True, "ckeditor":1 }, | 'bio': {'PlaceHolder':u"Ma Bilibiographie", "FieldStyle":"width:95%;min-height:150px;", "fieldset":True, "ckeditor":1 }, | ||||
| 'tiersship': {'Ignore':True} | 'tiersship': {'Ignore':True} | ||||
| @@ -14,14 +14,14 @@ fieldset:disabled { | |||||
| % else: | % else: | ||||
| <legend class="lowshadow"> | <legend class="lowshadow"> | ||||
| <img style="max-height:50px;" src="/img/warn.png" alt="Attention !"> | <img style="max-height:50px;" src="/img/warn.png" alt="Attention !"> | ||||
| Vous n'avez pas confirmé votre venue aux JM2L ${CurrentYear} | |||||
| Vous n'avez pas confirmé votre venue aux JM2L ${CurrentYear} | |||||
| </legend> | </legend> | ||||
| <h4 class="lowshadow">Complétez et validez vite ce formulaire !</h4> | |||||
| <h4 class="lowshadow">Complétez et validez vite ce formulaire !</h4> | |||||
| % endif | % endif | ||||
| <form id="ProfilForm" action="/MonSejour" method="POST"> | <form id="ProfilForm" action="/MonSejour" method="POST"> | ||||
| <fieldset class="ComeToJM2L"> | <fieldset class="ComeToJM2L"> | ||||
| <legend>Arrivée</legend> | |||||
| <legend>Arrivée</legend> | |||||
| <div class="form-inline"> | <div class="form-inline"> | ||||
| J'arrive | J'arrive | ||||
| <select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu"> | <select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu"> | ||||
| @@ -63,16 +63,16 @@ fieldset:disabled { | |||||
| <ul style="list-style-type: none;"> | <ul style="list-style-type: none;"> | ||||
| <li><label class="checkbox"> | <li><label class="checkbox"> | ||||
| <input id="PMR" ${mytrip.IsCheck("Arrival:PMR")|n} name="Arrival:PMR" title="Assistance Personne à mobilité réduite (PMR)" type="checkbox"> | |||||
| d'assistance : Personne à mobilité réduite (PMR)</input></label> | |||||
| <input id="PMR" ${mytrip.IsCheck("Arrival:PMR")|n} name="Arrival:PMR" title="Assistance Personne à mobilité réduite (PMR)" type="checkbox"> | |||||
| d'assistance : Personne à mobilité réduite (PMR)</input></label> | |||||
| </li> | </li> | ||||
| <li><label class="checkbox"> | <li><label class="checkbox"> | ||||
| <input id="Cov" ${mytrip.IsCheck("Arrival:Cov")|n} name="Arrival:Cov" title="Covoiturage" type="checkbox"> | <input id="Cov" ${mytrip.IsCheck("Arrival:Cov")|n} name="Arrival:Cov" title="Covoiturage" type="checkbox"> | ||||
| d'un covoiturage, d'un hébergement...<br>(j'ai rempli/je vais remplir la section Logistique).</input></label> | |||||
| d'un covoiturage, d'un hébergement...<br>(j'ai rempli/je vais remplir la section Logistique).</input></label> | |||||
| </li> | </li> | ||||
| <li><label class="checkbox"> | <li><label class="checkbox"> | ||||
| <input id="Bras" ${mytrip.IsCheck("Arrival:Bras")|n} name="Arrival:Bras" title="Bras" type="checkbox"> | <input id="Bras" ${mytrip.IsCheck("Arrival:Bras")|n} name="Arrival:Bras" title="Bras" type="checkbox"> | ||||
| de bras, car je rapporte plein de matériel. <br>(Je transporte ma maison, mon garage ...)</input></label> | |||||
| de bras, car je rapporte plein de matériel. <br>(Je transporte ma maison, mon garage ...)</input></label> | |||||
| </li> | </li> | ||||
| <li> | <li> | ||||
| <div class="form-inline"> | <div class="form-inline"> | ||||
| @@ -81,7 +81,7 @@ fieldset:disabled { | |||||
| Autres | Autres | ||||
| </input></label> | </input></label> | ||||
| <input type="text" style="width:20em;" name="Arrival:Comment" | <input type="text" style="width:20em;" name="Arrival:Comment" | ||||
| placeholder="Précisions à propos de mon arrivée…" /> | |||||
| placeholder="Précisions à propos de mon arrivée…" /> | |||||
| </div> | </div> | ||||
| </li> | </li> | ||||
| </ul> | </ul> | ||||
| @@ -90,7 +90,7 @@ fieldset:disabled { | |||||
| </fieldset> | </fieldset> | ||||
| <fieldset class="ComeToJM2L"> | <fieldset class="ComeToJM2L"> | ||||
| <legend>Départ</legend> | |||||
| <legend>Départ</legend> | |||||
| <div class="form-inline"> | <div class="form-inline"> | ||||
| Je repars | Je repars | ||||
| <select style="width:12em;" id="Departure:Place" class="formforform-field" name="Departure:Place" title="Alors, j'arrive"> | <select style="width:12em;" id="Departure:Place" class="formforform-field" name="Departure:Place" title="Alors, j'arrive"> | ||||
| @@ -130,8 +130,8 @@ fieldset:disabled { | |||||
| Je vais avoir besoin: <small style="color: #aaa;">(Cochez les cases correspondantes)</small> | Je vais avoir besoin: <small style="color: #aaa;">(Cochez les cases correspondantes)</small> | ||||
| <ul style="list-style-type: none;"> | <ul style="list-style-type: none;"> | ||||
| <li><label class="checkbox"> | <li><label class="checkbox"> | ||||
| <input id="PMR" ${mytrip.IsCheck("Departure:PMR")|n} name="Departure:PMR" title="d'Assistance : Personne à mobilité réduite (PMR)" type="checkbox"> | |||||
| d'assistance : Personne à mobilité réduite (PMR)</input> | |||||
| <input id="PMR" ${mytrip.IsCheck("Departure:PMR")|n} name="Departure:PMR" title="d'Assistance : Personne à mobilité réduite (PMR)" type="checkbox"> | |||||
| d'assistance : Personne à mobilité réduite (PMR)</input> | |||||
| </label> | </label> | ||||
| </li> | </li> | ||||
| <li><label class="checkbox"> | <li><label class="checkbox"> | ||||
| @@ -141,7 +141,7 @@ fieldset:disabled { | |||||
| </li> | </li> | ||||
| <li><label class="checkbox"> | <li><label class="checkbox"> | ||||
| <input id="Bras" ${mytrip.IsCheck("Departure:Bras")|n} name="Departure:Bras" title="de bras" type="checkbox"> | <input id="Bras" ${mytrip.IsCheck("Departure:Bras")|n} name="Departure:Bras" title="de bras" type="checkbox"> | ||||
| de bras, car j'ai en stock plein de matériel (Ma maison).</input> | |||||
| de bras, car j'ai en stock plein de matériel (Ma maison).</input> | |||||
| </label> | </label> | ||||
| </li> | </li> | ||||
| <li> | <li> | ||||
| @@ -151,7 +151,7 @@ fieldset:disabled { | |||||
| Autres | Autres | ||||
| </input></label> | </input></label> | ||||
| <input type="text" style="width:20em;" name="Departure:Comment" | <input type="text" style="width:20em;" name="Departure:Comment" | ||||
| placeholder="Précisions à propos de mon départ…" /> | |||||
| placeholder="Précisions à propos de mon départ…" /> | |||||
| </div> | </div> | ||||
| </li> | </li> | ||||
| </ul> | </ul> | ||||
| @@ -111,7 +111,7 @@ if Counter==0: | |||||
| vid = event.video.first() | vid = event.video.first() | ||||
| pres = event.presentation.first() | pres = event.presentation.first() | ||||
| %> | %> | ||||
| ${event.start_time.strftime("%a %d %b").decode('utf-8')}<br> | |||||
| ${event.start_time.strftime("%a %d %b")}<br> | |||||
| ${event.start_time.strftime("%H:%M")} - ${event.end_time.strftime("%H:%M")} | ${event.start_time.strftime("%H:%M")} - ${event.end_time.strftime("%H:%M")} | ||||
| </td> | </td> | ||||
| <td style="position: relative;"> | <td style="position: relative;"> | ||||
| @@ -24,7 +24,7 @@ from slugify import slugify | |||||
| % if len(DicSallePhy)==0: | % if len(DicSallePhy)==0: | ||||
| <tr> | <tr> | ||||
| <td style="text-align:center;"> | <td style="text-align:center;"> | ||||
| <i>Il n'y a pas de salle définie pour le moment.</i> | |||||
| <i>Il n'y a pas de salle définie pour le moment.</i> | |||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| % endif | % endif | ||||
| @@ -43,7 +43,7 @@ from slugify import slugify | |||||
| % if SallePhy.uid: | % if SallePhy.uid: | ||||
| [ ${SallePhy.nb_places} places ] | [ ${SallePhy.nb_places} places ] | ||||
| % else: | % else: | ||||
| [ <a href="/PhySalles">Créer</a> ] | |||||
| [ <a href="/PhySalles">Créer</a> ] | |||||
| % endif | % endif | ||||
| </div> | </div> | ||||
| @@ -29,9 +29,9 @@ | |||||
| %endif | %endif | ||||
| <% | <% | ||||
| DicForm = { | DicForm = { | ||||
| 'year_uid': {'PlaceHolder':u"Année", "FieldStyle":"width:7em;", "ContainerStyle":"float:left;" }, | |||||
| 'year_uid': {'PlaceHolder':u"Année", "FieldStyle":"width:7em;", "ContainerStyle":"float:left;" }, | |||||
| 'phy_salle_id': {'PlaceHolder':u"Salle Physique", "FieldStyle":"width:20em;", "ContainerStyle":"float:left;" }, | 'phy_salle_id': {'PlaceHolder':u"Salle Physique", "FieldStyle":"width:20em;", "ContainerStyle":"float:left;" }, | ||||
| 'place_type': {'PlaceHolder':u"Type d'évènement","FieldStyle":"width:15em;" }, | |||||
| 'place_type': {'PlaceHolder':u"Type d'évènement","FieldStyle":"width:15em;" }, | |||||
| 'name': {'PlaceHolder':u"Nom de la salle", "FieldStyle":"width:90%;" }, | 'name': {'PlaceHolder':u"Nom de la salle", "FieldStyle":"width:90%;" }, | ||||
| 'description': {'PlaceHolder':u"Description", "ContainerStyle":"width:95%;min-height:150px;padding-top: 12px;", "ckeditor":"1" }, | 'description': {'PlaceHolder':u"Description", "ContainerStyle":"width:95%;min-height:150px;padding-top: 12px;", "ckeditor":"1" }, | ||||
| } | } | ||||
| @@ -46,7 +46,7 @@ | |||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| % endif | % endif | ||||
| % for item, one_dic in found.iteritems(): | |||||
| % for item, one_dic in found.items(): | |||||
| <tr> | <tr> | ||||
| <td> | <td> | ||||
| <a href="/user/${item}"> | <a href="/user/${item}"> | ||||
| @@ -63,7 +63,7 @@ from slugify import slugify | |||||
| </a> | </a> | ||||
| <span style="float:right;"> | <span style="float:right;"> | ||||
| - <a href="/user/${task.assignee.slug}">${task.assignee.pseudo or ' '.join([task.assignee.prenom, task.assignee.nom]) }</a> | - <a href="/user/${task.assignee.slug}">${task.assignee.pseudo or ' '.join([task.assignee.prenom, task.assignee.nom]) }</a> | ||||
| - ${task.due_date.strftime("%d %b").decode("utf-8")} | |||||
| - ${task.due_date.strftime("%d %b")} | |||||
| </span> | </span> | ||||
| % endif | % endif | ||||
| </td> | </td> | ||||
| @@ -30,7 +30,7 @@ | |||||
| %endif | %endif | ||||
| % if 'uid' in form._fields: | % if 'uid' in form._fields: | ||||
| <div class="borderboxtime"> | <div class="borderboxtime"> | ||||
| ${event.start_time.strftime('%d %b %Y').decode('utf-8')} - | |||||
| ${event.start_time.strftime('%d %b %Y')} - | |||||
| ${event.start_time.strftime('%H:%M')} à ${event.end_time.strftime('%H:%M')} | ${event.start_time.strftime('%H:%M')} à ${event.end_time.strftime('%H:%M')} | ||||
| %if event.Salle: | %if event.Salle: | ||||
| - <strong>Salle</strong>: ${event.Salle.name} | - <strong>Salle</strong>: ${event.Salle.name} | ||||
| @@ -184,10 +184,10 @@ DicForm = { | |||||
| </fieldset> | </fieldset> | ||||
| <div class="clearfix"> </div> | <div class="clearfix"> </div> | ||||
| <p style="float:right;">Créé le ${event.created.strftime('%d %b %Y').decode('utf-8')}</p> | |||||
| <p style="float:right;">Créé le ${event.created.strftime('%d %b %Y')}</p> | |||||
| %else: | %else: | ||||
| <p style="float:right;">Créé le | <p style="float:right;">Créé le | ||||
| ${datetime.now().strftime('%d %b %Y').decode('utf-8')} | |||||
| ${datetime.now().strftime('%d %b %Y')} | |||||
| </p> | </p> | ||||
| % endif | % endif | ||||
| <br/> | <br/> | ||||
| @@ -7,7 +7,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| %> | %> | ||||
| <div class="row-fluid"> | <div class="row-fluid"> | ||||
| % for FieldName, Field in form._fields.items(): | % for FieldName, Field in form._fields.items(): | ||||
| % if DicFormat.has_key(Field.name) and DicFormat[Field.name].get("Ignore"): | |||||
| % if Field.name in DicFormat and DicFormat[Field.name].get("Ignore"): | |||||
| <% continue %> | <% continue %> | ||||
| % endif | % endif | ||||
| % if Field.type in ['HiddenField', 'CSRFTokenField']: | % if Field.type in ['HiddenField', 'CSRFTokenField']: | ||||
| @@ -27,7 +27,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| </a> | </a> | ||||
| % endif | % endif | ||||
| </label> | </label> | ||||
| % if DicFormat.has_key(Field.name): | |||||
| % if Field.name in DicFormat: | |||||
| <% | <% | ||||
| PlaceHolder = DicFormat[Field.name].get("PlaceHolder") | PlaceHolder = DicFormat[Field.name].get("PlaceHolder") | ||||
| Class = [False,"ckeditor"][ "ckeditor" in DicFormat[Field.name] ] | Class = [False,"ckeditor"][ "ckeditor" in DicFormat[Field.name] ] | ||||
| @@ -49,7 +49,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| % endfor | % endfor | ||||
| </div> | </div> | ||||
| % if DicFormat.has_key(Field.name) and DicFormat[Field.name].get("next")==True: | |||||
| % if Field.name in DicFormat and DicFormat[Field.name].get("next")==True: | |||||
| </div> | </div> | ||||
| <div class="row-fluid"> | <div class="row-fluid"> | ||||
| % endif | % endif | ||||
| @@ -72,7 +72,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| TabJs = {'select':[], 'desc':[]} | TabJs = {'select':[], 'desc':[]} | ||||
| %> | %> | ||||
| % for FieldName, Field in form._fields.items(): | % for FieldName, Field in form._fields.items(): | ||||
| % if DicFormat.has_key(Field.name) and DicFormat[Field.name].get("Ignore"): | |||||
| % if Field.name in DicFormat and DicFormat[Field.name].get("Ignore"): | |||||
| <% continue %> | <% continue %> | ||||
| % endif | % endif | ||||
| % if Field.type in ['HiddenField', 'CSRFTokenField']: | % if Field.type in ['HiddenField', 'CSRFTokenField']: | ||||
| @@ -81,11 +81,11 @@ TabJs = {'select':[], 'desc':[]} | |||||
| % elif Field.type=="SelectField": | % elif Field.type=="SelectField": | ||||
| <% TabJs['select'].append(Field.label.field_id) %> | <% TabJs['select'].append(Field.label.field_id) %> | ||||
| % endif | % endif | ||||
| % if DicFormat.has_key(Field.name) and DicFormat[Field.name].get("fieldset"): | |||||
| % if Field.name in DicFormat and DicFormat[Field.name].get("fieldset"): | |||||
| <fieldset> | <fieldset> | ||||
| <legend>${Field.label.text}</legend> | <legend>${Field.label.text}</legend> | ||||
| % else: | % else: | ||||
| % if DicFormat.has_key(Field.name) and DicFormat[Field.name].get("ContainerStyle"): | |||||
| % if Field.name in DicFormat and DicFormat[Field.name].get("ContainerStyle"): | |||||
| <div style="padding-right:5px;${DicFormat[Field.name].get("ContainerStyle")}"> | <div style="padding-right:5px;${DicFormat[Field.name].get("ContainerStyle")}"> | ||||
| % else: | % else: | ||||
| <div style="padding-right:5px;"> | <div style="padding-right:5px;"> | ||||
| @@ -101,7 +101,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| % endif | % endif | ||||
| </label> | </label> | ||||
| % endif | % endif | ||||
| % if DicFormat.has_key(Field.name): | |||||
| % if Field.name in DicFormat: | |||||
| <% | <% | ||||
| PlaceHolder = DicFormat[Field.name].get("PlaceHolder") | PlaceHolder = DicFormat[Field.name].get("PlaceHolder") | ||||
| FieldStyle = DicFormat[Field.name].get("FieldStyle") | FieldStyle = DicFormat[Field.name].get("FieldStyle") | ||||
| @@ -122,7 +122,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| ${ error } | ${ error } | ||||
| </div> | </div> | ||||
| % endfor | % endfor | ||||
| % if DicFormat.has_key(Field.name) and DicFormat[Field.name].get("fieldset"): | |||||
| % if Field.name in DicFormat and DicFormat[Field.name].get("fieldset"): | |||||
| </fieldset> | </fieldset> | ||||
| % else: | % else: | ||||
| </div> | </div> | ||||
| @@ -142,7 +142,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| <%def name="sejour_wrapper(Places)"> | <%def name="sejour_wrapper(Places)"> | ||||
| <div class="form-inline"> | <div class="form-inline"> | ||||
| Départ : | |||||
| Départ : | |||||
| <select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu"> | <select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu"> | ||||
| % for place in Places: | % for place in Places: | ||||
| <option value="${place.place_id}">${place.display_name}</option> | <option value="${place.place_id}">${place.display_name}</option> | ||||
| @@ -151,7 +151,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| </div> | </div> | ||||
| <br /> | <br /> | ||||
| <div class="form-inline"> | <div class="form-inline"> | ||||
| Arrivée : | |||||
| Arrivée : | |||||
| <select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu"> | <select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu"> | ||||
| % for place in Places: | % for place in Places: | ||||
| <option value="${place.place_id}">${place.display_name}</option> | <option value="${place.place_id}">${place.display_name}</option> | ||||
| @@ -184,7 +184,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| ${itin_form.arrival_place(style='width:17em;')} | ${itin_form.arrival_place(style='width:17em;')} | ||||
| </div> | </div> | ||||
| <div style="padding:5px;"> | <div style="padding:5px;"> | ||||
| <small style="color:#999">Si je n´ai pas trouvé le lieu dont j´ai besoin dans ces listes...</small> | |||||
| <small style="color:#999">Si je n´ai pas trouvé le lieu dont j´ai besoin dans ces listes...</small> | |||||
| <br /> | <br /> | ||||
| <small style="color:#999">Je peux </small> | <small style="color:#999">Je peux </small> | ||||
| <a class="btn btn-mini btn-info" role="button" href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/0');"> | <a class="btn btn-mini btn-info" role="button" href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/0');"> | ||||
| @@ -350,9 +350,9 @@ TabJs = {'select':[], 'desc':[]} | |||||
| <tr> | <tr> | ||||
| <td style="text-align:center;" colspan="2"> | <td style="text-align:center;" colspan="2"> | ||||
| % if NotFoundTitle: | % if NotFoundTitle: | ||||
| <i>${NotFoundTitle}</i> | |||||
| <i>${NotFoundTitle | h}</i> | |||||
| % else: | % else: | ||||
| <i>Désolé, Il n'y a rien dans l'historique.</i> | |||||
| <i>Désolé;, Il n'y a rien dans l'historique.</i> | |||||
| % endif | % endif | ||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| @@ -366,7 +366,7 @@ TabJs = {'select':[], 'desc':[]} | |||||
| vid = event.video.first() | vid = event.video.first() | ||||
| pres = event.presentation.first() | pres = event.presentation.first() | ||||
| %> | %> | ||||
| ${event.start_time.strftime('%d %b %Y').decode('utf-8')} | |||||
| ${event.start_time.strftime('%d %b %Y')} | |||||
| ${start.hour}:${"%.2d" % start.minute}-${end.hour}:${"%.2d" % end.minute} | ${start.hour}:${"%.2d" % start.minute}-${end.hour}:${"%.2d" % end.minute} | ||||
| </td> | </td> | ||||
| <td style="position: relative;">${event.event_type}: | <td style="position: relative;">${event.event_type}: | ||||
| @@ -61,7 +61,7 @@ | |||||
| <div class="tabbable" id="main_tab"> | <div class="tabbable" id="main_tab"> | ||||
| <ul class="nav nav-tabs nav-pills" style="margin-bottom: 5px;"> | <ul class="nav nav-tabs nav-pills" style="margin-bottom: 5px;"> | ||||
| <li class="active"><a href="#Profil" id="Map_Profil" data-toggle="tab">Mon Profil</a></li> | <li class="active"><a href="#Profil" id="Map_Profil" data-toggle="tab">Mon Profil</a></li> | ||||
| <li><a href="#Sejour" id="Map_Sejour" data-toggle="tab">Mon Séjour</a></li> | |||||
| <li><a href="#Sejour" id="Map_Sejour" data-toggle="tab">Mon Séjour</a></li> | |||||
| <li><a href="#Logistique" id="Map_Logistique" data-toggle="tab">Logistique</a></li> | <li><a href="#Logistique" id="Map_Logistique" data-toggle="tab">Logistique</a></li> | ||||
| <li><a href="#Interventions" id="Map_Interventions" data-toggle="tab">Mes Interventions</a></li> | <li><a href="#Interventions" id="Map_Interventions" data-toggle="tab">Mes Interventions</a></li> | ||||
| <li><a href="#Frais" id="Map_Frais" data-toggle="tab">Mes Frais</a></li> | <li><a href="#Frais" id="Map_Frais" data-toggle="tab">Mes Frais</a></li> | ||||
| @@ -79,8 +79,8 @@ | |||||
| <div class="tabbable tabs-left" id="Interventions_tab"> | <div class="tabbable tabs-left" id="Interventions_tab"> | ||||
| <ul class="nav nav-tabs navbar" style="margin-bottom:0;"> | <ul class="nav nav-tabs navbar" style="margin-bottom:0;"> | ||||
| <li class="active"> <a href="#ResumePart" data-toggle="tab">Resumé</a> </li> | |||||
| <li> <a href="#Conference" data-toggle="tab">Conférence</a> </li> | |||||
| <li class="active"> <a href="#ResumePart" data-toggle="tab">Resumé</a> </li> | |||||
| <li> <a href="#Conference" data-toggle="tab">Conférence</a> </li> | |||||
| <li> <a href="#Stand" data-toggle="tab">Stand</a> </li> | <li> <a href="#Stand" data-toggle="tab">Stand</a> </li> | ||||
| <li> <a href="#Atelier" data-toggle="tab">Atelier</a> </li> | <li> <a href="#Atelier" data-toggle="tab">Atelier</a> </li> | ||||
| <li> <a href="#TableRonde" data-toggle="tab">Table Ronde</a> </li> | <li> <a href="#TableRonde" data-toggle="tab">Table Ronde</a> </li> | ||||
| @@ -118,12 +118,12 @@ | |||||
| <div class="tab-pane fade" id="Frais"> | <div class="tab-pane fade" id="Frais"> | ||||
| <fieldset> | <fieldset> | ||||
| <legend class="lowshadow">Une participation à mes frais ?</legend> | <legend class="lowshadow">Une participation à mes frais ?</legend> | ||||
| L'équipe des JM2L participe aux <u>frais de transport</u> des intervenants !<br /><br /> | |||||
| L'équipe des JM2L participe aux <u>frais de transport</u> des intervenants !<br /><br /> | |||||
| Et bien oui, mais cette participation ne sera effective que si vous remplissez <u>toutes les conditions</u> suivantes: | Et bien oui, mais cette participation ne sera effective que si vous remplissez <u>toutes les conditions</u> suivantes: | ||||
| <ul style="list-style:circle;"> | <ul style="list-style:circle;"> | ||||
| <li>Vous animez <strong>un atelier, une conférence ou une table ronde</strong> aux JM2L ${CurrentYear}.</li> | |||||
| <li>Votre fiche est renseignée avec <strong>votre RIB</strong>.</li> | |||||
| <li>Votre fiche est renseignée avec <strong>les preuves</strong> de vos achats.</li> | |||||
| <li>Vous animez <strong>un atelier, une conférence ou une table ronde</strong> aux JM2L ${CurrentYear}.</li> | |||||
| <li>Votre fiche est renseignée avec <strong>votre RIB</strong>.</li> | |||||
| <li>Votre fiche est renseignée avec <strong>les preuves</strong> de vos achats.</li> | |||||
| <li>Vous <strong>présentez l'original de vos tickets</strong> à l'accueil pendant l'évènement.</li> | <li>Vous <strong>présentez l'original de vos tickets</strong> à l'accueil pendant l'évènement.</li> | ||||
| <li>Tous vos documents sont conformes.</li> | <li>Tous vos documents sont conformes.</li> | ||||
| </ul> | </ul> | ||||
| @@ -3,7 +3,7 @@ | |||||
| <%namespace name="helpers" file="jm2l:templates/helpers.mako"/> | <%namespace name="helpers" file="jm2l:templates/helpers.mako"/> | ||||
| <% | <% | ||||
| context._kwargs['postpone_js']=[] | context._kwargs['postpone_js']=[] | ||||
| DisplayYear = request.session.get('year', 2018) | |||||
| DisplayYear = request.session.get('year', 2020) | |||||
| %> | %> | ||||
| <head> | <head> | ||||
| <title>JM2L ${DisplayYear}</title> | <title>JM2L ${DisplayYear}</title> | ||||
| @@ -68,12 +68,12 @@ ${helpers.uploader_js()} | |||||
| % if request.user and request.user.vote_logo not in [1,2,3]: | % if request.user and request.user.vote_logo not in [1,2,3]: | ||||
| <div class="item active"> | <div class="item active"> | ||||
| <div class="align-center"> | <div class="align-center"> | ||||
| <H1>JM2L 2017</H1> | |||||
| <h3>Choisissez ici votre logo préféré !</h3> | |||||
| <H1>JM2L 2020</H1> | |||||
| <h3>Choisissez ici votre logo préféré !</h3> | |||||
| <p>Utilisez les flèches pour choisir et voter !<br> | <p>Utilisez les flèches pour choisir et voter !<br> | ||||
| Vous pouvez changer à tout moment, mais vous n'aurez droit qu'a un seul choix, le vôtre ;)</p> | Vous pouvez changer à tout moment, mais vous n'aurez droit qu'a un seul choix, le vôtre ;)</p> | ||||
| <p>Vous souhaitez proposer le vôtre ? <br> | <p>Vous souhaitez proposer le vôtre ? <br> | ||||
| N'hésitez pas à envoyer vos propositions par mail à l'équipe !</p> | |||||
| N'hésitez pas à envoyer vos propositions par mail à l'équipe !</p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| % endif | % endif | ||||
| @@ -105,10 +105,10 @@ ${helpers.uploader_js()} | |||||
| <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"> | <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"> | ||||
| Édition <span class="caret"></span></a> | Édition <span class="caret"></span></a> | ||||
| <ul class="dropdown-menu pull-right" style="min-width:0"> | <ul class="dropdown-menu pull-right" style="min-width:0"> | ||||
| % for tmpyear in range(2018, 2005, -1): | |||||
| % for tmpyear in range(2020, 2005, -1): | |||||
| % if tmpyear==DisplayYear: | % if tmpyear==DisplayYear: | ||||
| <li><a style="font-weight: bold;" href="/year/${tmpyear}">${tmpyear}</a></li> | <li><a style="font-weight: bold;" href="/year/${tmpyear}">${tmpyear}</a></li> | ||||
| % elif tmpyear!=2014 and tmpyear!=2016: | |||||
| % elif tmpyear not in [2014, 2016, 2018, 2019]: | |||||
| <li><a href="/year/${tmpyear}">${tmpyear}</a></li> | <li><a href="/year/${tmpyear}">${tmpyear}</a></li> | ||||
| % endif | % endif | ||||
| % endfor | % endfor | ||||
| @@ -128,17 +128,17 @@ ${helpers.uploader_js()} | |||||
| % if request.user: | % if request.user: | ||||
| % if request.user.Staff: | % if request.user.Staff: | ||||
| <li><a href="/${DisplayYear}/Staff">Partie Staff</a></li> | <li><a href="/${DisplayYear}/Staff">Partie Staff</a></li> | ||||
| <li><a href="/${DisplayYear}/ListParticipant">Gérer les intervenants</a></li> | |||||
| <li><a href="/ListSalles">Gérer les salles</a></li> | |||||
| <li><a href="/entities">Gérer les entités</a></li> | |||||
| <li><a href="/${DisplayYear}/ListParticipant">Gérer les intervenants</a></li> | |||||
| <li><a href="/ListSalles">Gérer les salles</a></li> | |||||
| <li><a href="/entities">Gérer les entités</a></li> | |||||
| <li><a href="/${DisplayYear}/ListOrga">Participations à l'orga</a></li> | <li><a href="/${DisplayYear}/ListOrga">Participations à l'orga</a></li> | ||||
| <li><a href="/${DisplayYear}/Staff/compta">Comptabilité</a></li> | |||||
| <li><a href="/${DisplayYear}/Staff/compta">Comptabilité</a></li> | |||||
| <li><a href="/ListSallesPhy">Les salles à Poly'tech</a></li> | <li><a href="/ListSallesPhy">Les salles à Poly'tech</a></li> | ||||
| <li role="separator" class="divider"></li> | <li role="separator" class="divider"></li> | ||||
| % endif | % endif | ||||
| <li><a href="/MesJM2L">Mon profil</a></li> | <li><a href="/MesJM2L">Mon profil</a></li> | ||||
| <li><a href="/user/${request.user.slug}">Mon profil public</a></li> | <li><a href="/user/${request.user.slug}">Mon profil public</a></li> | ||||
| <li><a href="/sign/out">Me déconnecter</a></li> | |||||
| <li><a href="/sign/out">Me déconnecter</a></li> | |||||
| % else: | % else: | ||||
| <li><a href="/participer-l-evenement#inscription">Je m'inscris</a></li> | <li><a href="/participer-l-evenement#inscription">Je m'inscris</a></li> | ||||
| <li><a href="/sign/login">Je m'identifie</a></li> | <li><a href="/sign/login">Je m'identifie</a></li> | ||||
| @@ -186,9 +186,9 @@ ${helpers.uploader_js()} | |||||
| <footer class="footer"> | <footer class="footer"> | ||||
| <div class="container"> | <div class="container"> | ||||
| <h4>JM2L 2005-2018</h4> | |||||
| <h4>JM2L 2005-2020</h4> | |||||
| <p> | <p> | ||||
| Concocté par <a href="http://www.linux-azur.org/">Linux Azur</a> ~ | |||||
| Concocté par <a href="http://www.linux-azur.org/">Linux Azur</a> ~ | |||||
| <a href="http://creativecommons.org/licenses/by-sa/4.0/">CopyFriendly</a> | <a href="http://creativecommons.org/licenses/by-sa/4.0/">CopyFriendly</a> | ||||
| </p> | </p> | ||||
| <p> | <p> | ||||
| @@ -196,10 +196,10 @@ ${helpers.uploader_js()} | |||||
| </p> | </p> | ||||
| <p> | <p> | ||||
| Conception et construction en <a href="http://git.linux-azur.org/JM2L/jm2l/src/master">DIY</a> ~ | Conception et construction en <a href="http://git.linux-azur.org/JM2L/jm2l/src/master">DIY</a> ~ | ||||
| Hébergé par <a href="http://www.heberg-24.com/"> Heberg24 </a> | |||||
| Hébergé par <a href="http://www.heberg-24.com/"> Heberg24 </a> | |||||
| </p> | </p> | ||||
| <p> | <p> | ||||
| Vous avez trouvé un bug ? <a href="http://git.linux-azur.org/JM2L/jm2l/issues">Reportez-le ici</a> | |||||
| Vous avez trouvé un bug ? <a href="http://git.linux-azur.org/JM2L/jm2l/issues">Reportez-le ici</a> | |||||
| </p> | </p> | ||||
| </div> | </div> | ||||
| </footer> | </footer> | ||||
| @@ -245,7 +245,7 @@ function handlevote() { | |||||
| $('.carousel-vote a').attr('href', "/vote_logo/" + currentIndex ) | $('.carousel-vote a').attr('href', "/vote_logo/" + currentIndex ) | ||||
| if (currentIndex==${request.user.vote_logo or 0}) { | if (currentIndex==${request.user.vote_logo or 0}) { | ||||
| $('.carousel-vote a').removeClass('btn-primary').addClass('btn-success') | $('.carousel-vote a').removeClass('btn-primary').addClass('btn-success') | ||||
| $('.carousel-vote a').html("<i class='icon-ok icon-white'></i> Mon préféré ! "); | |||||
| $('.carousel-vote a').html("<i class='icon-ok icon-white'></i> Mon préféré ! "); | |||||
| } else { | } else { | ||||
| $('.carousel-vote a').removeClass('btn-success').addClass('btn-primary'); | $('.carousel-vote a').removeClass('btn-success').addClass('btn-primary'); | ||||
| $('.carousel-vote a').html("<i class='icon-star icon-white'></i> Je vote pour ce logo ! "); | $('.carousel-vote a').html("<i class='icon-star icon-white'></i> Je vote pour ce logo ! "); | ||||
| @@ -96,7 +96,7 @@ Voici ce qu'il y'a dans la liste des tâches qui te sont assignées: | |||||
| % for t in sorted(User.task_assoc, key=lambda k:k.due_date): | % for t in sorted(User.task_assoc, key=lambda k:k.due_date): | ||||
| % if not t.closed: | % if not t.closed: | ||||
| <tr> | <tr> | ||||
| <td>${t.due_date.strftime('%d %B %Y').decode('utf-8', 'xmlcharrefreplace')}</td><td>${t.area.name}</td> | |||||
| <td>${t.due_date.strftime('%d %B %Y')}</td><td>${t.area.name}</td> | |||||
| <td><a href="http://jm2l.linux-azur.org/2017/Staff/tasks/${t.uid}">${t.name}</a> | <td><a href="http://jm2l.linux-azur.org/2017/Staff/tasks/${t.uid}">${t.name}</a> | ||||
| % endif | % endif | ||||
| % endfor | % endfor | ||||
| @@ -107,7 +107,7 @@ Voici ce qu'il y'a dans la liste des tâches qui te sont assignées: | |||||
| % for t in sorted(Contact.task_assoc, key=lambda k:k.due_date): | % for t in sorted(Contact.task_assoc, key=lambda k:k.due_date): | ||||
| % if not t.closed: | % if not t.closed: | ||||
| <tr> | <tr> | ||||
| <td>${t.due_date.strftime('%d %B %Y').decode('utf-8', 'xmlcharrefreplace')}</td><td>${t.area.name}</td> | |||||
| <td>${t.due_date.strftime('%d %B %Y')}</td><td>${t.area.name}</td> | |||||
| <td><a href="http://jm2l.linux-azur.org/2017/Staff/tasks/${t.uid}">${t.name}</a> | <td><a href="http://jm2l.linux-azur.org/2017/Staff/tasks/${t.uid}">${t.name}</a> | ||||
| % endif | % endif | ||||
| % endfor | % endfor | ||||
| @@ -116,7 +116,7 @@ Voici ce qu'il y'a dans la liste des tâches qui te sont assignées: | |||||
| Pour accéder à ton espace sur le site, il te suffit de cliquer sur le <a href="${request.route_url('bymail', hash=User.my_hash)}">lien suivant.</a> | Pour accéder à ton espace sur le site, il te suffit de cliquer sur le <a href="${request.route_url('bymail', hash=User.my_hash)}">lien suivant.</a> | ||||
| <br/><br/> | <br/><br/> | ||||
| % for t in filter(lambda k:k.uid==51, Contact.task_assoc): | % for t in filter(lambda k:k.uid==51, Contact.task_assoc): | ||||
| Nous avons fixé la prochaine réunion JM2L au ${t.due_date.strftime('%d %B').decode('utf-8', 'xmlcharrefreplace')} à 19h30. | |||||
| Nous avons fixé la prochaine réunion JM2L au ${t.due_date.strftime('%d %B')} à 19h30. | |||||
| % endfor | % endfor | ||||
| <p> | <p> | ||||
| Bon courage ! | Bon courage ! | ||||
| @@ -65,7 +65,7 @@ Voici ce qu'il y'a dans la liste des tâches qui te sont assignées: | |||||
| % for t in sorted(User.task_assoc, key=lambda k:k.due_date): | % for t in sorted(User.task_assoc, key=lambda k:k.due_date): | ||||
| % if not t.closed: | % if not t.closed: | ||||
| - Pour le ${t.due_date.strftime('%d %B %Y').decode('utf-8', 'xmlcharrefreplace')} - ${t.area.name} tâche ${t.uid} | |||||
| - Pour le ${t.due_date.strftime('%d %B %Y')} - ${t.area.name} tâche ${t.uid} | |||||
| => ${t.name} | => ${t.name} | ||||
| % endif | % endif | ||||
| @@ -75,7 +75,7 @@ Et il y'a aussi des tâches communes ! | |||||
| % for t in sorted(Contact.task_assoc, key=lambda k:k.due_date): | % for t in sorted(Contact.task_assoc, key=lambda k:k.due_date): | ||||
| % if not t.closed and t.uid!=51: | % if not t.closed and t.uid!=51: | ||||
| - Pour le ${t.due_date.strftime('%d %B %Y').decode('utf-8', 'xmlcharrefreplace')} - ${t.area.name} tâche ${t.uid} | |||||
| - Pour le ${t.due_date.strftime('%d %B %Y')} - ${t.area.name} tâche ${t.uid} | |||||
| => ${t.name} | => ${t.name} | ||||
| % endif | % endif | ||||
| @@ -85,7 +85,7 @@ Pour accéder à ton espace il te suffit de cliquer sur le lien suivant : | |||||
| ${request.route_url('bymail', hash=User.my_hash)}. | ${request.route_url('bymail', hash=User.my_hash)}. | ||||
| % for t in filter(lambda k:k.uid==51, Contact.task_assoc): | % for t in filter(lambda k:k.uid==51, Contact.task_assoc): | ||||
| Nous avons fixé la prochaine réunion JM2L au ${t.due_date.strftime('%d %B').decode('utf-8', 'xmlcharrefreplace')} à 19h30. | |||||
| Nous avons fixé la prochaine réunion JM2L au ${t.due_date.strftime('%d %B')} à 19h30. | |||||
| % endfor | % endfor | ||||
| @@ -52,7 +52,7 @@ | |||||
| </div> | </div> | ||||
| <br/> | <br/> | ||||
| <hr/> | <hr/> | ||||
| <p style="float:right;">Créé le ${DispUser.created.strftime('%d %b %Y').decode('utf-8')}</p> | |||||
| <p style="float:right;">Créé le ${DispUser.created.strftime('%d %b %Y')}</p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -13,7 +13,7 @@ | |||||
| </div> | </div> | ||||
| <strong>${event.event_type}</strong>: | <strong>${event.event_type}</strong>: | ||||
| <div class="borderboxtime"> | <div class="borderboxtime"> | ||||
| ${event.start_time.strftime('%d %b %Y').decode('utf-8')} - | |||||
| ${event.start_time.strftime('%d %b %Y')} - | |||||
| ${event.start_time.strftime('%H:%M')} à ${event.end_time.strftime('%H:%M')} | ${event.start_time.strftime('%H:%M')} à ${event.end_time.strftime('%H:%M')} | ||||
| </div> | </div> | ||||
| % if event.for_year==CurrentYear and request.user and (request.user.Staff or request.user in event.intervenants): | % if event.for_year==CurrentYear and request.user and (request.user.Staff or request.user in event.intervenants): | ||||
| @@ -116,7 +116,7 @@ | |||||
| </p> | </p> | ||||
| % endfor | % endfor | ||||
| <div class="clearfix"> </div> | <div class="clearfix"> </div> | ||||
| <p style="float:right;">Créé le ${event.created.strftime('%d %b %Y').decode('utf-8')}</p> | |||||
| <p style="float:right;">Créé le ${event.created.strftime('%d %b %Y')}</p> | |||||
| <br/> | <br/> | ||||
| <hr/> | <hr/> | ||||
| </div> | </div> | ||||
| @@ -103,7 +103,7 @@ ${The_entity_type.entity_subtype} | |||||
| </p> | </p> | ||||
| % endfor | % endfor | ||||
| <br/><br/> | <br/><br/> | ||||
| <p style="float:right;">Créé le ${entity.created.strftime('%d %b %Y').decode('utf-8')}</p> | |||||
| <p style="float:right;">Créé le ${entity.created.strftime('%d %b %Y')}</p> | |||||
| <br/> | <br/> | ||||
| <hr/> | <hr/> | ||||
| @@ -47,7 +47,7 @@ | |||||
| <h4>Ses interventions :</h4> | <h4>Ses interventions :</h4> | ||||
| ${helpers.show_Interventions(DispUser.events)} | ${helpers.show_Interventions(DispUser.events)} | ||||
| % endif | % endif | ||||
| <p style="float:right;">Créé le ${DispUser.created.strftime('%d %b %Y').decode('utf-8')}</p> | |||||
| <p style="float:right;">Créé le ${DispUser.created.strftime('%d %b %Y')}</p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -1,6 +1,9 @@ | |||||
| # -*- coding: utf8 -*- | # -*- coding: utf8 -*- | ||||
| from pyramid.response import Response | from pyramid.response import Response | ||||
| import cStringIO as StringIO | |||||
| 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 | ||||
| @@ -9,113 +9,114 @@ from os import path | |||||
| import mimetypes | import mimetypes | ||||
| import magic | import magic | ||||
| import subprocess | import subprocess | ||||
| import cStringIO as StringIO | |||||
| try: | |||||
| from StringIO import StringIO | |||||
| except ImportError: | |||||
| from io import StringIO | |||||
| # Database access imports | # Database access imports | ||||
| from .models import User, Place, Tiers, Event, SallePhy | from .models import User, Place, Tiers, Event, SallePhy | ||||
| from .blenderthumbnailer import blend_extract_thumb, write_png | from .blenderthumbnailer import blend_extract_thumb, write_png | ||||
| from jm2l.const import CurrentYear | from jm2l.const import CurrentYear | ||||
| from slugify import slugify | from slugify import slugify | ||||
| MIN_FILE_SIZE = 1 # bytes | |||||
| MAX_FILE_SIZE = 500000000 # bytes | |||||
| MIN_FILE_SIZE = 1 # bytes | |||||
| MAX_FILE_SIZE = 500000000 # bytes | |||||
| IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') | IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') | ||||
| ACCEPTED_MIMES = ['application/pdf', | ACCEPTED_MIMES = ['application/pdf', | ||||
| 'application/vnd.oasis.opendocument.text', | |||||
| 'application/vnd.oasis.opendocument.text-template', | |||||
| 'application/vnd.oasis.opendocument.graphics', | |||||
| 'application/vnd.oasis.opendocument.graphics-template', | |||||
| 'application/vnd.oasis.opendocument.presentation', | |||||
| 'application/vnd.oasis.opendocument.presentation-template', | |||||
| 'application/vnd.oasis.opendocument.spreadsheet', | |||||
| 'application/vnd.oasis.opendocument.spreadsheet-template', | |||||
| 'image/svg+xml', | |||||
| 'application/x-blender' | |||||
| ] | |||||
| 'application/vnd.oasis.opendocument.text', | |||||
| 'application/vnd.oasis.opendocument.text-template', | |||||
| 'application/vnd.oasis.opendocument.graphics', | |||||
| 'application/vnd.oasis.opendocument.graphics-template', | |||||
| 'application/vnd.oasis.opendocument.presentation', | |||||
| 'application/vnd.oasis.opendocument.presentation-template', | |||||
| 'application/vnd.oasis.opendocument.spreadsheet', | |||||
| 'application/vnd.oasis.opendocument.spreadsheet-template', | |||||
| 'image/svg+xml', | |||||
| 'application/x-blender' | |||||
| ] | |||||
| ACCEPT_FILE_TYPES = IMAGE_TYPES | ACCEPT_FILE_TYPES = IMAGE_TYPES | ||||
| THUMBNAIL_SIZE = 80 | THUMBNAIL_SIZE = 80 | ||||
| EXPIRATION_TIME = 300 # seconds | |||||
| IMAGEPATH = [ 'images' ] | |||||
| DOCPATH = [ 'document' ] | |||||
| THUMBNAILPATH = [ 'images', 'thumbnails' ] | |||||
| EXPIRATION_TIME = 300 # seconds | |||||
| IMAGEPATH = ['images'] | |||||
| DOCPATH = ['document'] | |||||
| THUMBNAILPATH = ['images', 'thumbnails'] | |||||
| # change the following to POST if DELETE isn't supported by the webserver | # change the following to POST if DELETE isn't supported by the webserver | ||||
| DELETEMETHOD="DELETE" | |||||
| DELETEMETHOD = "DELETE" | |||||
| mimetypes.init() | mimetypes.init() | ||||
| class MediaPath(): | |||||
| class MediaPath(): | |||||
| def get_all(self, media_table, linked_id, MediaType=None): | def get_all(self, media_table, linked_id, MediaType=None): | ||||
| filelist = list() | filelist = list() | ||||
| curpath = self.get_mediapath(media_table, linked_id, None) | curpath = self.get_mediapath(media_table, linked_id, None) | ||||
| thumbpath = os.path.join( curpath, 'thumbnails') | |||||
| thumbpath = os.path.join(curpath, 'thumbnails') | |||||
| if not os.path.isdir(curpath) or not os.path.isdir(thumbpath): | if not os.path.isdir(curpath) or not os.path.isdir(thumbpath): | ||||
| return list() | return list() | ||||
| for f in os.listdir(curpath): | for f in os.listdir(curpath): | ||||
| filename, ext = os.path.splitext( f ) | |||||
| if os.path.isdir(os.path.join(curpath,f)): | |||||
| filename, ext = os.path.splitext(f) | |||||
| if os.path.isdir(os.path.join(curpath, f)): | |||||
| continue | continue | ||||
| if f.endswith('.type'): | if f.endswith('.type'): | ||||
| continue | continue | ||||
| if f: | if f: | ||||
| ress_url = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ", "%20")) | ress_url = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ", "%20")) | ||||
| thumb_url = '/image/%s/%d/thumbnails/%s' % (media_table, linked_id, f.replace(" ","%20")) | |||||
| thumb_url = '/image/%s/%d/thumbnails/%s' % (media_table, linked_id, f.replace(" ", "%20")) | |||||
| if MediaType is None: | if MediaType is None: | ||||
| if os.path.exists(os.path.join(thumbpath, f +".jpg")): | |||||
| filelist.append((ress_url, thumb_url +".jpg")) | |||||
| if os.path.exists(os.path.join(thumbpath, f + ".jpg")): | |||||
| filelist.append((ress_url, thumb_url + ".jpg")) | |||||
| else: | else: | ||||
| filelist.append((ress_url, thumb_url)) | filelist.append((ress_url, thumb_url)) | ||||
| elif MediaType=='Image' and len( os.path.splitext(filename)[1] )==0: | |||||
| elif MediaType == 'Image' and len(os.path.splitext(filename)[1]) == 0: | |||||
| filelist.append((ress_url, thumb_url)) | filelist.append((ress_url, thumb_url)) | ||||
| elif MediaType=='Other' and len( os.path.splitext(filename)[1] ): | |||||
| elif MediaType == 'Other' and len(os.path.splitext(filename)[1]): | |||||
| filelist.append((ress_url, thumb_url)) | filelist.append((ress_url, thumb_url)) | ||||
| return filelist | return filelist | ||||
| def get_list(self, media_table, linked_id, MediaType=None): | def get_list(self, media_table, linked_id, MediaType=None): | ||||
| filelist = list() | filelist = list() | ||||
| curpath = self.get_mediapath(media_table, linked_id, None) | curpath = self.get_mediapath(media_table, linked_id, None) | ||||
| if not os.path.isdir(curpath): | if not os.path.isdir(curpath): | ||||
| return list() | return list() | ||||
| for f in os.listdir(curpath): | for f in os.listdir(curpath): | ||||
| if os.path.isdir(os.path.join(curpath,f)): | |||||
| if os.path.isdir(os.path.join(curpath, f)): | |||||
| continue | continue | ||||
| if f.endswith('.type'): | if f.endswith('.type'): | ||||
| continue | continue | ||||
| if f: | if f: | ||||
| filename, ext = os.path.splitext( f ) | |||||
| tmpurl = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ","%20")) | |||||
| filename, ext = os.path.splitext(f) | |||||
| tmpurl = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ", "%20")) | |||||
| if MediaType is None: | if MediaType is None: | ||||
| filelist.append(tmpurl) | filelist.append(tmpurl) | ||||
| elif MediaType=='Image' and ext.lower() in ['.gif','.jpg','.png','.svg','.jpeg']: | |||||
| elif MediaType == 'Image' and ext.lower() in ['.gif', '.jpg', '.png', '.svg', '.jpeg']: | |||||
| filelist.append(tmpurl) | filelist.append(tmpurl) | ||||
| elif MediaType=='Other' and ext.lower() not in ['.gif','.jpg','.png','.svg','.jpeg']: | |||||
| elif MediaType == 'Other' and ext.lower() not in ['.gif', '.jpg', '.png', '.svg', '.jpeg']: | |||||
| filelist.append(tmpurl) | filelist.append(tmpurl) | ||||
| return filelist | return filelist | ||||
| def get_thumb(self, media_table, linked_id, MediaType=None): | def get_thumb(self, media_table, linked_id, MediaType=None): | ||||
| filelist = list() | filelist = list() | ||||
| curpath = self.get_mediapath(media_table, linked_id, None) | curpath = self.get_mediapath(media_table, linked_id, None) | ||||
| curpath = os.path.join( curpath, 'thumbnails') | |||||
| curpath = os.path.join(curpath, 'thumbnails') | |||||
| if not os.path.isdir(curpath): | if not os.path.isdir(curpath): | ||||
| return list() | return list() | ||||
| for f in os.listdir(curpath): | for f in os.listdir(curpath): | ||||
| filename, ext = os.path.splitext( f ) | |||||
| if os.path.isdir(os.path.join(curpath,f)): | |||||
| filename, ext = os.path.splitext(f) | |||||
| if os.path.isdir(os.path.join(curpath, f)): | |||||
| continue | continue | ||||
| if f.endswith('.type'): | if f.endswith('.type'): | ||||
| continue | continue | ||||
| if f: | if f: | ||||
| tmpurl = '/image/%s/%d/thumbnails/%s' % (media_table, linked_id, f.replace(" ","%20")) | |||||
| tmpurl = '/image/%s/%d/thumbnails/%s' % (media_table, linked_id, f.replace(" ", "%20")) | |||||
| if MediaType is None: | if MediaType is None: | ||||
| filelist.append(tmpurl) | filelist.append(tmpurl) | ||||
| elif MediaType=='Image' and len( os.path.splitext(filename)[1] )==0: | |||||
| elif MediaType == 'Image' and len(os.path.splitext(filename)[1]) == 0: | |||||
| filelist.append(tmpurl) | filelist.append(tmpurl) | ||||
| elif MediaType=='Other' and len( os.path.splitext(filename)[1] ): | |||||
| elif MediaType == 'Other' and len(os.path.splitext(filename)[1]): | |||||
| filelist.append(tmpurl) | filelist.append(tmpurl) | ||||
| return filelist | |||||
| return filelist | |||||
| def move_mediapath(self, media_table, from_id, to_id): | def move_mediapath(self, media_table, from_id, to_id): | ||||
| """ | """ | ||||
| @@ -126,8 +127,8 @@ class MediaPath(): | |||||
| :return: Error if any | :return: Error if any | ||||
| """ | """ | ||||
| if media_table in ['tiers', 'place', 'salle', 'users']: | if media_table in ['tiers', 'place', 'salle', 'users']: | ||||
| src = IMAGEPATH + [ media_table, from_id ] | |||||
| dst = IMAGEPATH + [ media_table, to_id ] | |||||
| src = IMAGEPATH + [media_table, from_id] | |||||
| dst = IMAGEPATH + [media_table, to_id] | |||||
| else: | else: | ||||
| raise RuntimeError("Sorry, Media '%s' not supported yet for move." % media_table) | raise RuntimeError("Sorry, Media '%s' not supported yet for move." % media_table) | ||||
| @@ -153,51 +154,51 @@ class MediaPath(): | |||||
| linked_id = str(linked_id) | linked_id = str(linked_id) | ||||
| if media_table in ['tiers', 'place', 'salle']: | if media_table in ['tiers', 'place', 'salle']: | ||||
| # Retrieve Slug | # Retrieve Slug | ||||
| if media_table=='tiers': | |||||
| if media_table == 'tiers': | |||||
| slug = Tiers.by_id(linked_id).slug | slug = Tiers.by_id(linked_id).slug | ||||
| if media_table=='place': | |||||
| if media_table == 'place': | |||||
| slug = Place.by_id(linked_id).slug or slugify(Place.by_id(linked_id).name) | slug = Place.by_id(linked_id).slug or slugify(Place.by_id(linked_id).name) | ||||
| if media_table=='salle': | |||||
| if media_table == 'salle': | |||||
| slug = SallePhy.by_id(linked_id).slug | slug = SallePhy.by_id(linked_id).slug | ||||
| p = IMAGEPATH + [ media_table, slug ] | |||||
| elif media_table=='presse': | |||||
| p = IMAGEPATH + [media_table, slug] | |||||
| elif media_table == 'presse': | |||||
| # Use Year in linked_id | # Use Year in linked_id | ||||
| p = IMAGEPATH + [ media_table, linked_id ] | |||||
| elif media_table=='tasks': | |||||
| p = IMAGEPATH + [media_table, linked_id] | |||||
| elif media_table == 'tasks': | |||||
| # Use Current Year | # Use Current Year | ||||
| p = IMAGEPATH + [ str(CurrentYear), media_table, linked_id ] | |||||
| elif media_table=='poles': | |||||
| p = IMAGEPATH + [str(CurrentYear), media_table, linked_id] | |||||
| elif media_table == 'poles': | |||||
| # Use Current Year | # Use Current Year | ||||
| p = IMAGEPATH + [ str(CurrentYear), media_table, linked_id ] | |||||
| p = IMAGEPATH + [str(CurrentYear), media_table, linked_id] | |||||
| elif media_table in ['RIB', 'Justif']: | elif media_table in ['RIB', 'Justif']: | ||||
| slug = User.by_id(linked_id).slug | slug = User.by_id(linked_id).slug | ||||
| p = IMAGEPATH + ['users', slug , media_table ] | |||||
| p = IMAGEPATH + ['users', slug, media_table] | |||||
| elif media_table in ['users', 'badge']: | elif media_table in ['users', 'badge']: | ||||
| user = User.by_id(linked_id) | user = User.by_id(linked_id) | ||||
| if not user: | if not user: | ||||
| raise HTTPNotFound() | raise HTTPNotFound() | ||||
| else: | else: | ||||
| slug = user.slug | slug = user.slug | ||||
| p = IMAGEPATH + [media_table, slug ] | |||||
| elif media_table=='event': | |||||
| p = IMAGEPATH + [media_table, slug] | |||||
| elif media_table == 'event': | |||||
| ev = Event.by_id(linked_id) | ev = Event.by_id(linked_id) | ||||
| slug = ev.slug | slug = ev.slug | ||||
| year = ev.for_year | year = ev.for_year | ||||
| p = IMAGEPATH + ['event', str(year), slug ] | |||||
| p = IMAGEPATH + ['event', str(year), slug] | |||||
| if name: | if name: | ||||
| p += [ name ] | |||||
| p += [name] | |||||
| TargetPath = os.path.join('jm2l/upload', *p) | TargetPath = os.path.join('jm2l/upload', *p) | ||||
| if not os.path.isdir(os.path.dirname(TargetPath)): | if not os.path.isdir(os.path.dirname(TargetPath)): | ||||
| try: | try: | ||||
| os.makedirs(os.path.dirname(TargetPath)) | os.makedirs(os.path.dirname(TargetPath)) | ||||
| except OSError, e: | |||||
| except OSError as e: | |||||
| if e.errno != 17: | if e.errno != 17: | ||||
| raise e | raise e | ||||
| return os.path.join('jm2l/upload', *p) | |||||
| return os.path.join('jm2l/upload', *p) | |||||
| def ExtMimeIcon(self, mime): | def ExtMimeIcon(self, mime): | ||||
| if mime=='application/pdf': | |||||
| if mime == 'application/pdf': | |||||
| return "/img/PDF.png" | return "/img/PDF.png" | ||||
| def check_blend_file(self, fileobj): | def check_blend_file(self, fileobj): | ||||
| @@ -217,12 +218,12 @@ class MediaPath(): | |||||
| fileobj.seek(0) | fileobj.seek(0) | ||||
| # Check if the binary file is a blender file | # Check if the binary file is a blender file | ||||
| if ( mimetype == "application/octet-stream" or mimetype == "application/x-gzip" ) and self.check_blend_file(fileobj): | |||||
| if (mimetype == "application/octet-stream" or mimetype == "application/x-gzip") and self.check_blend_file( | |||||
| fileobj): | |||||
| return "application/x-blender", True | return "application/x-blender", True | ||||
| else: | else: | ||||
| return mimetype, False | return mimetype, False | ||||
| def get_mimetype(self, name): | def get_mimetype(self, name): | ||||
| """ This function return the mime-type based on .type file """ | """ This function return the mime-type based on .type file """ | ||||
| try: | try: | ||||
| @@ -232,6 +233,7 @@ class MediaPath(): | |||||
| except IOError: | except IOError: | ||||
| return None | return None | ||||
| @view_defaults(route_name='media_upload') | @view_defaults(route_name='media_upload') | ||||
| class MediaUpload(MediaPath): | class MediaUpload(MediaPath): | ||||
| @@ -256,17 +258,17 @@ class MediaUpload(MediaPath): | |||||
| # Try to determine mime type from content uploaded | # Try to determine mime type from content uploaded | ||||
| found_mime = magic.from_buffer(filecontent.read(1024), mime=True) | found_mime = magic.from_buffer(filecontent.read(1024), mime=True) | ||||
| filecontent.seek(0) | filecontent.seek(0) | ||||
| # Do a special statement for specific detected mime type | # Do a special statement for specific detected mime type | ||||
| if found_mime in ["application/octet-stream", "application/x-gzip"]: | if found_mime in ["application/octet-stream", "application/x-gzip"]: | ||||
| # Lets see if it's a bender file | # Lets see if it's a bender file | ||||
| if self.check_blend_file(filecontent): | if self.check_blend_file(filecontent): | ||||
| found_mime = "application/x-blender" | found_mime = "application/x-blender" | ||||
| # MonKey Patch of content type | # MonKey Patch of content type | ||||
| result['type'] = found_mime | |||||
| # Reject mime type that don't match | |||||
| if found_mime!=result['type']: | |||||
| result['type'] = found_mime | |||||
| # Reject mime type that don't match | |||||
| if found_mime != result['type']: | |||||
| result['error'] = 'L\'extension du fichier ne correspond pas à son contenu - ' | result['error'] = 'L\'extension du fichier ne correspond pas à son contenu - ' | ||||
| result['error'] += "( %s vs %s )" % (found_mime, result['type']) | result['error'] += "( %s vs %s )" % (found_mime, result['type']) | ||||
| return False | return False | ||||
| @@ -281,7 +283,7 @@ class MediaUpload(MediaPath): | |||||
| result['error'] = 'le fichier est trop petit' | result['error'] = 'le fichier est trop petit' | ||||
| elif result['size'] > MAX_FILE_SIZE: | elif result['size'] > MAX_FILE_SIZE: | ||||
| result['error'] = 'le fichier est trop voluminueux' | result['error'] = 'le fichier est trop voluminueux' | ||||
| #elif not ACCEPT_FILE_TYPES.match(file['type']): | |||||
| # elif not ACCEPT_FILE_TYPES.match(file['type']): | |||||
| # file['error'] = u'les type de fichiers acceptés sont png, jpg et gif' | # file['error'] = u'les type de fichiers acceptés sont png, jpg et gif' | ||||
| else: | else: | ||||
| return True | return True | ||||
| @@ -289,80 +291,80 @@ class MediaUpload(MediaPath): | |||||
| return False | return False | ||||
| def get_file_size(self, fileobj): | def get_file_size(self, fileobj): | ||||
| fileobj.seek(0, 2) # Seek to the end of the file | |||||
| size = fileobj.tell() # Get the position of EOF | |||||
| fileobj.seek(0) # Reset the file position to the beginning | |||||
| fileobj.seek(0, 2) # Seek to the end of the file | |||||
| size = fileobj.tell() # Get the position of EOF | |||||
| fileobj.seek(0) # Reset the file position to the beginning | |||||
| return size | return size | ||||
| def thumbnailurl(self,name): | |||||
| return self.request.route_url('media_view',name='thumbnails', | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) + '/' + name | |||||
| def thumbnailurl(self, name): | |||||
| return self.request.route_url('media_view', name='thumbnails', | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) + '/' + name | |||||
| def thumbnailpath(self,name): | |||||
| def thumbnailpath(self, name): | |||||
| origin = self.mediapath(name) | origin = self.mediapath(name) | ||||
| TargetPath = os.path.join( os.path.dirname(origin), 'thumbnails', name) | |||||
| TargetPath = os.path.join(os.path.dirname(origin), 'thumbnails', name) | |||||
| if not os.path.isdir(os.path.dirname(TargetPath)): | if not os.path.isdir(os.path.dirname(TargetPath)): | ||||
| os.makedirs(os.path.dirname(TargetPath)) | |||||
| os.makedirs(os.path.dirname(TargetPath)) | |||||
| return TargetPath | return TargetPath | ||||
| def createthumbnail(self, filename): | def createthumbnail(self, filename): | ||||
| image = Image.open( self.mediapath(filename) ) | |||||
| image = Image.open(self.mediapath(filename)) | |||||
| image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | ||||
| timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | ||||
| timage.paste( | timage.paste( | ||||
| image, | image, | ||||
| ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ||||
| TargetFileName = self.thumbnailpath(filename) | TargetFileName = self.thumbnailpath(filename) | ||||
| timage.save( TargetFileName ) | |||||
| return self.thumbnailurl( os.path.basename(TargetFileName) ) | |||||
| timage.save(TargetFileName) | |||||
| return self.thumbnailurl(os.path.basename(TargetFileName)) | |||||
| def pdfthumbnail(self, filename): | def pdfthumbnail(self, filename): | ||||
| TargetFileName = self.thumbnailpath(filename) | TargetFileName = self.thumbnailpath(filename) | ||||
| Command = ["convert","./%s[0]" % self.mediapath(filename),"./%s_.jpg" % TargetFileName] | |||||
| Command = ["convert", "./%s[0]" % self.mediapath(filename), "./%s_.jpg" % TargetFileName] | |||||
| Result = subprocess.call(Command) | Result = subprocess.call(Command) | ||||
| if Result==0: | |||||
| image = Image.open( TargetFileName+"_.jpg" ) | |||||
| pdf_indicator = Image.open( "jm2l/static/img/PDF_Thumb_Stamp.png" ) | |||||
| if Result == 0: | |||||
| image = Image.open(TargetFileName + "_.jpg") | |||||
| pdf_indicator = Image.open("jm2l/static/img/PDF_Thumb_Stamp.png") | |||||
| image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | ||||
| timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | ||||
| # Add thumbnail | # Add thumbnail | ||||
| timage.paste( | timage.paste( | ||||
| image, | |||||
| image, | |||||
| ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ||||
| # Stamp with PDF file type | # Stamp with PDF file type | ||||
| timage.paste( | timage.paste( | ||||
| pdf_indicator, | pdf_indicator, | ||||
| (timage.size[0]-30, timage.size[1]-30), | |||||
| (timage.size[0] - 30, timage.size[1] - 30), | |||||
| pdf_indicator, | pdf_indicator, | ||||
| ) | |||||
| timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG') | |||||
| os.unlink(TargetFileName+"_.jpg") | |||||
| return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") ) | |||||
| ) | |||||
| timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG') | |||||
| os.unlink(TargetFileName + "_.jpg") | |||||
| return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg")) | |||||
| return self.ExtMimeIcon('application/pdf') | return self.ExtMimeIcon('application/pdf') | ||||
| def svgthumbnail(self, filename): | def svgthumbnail(self, filename): | ||||
| TargetFileName = self.thumbnailpath(filename) | TargetFileName = self.thumbnailpath(filename) | ||||
| Command = ["convert","./%s[0]" % self.mediapath(filename),"./%s_.jpg" % TargetFileName] | |||||
| Command = ["convert", "./%s[0]" % self.mediapath(filename), "./%s_.jpg" % TargetFileName] | |||||
| Result = subprocess.call(Command) | Result = subprocess.call(Command) | ||||
| if Result==0: | |||||
| image = Image.open( TargetFileName+"_.jpg" ) | |||||
| pdf_indicator = Image.open( "jm2l/static/img/svg-icon.png" ) | |||||
| if Result == 0: | |||||
| image = Image.open(TargetFileName + "_.jpg") | |||||
| pdf_indicator = Image.open("jm2l/static/img/svg-icon.png") | |||||
| image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | ||||
| timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | ||||
| # Add thumbnail | # Add thumbnail | ||||
| timage.paste( | timage.paste( | ||||
| image, | |||||
| image, | |||||
| ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ||||
| # Stamp with PDF file type | # Stamp with PDF file type | ||||
| timage.paste( | timage.paste( | ||||
| pdf_indicator, | pdf_indicator, | ||||
| (timage.size[0]-30, timage.size[1]-30), | |||||
| (timage.size[0] - 30, timage.size[1] - 30), | |||||
| pdf_indicator, | pdf_indicator, | ||||
| ) | |||||
| timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG') | |||||
| os.unlink(TargetFileName+"_.jpg") | |||||
| return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") ) | |||||
| ) | |||||
| timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG') | |||||
| os.unlink(TargetFileName + "_.jpg") | |||||
| return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg")) | |||||
| return self.ExtMimeIcon('image/svg+xml') | return self.ExtMimeIcon('image/svg+xml') | ||||
| def docthumbnail(self, filename): | def docthumbnail(self, filename): | ||||
| @@ -370,29 +372,30 @@ class MediaUpload(MediaPath): | |||||
| # let's take the thumbnail generated inside the document | # let's take the thumbnail generated inside the document | ||||
| Command = ["unzip", "-p", self.mediapath(filename), "Thumbnails/thumbnail.png"] | Command = ["unzip", "-p", self.mediapath(filename), "Thumbnails/thumbnail.png"] | ||||
| ThumbBytes = subprocess.check_output(Command) | ThumbBytes = subprocess.check_output(Command) | ||||
| image = Image.open( StringIO.StringIO(ThumbBytes) ) | |||||
| image = Image.open(StringIO.StringIO(ThumbBytes)) | |||||
| image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | ||||
| # Use the correct stamp | # Use the correct stamp | ||||
| f, ext = os.path.splitext( filename ) | |||||
| istamp = [ ('Writer','odt'), | |||||
| ('Impress','odp'), | |||||
| ('Calc','ods'), | |||||
| ('Draw','odg')] | |||||
| stampfilename = filter(lambda (x,y): ext.endswith(y), istamp) | |||||
| stamp = Image.open( "jm2l/static/img/%s-icon.png" % stampfilename[0][0]) | |||||
| f, ext = os.path.splitext(filename) | |||||
| istamp = [('Writer', 'odt'), | |||||
| ('Impress', 'odp'), | |||||
| ('Calc', 'ods'), | |||||
| ('Draw', 'odg')] | |||||
| stampfilename = filter(lambda x, y: ext.endswith(y), istamp) | |||||
| stamp = Image.open("jm2l/static/img/%s-icon.png" % stampfilename[0][0]) | |||||
| timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | ||||
| # Add thumbnail | # Add thumbnail | ||||
| timage.paste( | timage.paste( | ||||
| image, | |||||
| image, | |||||
| ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2)) | ||||
| # Stamp with PDF file type | # Stamp with PDF file type | ||||
| timage.paste( | timage.paste( | ||||
| stamp, | stamp, | ||||
| (timage.size[0]-30, timage.size[1]-30), | |||||
| (timage.size[0] - 30, timage.size[1] - 30), | |||||
| stamp, | stamp, | ||||
| ) | |||||
| timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG') | |||||
| return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") ) | |||||
| ) | |||||
| timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG') | |||||
| return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg")) | |||||
| def blendthumbnail(self, filename): | def blendthumbnail(self, filename): | ||||
| blendfile = self.mediapath(filename) | blendfile = self.mediapath(filename) | ||||
| @@ -400,18 +403,18 @@ class MediaUpload(MediaPath): | |||||
| if 0: | if 0: | ||||
| head = fileobj.read(12) | head = fileobj.read(12) | ||||
| fileobj.seek(0) | fileobj.seek(0) | ||||
| if head[:2] == b'\x1f\x8b': # gzip magic | if head[:2] == b'\x1f\x8b': # gzip magic | ||||
| import zlib | import zlib | ||||
| head = zlib.decompress(fileobj.read(), 31)[:12] | head = zlib.decompress(fileobj.read(), 31)[:12] | ||||
| fileobj.seek(0) | |||||
| fileobj.seek(0) | |||||
| buf, width, height = blend_extract_thumb(blendfile) | buf, width, height = blend_extract_thumb(blendfile) | ||||
| if buf: | if buf: | ||||
| png = write_png(buf, width, height) | png = write_png(buf, width, height) | ||||
| TargetFileName = self.thumbnailpath(filename) | TargetFileName = self.thumbnailpath(filename) | ||||
| image = Image.open(StringIO.StringIO(png)) | image = Image.open(StringIO.StringIO(png)) | ||||
| blender_indicator = Image.open( "jm2l/static/img/Blender_Thumb_Stamp.png" ) | |||||
| blender_indicator = Image.open("jm2l/static/img/Blender_Thumb_Stamp.png") | |||||
| image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS) | ||||
| timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0)) | ||||
| # Add thumbnail | # Add thumbnail | ||||
| @@ -421,24 +424,24 @@ class MediaUpload(MediaPath): | |||||
| # Stamp with Blender file type | # Stamp with Blender file type | ||||
| timage.paste( | timage.paste( | ||||
| blender_indicator, | blender_indicator, | ||||
| (timage.size[0]-30, timage.size[1]-30), | |||||
| (timage.size[0] - 30, timage.size[1] - 30), | |||||
| blender_indicator, | blender_indicator, | ||||
| ) | |||||
| timage.save( TargetFileName+".png") | |||||
| return self.thumbnailurl( os.path.basename(TargetFileName+".png") ) | |||||
| ) | |||||
| timage.save(TargetFileName + ".png") | |||||
| return self.thumbnailurl(os.path.basename(TargetFileName + ".png")) | |||||
| return self.ExtMimeIcon('application/x-blender') | return self.ExtMimeIcon('application/x-blender') | ||||
| def fileinfo(self,name): | |||||
| filename = self.mediapath(name) | |||||
| def fileinfo(self, name): | |||||
| filename = self.mediapath(name) | |||||
| f, ext = os.path.splitext(name) | f, ext = os.path.splitext(name) | ||||
| if ext!='.type' and os.path.isfile(filename): | |||||
| if ext != '.type' and os.path.isfile(filename): | |||||
| info = {} | info = {} | ||||
| info['name'] = name | info['name'] = name | ||||
| info['size'] = os.path.getsize(filename) | info['size'] = os.path.getsize(filename) | ||||
| info['url'] = self.request.route_url('media_view', | info['url'] = self.request.route_url('media_view', | ||||
| name=name, | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) | |||||
| name=name, | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) | |||||
| mime = self.get_mimetype(name) | mime = self.get_mimetype(name) | ||||
| if IMAGE_TYPES.match(mime): | if IMAGE_TYPES.match(mime): | ||||
| @@ -448,8 +451,8 @@ class MediaUpload(MediaPath): | |||||
| thumbext = ".jpg" | thumbext = ".jpg" | ||||
| if mime == "application/x-blender": | if mime == "application/x-blender": | ||||
| thumbext = ".png" | thumbext = ".png" | ||||
| if os.path.exists( thumb + thumbext ): | |||||
| info['thumbnailUrl'] = self.thumbnailurl(name)+thumbext | |||||
| if os.path.exists(thumb + thumbext): | |||||
| info['thumbnailUrl'] = self.thumbnailurl(name) + thumbext | |||||
| else: | else: | ||||
| info['thumbnailUrl'] = self.ExtMimeIcon(mime) | info['thumbnailUrl'] = self.ExtMimeIcon(mime) | ||||
| else: | else: | ||||
| @@ -457,10 +460,10 @@ class MediaUpload(MediaPath): | |||||
| if not self.display_only: | if not self.display_only: | ||||
| info['deleteType'] = DELETEMETHOD | info['deleteType'] = DELETEMETHOD | ||||
| info['deleteUrl'] = self.request.route_url('media_upload', | info['deleteUrl'] = self.request.route_url('media_upload', | ||||
| sep='', | |||||
| name='', | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) + '/' + name | |||||
| sep='', | |||||
| name='', | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) + '/' + name | |||||
| if DELETEMETHOD != 'DELETE': | if DELETEMETHOD != 'DELETE': | ||||
| info['deleteUrl'] += '&_method=DELETE' | info['deleteUrl'] += '&_method=DELETE' | ||||
| return info | return info | ||||
| @@ -488,7 +491,7 @@ class MediaUpload(MediaPath): | |||||
| n = self.fileinfo(f) | n = self.fileinfo(f) | ||||
| if n: | if n: | ||||
| filelist.append(n) | filelist.append(n) | ||||
| return { "files":filelist } | |||||
| return {"files": filelist} | |||||
| @view_config(request_method='DELETE', xhr=True, accept="application/json", renderer='json') | @view_config(request_method='DELETE', xhr=True, accept="application/json", renderer='json') | ||||
| def delete(self): | def delete(self): | ||||
| @@ -498,32 +501,32 @@ class MediaUpload(MediaPath): | |||||
| except IOError: | except IOError: | ||||
| pass | pass | ||||
| except OSError: | except OSError: | ||||
| pass | |||||
| pass | |||||
| try: | try: | ||||
| os.remove(self.thumbnailpath(filename)) | os.remove(self.thumbnailpath(filename)) | ||||
| except IOError: | except IOError: | ||||
| pass | pass | ||||
| except OSError: | |||||
| except OSError: | |||||
| pass | pass | ||||
| try: | try: | ||||
| os.remove(self.thumbnailpath(filename+".jpg")) | |||||
| os.remove(self.thumbnailpath(filename + ".jpg")) | |||||
| except IOError: | except IOError: | ||||
| pass | pass | ||||
| except OSError: | |||||
| pass | |||||
| except OSError: | |||||
| pass | |||||
| try: | try: | ||||
| os.remove(self.mediapath(filename)) | os.remove(self.mediapath(filename)) | ||||
| except IOError: | except IOError: | ||||
| return False | return False | ||||
| return True | return True | ||||
| @view_config(request_method='POST', xhr=True, accept="application/json", renderer='json') | @view_config(request_method='POST', xhr=True, accept="application/json", renderer='json') | ||||
| def post(self): | def post(self): | ||||
| if self.request.matchdict.get('_method') == "DELETE": | if self.request.matchdict.get('_method') == "DELETE": | ||||
| return self.delete() | return self.delete() | ||||
| results = [] | results = [] | ||||
| for name, fieldStorage in self.request.POST.items(): | for name, fieldStorage in self.request.POST.items(): | ||||
| if isinstance(fieldStorage,unicode): | |||||
| if isinstance(fieldStorage, unicode): | |||||
| continue | continue | ||||
| result = {} | result = {} | ||||
| result['name'] = os.path.basename(fieldStorage.filename) | result['name'] = os.path.basename(fieldStorage.filename) | ||||
| @@ -531,63 +534,64 @@ class MediaUpload(MediaPath): | |||||
| result['size'] = self.get_file_size(fieldStorage.file) | result['size'] = self.get_file_size(fieldStorage.file) | ||||
| if self.validate(result, fieldStorage.file): | if self.validate(result, fieldStorage.file): | ||||
| filename, file_extension = os.path.splitext( result['name'] ) | |||||
| local_filename = slugify( filename ) + file_extension | |||||
| filename, file_extension = os.path.splitext(result['name']) | |||||
| local_filename = slugify(filename) + file_extension | |||||
| # Keep mime-type in .type file | # Keep mime-type in .type file | ||||
| with open( self.mediapath( local_filename ) + '.type', 'w') as f: | |||||
| with open(self.mediapath(local_filename) + '.type', 'w') as f: | |||||
| f.write(result['type']) | f.write(result['type']) | ||||
| # Store uploaded file | # Store uploaded file | ||||
| fieldStorage.file.seek(0) | fieldStorage.file.seek(0) | ||||
| with open( self.mediapath( local_filename ), 'wb') as f: | |||||
| shutil.copyfileobj( fieldStorage.file , f) | |||||
| with open(self.mediapath(local_filename), 'wb') as f: | |||||
| shutil.copyfileobj(fieldStorage.file, f) | |||||
| if re.match(IMAGE_TYPES, result['type']): | if re.match(IMAGE_TYPES, result['type']): | ||||
| result['thumbnailUrl'] = self.createthumbnail(local_filename) | result['thumbnailUrl'] = self.createthumbnail(local_filename) | ||||
| elif result['type']=='application/pdf': | |||||
| elif result['type'] == 'application/pdf': | |||||
| result['thumbnailUrl'] = self.pdfthumbnail(local_filename) | result['thumbnailUrl'] = self.pdfthumbnail(local_filename) | ||||
| elif result['type']=='image/svg+xml': | |||||
| elif result['type'] == 'image/svg+xml': | |||||
| result['thumbnailUrl'] = self.svgthumbnail(local_filename) | result['thumbnailUrl'] = self.svgthumbnail(local_filename) | ||||
| elif result['type'].startswith('application/vnd'): | elif result['type'].startswith('application/vnd'): | ||||
| result['thumbnailUrl'] = self.docthumbnail(local_filename) | result['thumbnailUrl'] = self.docthumbnail(local_filename) | ||||
| elif result['type']=='application/x-blender': | |||||
| elif result['type'] == 'application/x-blender': | |||||
| result['thumbnailUrl'] = self.blendthumbnail(local_filename) | result['thumbnailUrl'] = self.blendthumbnail(local_filename) | ||||
| else: | else: | ||||
| result['thumbnailUrl'] = self.ExtMimeIcon(result['type']) | result['thumbnailUrl'] = self.ExtMimeIcon(result['type']) | ||||
| result['deleteType'] = DELETEMETHOD | result['deleteType'] = DELETEMETHOD | ||||
| result['deleteUrl'] = self.request.route_url('media_upload', | result['deleteUrl'] = self.request.route_url('media_upload', | ||||
| sep='', | |||||
| name='', | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) + '/' + local_filename | |||||
| sep='', | |||||
| name='', | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id) + '/' + local_filename | |||||
| result['url'] = self.request.route_url('media_view', | result['url'] = self.request.route_url('media_view', | ||||
| media_table=self.media_table, | |||||
| uid=self.linked_id, | |||||
| name=local_filename) | |||||
| media_table=self.media_table, | |||||
| uid=self.linked_id, | |||||
| name=local_filename) | |||||
| if DELETEMETHOD != 'DELETE': | if DELETEMETHOD != 'DELETE': | ||||
| result['deleteUrl'] += '&_method=DELETE' | result['deleteUrl'] += '&_method=DELETE' | ||||
| results.append(result) | results.append(result) | ||||
| return {"files":results} | |||||
| return {"files": results} | |||||
| @view_defaults(route_name='media_view') | @view_defaults(route_name='media_view') | ||||
| class MediaView(MediaPath): | class MediaView(MediaPath): | ||||
| def __init__(self,request): | |||||
| def __init__(self, request): | |||||
| self.request = request | self.request = request | ||||
| self.media_table = self.request.matchdict.get('media_table') | self.media_table = self.request.matchdict.get('media_table') | ||||
| self.linked_id = self.request.matchdict.get('uid') | self.linked_id = self.request.matchdict.get('uid') | ||||
| def mediapath(self,name): | |||||
| def mediapath(self, name): | |||||
| return self.get_mediapath(self.media_table, self.linked_id, name) | return self.get_mediapath(self.media_table, self.linked_id, name) | ||||
| @view_config(request_method='GET', http_cache = (EXPIRATION_TIME, {'public':True})) | |||||
| @view_config(request_method='GET', http_cache=(EXPIRATION_TIME, {'public': True})) | |||||
| def get(self): | def get(self): | ||||
| name = self.request.matchdict.get('name') | name = self.request.matchdict.get('name') | ||||
| self.request.response.content_type = self.get_mimetype(name) | self.request.response.content_type = self.get_mimetype(name) | ||||
| try: | try: | ||||
| self.request.response.body_file = open( self.mediapath(name), 'rb', 10000) | |||||
| self.request.response.body_file = open(self.mediapath(name), 'rb', 10000) | |||||
| except IOError: | except IOError: | ||||
| raise NotFound | raise NotFound | ||||
| return self.request.response | return self.request.response | ||||
| @@ -28,13 +28,14 @@ requires = [ | |||||
| 'python-magic', | 'python-magic', | ||||
| 'Pillow', | 'Pillow', | ||||
| 'pyramid_exclog', | 'pyramid_exclog', | ||||
| 'repoze.sendmail==4.1', | |||||
| 'repoze.sendmail', | |||||
| 'pyramid_mailer', | 'pyramid_mailer', | ||||
| 'apscheduler', | 'apscheduler', | ||||
| 'qrcode', | 'qrcode', | ||||
| 'reportlab', | 'reportlab', | ||||
| 'passlib', | 'passlib', | ||||
| 'argon2_cffi' | |||||
| 'argon2_cffi', | |||||
| 'paginate' | |||||
| ] | ] | ||||
| setup(name='JM2L', | setup(name='JM2L', | ||||