Migration to python 3

This commit is contained in:
2020-07-26 17:38:55 +02:00
parent b6af9a0e08
commit ad9883ae09
37 changed files with 1690 additions and 1567 deletions
+2 -2
View File
@@ -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 ])
+1 -1
View File
@@ -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
+101 -87
View File
@@ -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.setFillColorRGB(.83, 0, .33)
logoobject.setTextOrigin(OffX+5, OffY+17) 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) canvas.setStrokeColorRGB(0.5, 0.5, 0.5)
Logos = filter(lambda x:x.ThumbLinks, DispUser.tiers)[:3] 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[1] = {0: (1. / 2, 1. / 2)}
DicPos[2] = { 0:(1./3, 1./2), 1:(2./3, 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[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), DicPos[4] = {0: (1. / 3, 1. / 4), 1: (2. / 3, 1. / 4), 2: (1. / 3, 3. / 4),
3:(2./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), 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) } 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), 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) } 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), 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), 3: (1. / 8, 3. / 4), 4: (3. / 8, 3. / 4), 5: (5. / 8, 3. / 4),
6:(7./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), 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), 3: (7. / 8, 1. / 4), 4: (1. / 8, 3. / 4), 5: (3. / 8, 3. / 4),
6:(5./8, 3./4), 7:(7./8, 3./4) } 6: (5. / 8, 3. / 4), 7: (7. / 8, 3. / 4)}
# draw overall border # draw overall border
# canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True) # 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) ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
PosX = OffX+StartX + DicPos[len(Logos)][num][0] * MaxX - (ICONSIZE+Border)/2 PosX = OffX + StartX + DicPos[len(Logos)][num][0] * MaxX - (ICONSIZE + Border) / 2
PosY = OffY+StartY + DicPos[len(Logos)][num][1] * MaxY - (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 size = ICONSIZE * 1.5
canvas.drawImage(ImagePath, canvas.drawImage(ImagePath,
PosX, PosY, size, size,\ PosX, PosY, size, size,
preserveAspectRatio=True, preserveAspectRatio=True,
anchor='c', anchor='c',
mask='auto' mask='auto'
) )
# draw icon border # draw icon border
# canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True) # canvas.roundRect(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,66 +110,67 @@ 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.setFillColorRGB(.83, 0, .33)
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
c.setFillColorRGB(1,1,1) c.setFillColorRGB(1, 1, 1)
c.setFont('Liberation', 30) c.setFont('Liberation', 30)
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "STAFF") c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "STAFF")
elif DispUser.is_Intervenant: elif DispUser.is_Intervenant:
# Intervenant # Intervenant
c.setFillColorRGB(.21,.67,.78) c.setFillColorRGB(.21, .67, .78)
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
c.setFillColorRGB(1,1,1) c.setFillColorRGB(1, 1, 1)
c.setFont('Liberation', 30) c.setFont('Liberation', 30)
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Intervenant") c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Intervenant")
elif DispUser.is_crew: elif DispUser.is_crew:
# Benevole # Benevole
c.setFillColorRGB(.18,.76,.23) c.setFillColorRGB(.18, .76, .23)
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
c.setFillColorRGB(1,1,1) c.setFillColorRGB(1, 1, 1)
c.setFont('Liberation', 30) c.setFont('Liberation', 30)
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Bénévole") c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT - 24, "Bénévole")
else: else:
# Visiteur # Visiteur
c.setFillColorRGB(.8,.8,.8) c.setFillColorRGB(.8, .8, .8)
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0) c.rect(OffX - 3, OffY + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
c.setFillColorRGB(1,1,1) c.setFillColorRGB(1, 1, 1)
c.setFont('Liberation', 30) c.setFont('Liberation', 30)
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Visiteur") c.drawCentredString(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.setStrokeColorRGB(0, 0, 0)
c.setFillColorRGB(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.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 0 * mm, "%s" % DispUser.prenom)
#c.setFont('Courier', 17) # c.setFont('Courier', 17)
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom ) c.drawCentredString(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.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 4 * mm, "%s" % DispUser.prenom)
#c.setFont('Courier', 17) # c.setFont('Courier', 17)
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom ) c.drawCentredString(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 ) c.drawCentredString(OffX + WIDTH / 2, OffY + HEIGHT / 2 + 10 * mm, "%s" % DispUser.pseudo)
# Put QR code to user profile #  Put QR code to user profile
c.drawInlineImage(QRCode(DispUser), \ c.drawInlineImage(QRCode(DispUser), \
OffX+WIDTH - 20 * mm -5, OffY+5, \ OffX + WIDTH - 20 * mm - 5, OffY + 5, \
20 * mm, 20 * mm, \ 20 * mm, 20 * mm, \
preserveAspectRatio=True, \ preserveAspectRatio=True, \
anchor='s') anchor='s')
@@ -165,11 +178,11 @@ def one_badge(c, DispUser, Offset=(0,0)):
Tiers_Logo(c, DispUser, None, Offset) Tiers_Logo(c, DispUser, None, Offset)
@view_config(route_name='badge_user', http_cache = (EXPIRATION_TIME, {'public':True})) @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)
@@ -181,14 +194,14 @@ def badge_user(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()
out_img = StringIO.StringIO() out_img = StringIO()
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) ) c = canvas.Canvas(pdf, pagesize=(WIDTH, HEIGHT))
c.translate(mm, mm) c.translate(mm, mm)
# Feed some metadata # Feed some metadata
@@ -198,27 +211,28 @@ def badge_user(request):
c.saveState() c.saveState()
one_badge(c, DispUser) one_badge(c, DispUser)
OutPDF = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf')
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')
# Let's generate a png file for website
with open( OutPDF ,'wb') as pdff:
pdff.write(pdf.read())
Command = ["convert","-density","150x150", OutPDF, OutPNG] OutPNG = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png')
#  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: with open("./%s" % OutPNG, 'r') as pngfile:
out_img.write(pngfile.read()) 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,7 +248,7 @@ 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))
@@ -243,23 +257,23 @@ def planche_badge(request):
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: if num % 8 == 7:
t=num+1 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')
+4 -1
View File
@@ -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
View File
@@ -1 +1 @@
CurrentYear = 2018 CurrentYear = 2020
+31 -28
View File
@@ -4,18 +4,20 @@ 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)\ self.Sejour = DBSession.query(Sejour) \
.filter(Sejour.user_id==self.Me.uid)\ .filter(Sejour.user_id == self.Me.uid) \
.filter(Sejour.for_year==self.CurrentEventYear.year_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):
@@ -33,32 +35,32 @@ class Sejour_helpers(DummySejour):
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 departure = True
myDayRange = xrange(3) 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') ArrDate = datetime.strftime(self.Sejour.arrival_time, "%d %B %Y")
DepDate = datetime.strftime(self.Sejour.depart_time,"%d %B %Y").decode('utf-8') 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') ArrDate = datetime.strftime(self.CurrentEventYear.start_time, "%d %B %Y")
DepDate = datetime.strftime( self.CurrentEventYear.end_time,"%d %B %Y" ).decode('utf-8') 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") DayName = datetime.strftime(TmpDay, "%A")
DayNum = datetime.strftime(TmpDay,"%d/%m/%y") DayNum = datetime.strftime(TmpDay, "%d/%m/%y")
DayString = datetime.strftime(TmpDay,"%d %B %Y").decode('utf-8') DayString = datetime.strftime(TmpDay, "%d %B %Y")
if arrival and ArrDate==DayString: 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, ""))
@@ -69,19 +71,19 @@ class Sejour_helpers(DummySejour):
TabResult = list() TabResult = list()
if self.Sejour: if self.Sejour:
ArrTime = datetime.strftime(self.Sejour.arrival_time,"%H:%M") ArrTime = datetime.strftime(self.Sejour.arrival_time, "%H:%M")
DepTime = datetime.strftime(self.Sejour.depart_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: if typedate == "arrival" and StrTime == ArrTime:
TabResult.append( (StrTime, DispTime, 'selected="selected"') ) TabResult.append((StrTime, DispTime, 'selected="selected"'))
elif typedate == "departure" and StrTime==DepTime: elif typedate == "departure" and StrTime == DepTime:
TabResult.append( (StrTime, DispTime, 'selected="selected"') ) 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):
@@ -132,7 +135,7 @@ class Orga_helpers(DummySejour):
] ]
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\""
@@ -144,8 +147,8 @@ class Orga_helpers(DummySejour):
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)): for num in range(0, len(self.Orga_tasks)):
curs = 2**num curs = 2 ** num
if self.Sejour.orga_part & curs == curs: if self.Sejour.orga_part & curs == curs:
ListOrga.append(self.Orga_tasks[num]) ListOrga.append(self.Orga_tasks[num])
return ListOrga return ListOrga
+152 -125
View File
@@ -15,29 +15,39 @@ from sqlalchemy import (
Enum, Enum,
Boolean, Boolean,
ForeignKey ForeignKey
) )
from slugify import slugify from slugify import slugify
from webhelpers.text import urlify # from webhelpers.text import urlify
from webhelpers.paginate import PageURL_WebOb, Page from paginate import Page # PageURL_WebOb
from webhelpers.date import time_ago_in_words
from webhelpers2.date import time_ago_in_words
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import ( from sqlalchemy.orm import (
scoped_session, scoped_session,
sessionmaker sessionmaker
) )
from zope.sqlalchemy import ZopeTransactionExtension # from zope.sqlalchemy import ZopeTransactionExtension
from zope.sqlalchemy import register
from jm2l.const import CurrentYear from jm2l.const import CurrentYear
from passlib.hash import argon2 from passlib.hash import argon2
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
def urlify(in_string, in_string_length):
return ''.join('%20' if c == ' ' else c for c in in_string[:in_string_length])
DBSession = scoped_session(sessionmaker(autoflush=False))
register(DBSession)
# DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base() Base = declarative_base()
class TasksArea(Base): class TasksArea(Base):
__tablename__ = 'staff_tasks_area' __tablename__ = 'staff_tasks_area'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
@@ -49,40 +59,43 @@ class TasksArea(Base):
def by_id(cls, uid): def by_id(cls, uid):
return DBSession.query(cls).filter(cls.uid == uid).first() return DBSession.query(cls).filter(cls.uid == uid).first()
class Tasks(Base): class Tasks(Base):
__tablename__ = 'staff_tasks' __tablename__ = 'staff_tasks'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
area_uid = Column(Integer, ForeignKey('staff_tasks_area.uid') ) area_uid = Column(Integer, ForeignKey('staff_tasks_area.uid'))
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear) year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
due_date = Column(DateTime, default=None) due_date = Column(DateTime, default=None)
closed_by = Column(Integer, ForeignKey('users.uid') ) closed_by = Column(Integer, ForeignKey('users.uid'))
closed_date = Column(DateTime, default=None) closed_date = Column(DateTime, default=None)
closed = Column(Integer, default=0) closed = Column(Integer, default=0)
name = Column(Unicode(80)) name = Column(Unicode(80))
description = Column(UnicodeText) description = Column(UnicodeText)
area = relationship(TasksArea, backref=backref("tasks") ) area = relationship(TasksArea, backref=backref("tasks"))
assignee = relationship('User', backref=backref("task_assoc") ) assignee = relationship('User', backref=backref("task_assoc"))
@classmethod @classmethod
def by_id(cls, uid): def by_id(cls, uid):
return DBSession.query(cls).filter(cls.uid == uid).first() return DBSession.query(cls).filter(cls.uid == uid).first()
class User_Event(Base): class User_Event(Base):
""" Créer le lien entre la personne et l' évenement en fonction de l'année""" """ Créer le lien entre la personne et l' évenement en fonction de l'année"""
__tablename__ = 'user_event_link' __tablename__ = 'user_event_link'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
event_uid = Column(Integer, ForeignKey('events.uid') ) event_uid = Column(Integer, ForeignKey('events.uid'))
#, primary_key=True) # , primary_key=True)
# #
user_uid = Column(Integer, ForeignKey('users.uid') ) user_uid = Column(Integer, ForeignKey('users.uid'))
#, primary_key=True) # , primary_key=True)
# #
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear) year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
role = Column(Unicode(80)) role = Column(Unicode(80))
# Define some relation # Define some relation
#user = relationship('User', backref=backref("events_assoc") ) # user = relationship('User', backref=backref("events_assoc") )
#event = relationship('events', backref=backref("users_assoc") ) # event = relationship('events', backref=backref("users_assoc") )
class JM2L_Year(Base): class JM2L_Year(Base):
__tablename__ = 'jm2l_year' __tablename__ = 'jm2l_year'
@@ -102,22 +115,22 @@ class JM2L_Year(Base):
.filter(JM2L_Year.start_time == .filter(JM2L_Year.start_time ==
DBSession.query(func.max(JM2L_Year.start_time)) DBSession.query(func.max(JM2L_Year.start_time))
).one() ).one()
return last_record.start_time.strftime("%A %d %B %Y").decode('utf-8') return last_record.start_time.strftime("%A %d %B %Y") # .decode('utf-8')
@property @property
def AvailableTimeSlots(self, TimeStep=30): def AvailableTimeSlots(self, TimeStep=30):
Available = self.end_time - self.start_time Available = self.end_time - self.start_time
NbMinutes = Available.total_seconds()/60 NbMinutes = Available.total_seconds() / 60
NbSteps = NbMinutes/TimeStep NbSteps = NbMinutes / TimeStep
# Create the range of date each 30min # Create the range of date each 30min
date_list = [self.start_time + datetime.timedelta(minutes=TimeStep*x) for x in range(0, int(NbSteps))] date_list = [self.start_time + datetime.timedelta(minutes=TimeStep * x) for x in range(0, int(NbSteps))]
# Remove out of range datetime # Remove out of range datetime
# Remove hours > 19h # Remove hours > 19h
date_list = filter(lambda x:x.hour < 19, date_list) date_list = filter(lambda x: x.hour < 19, date_list)
# Remove hours < 10h # Remove hours < 10h
date_list = filter(lambda x:x.hour >= 10, date_list) date_list = filter(lambda x: x.hour >= 10, date_list)
# Remove 12h < hours < 13h # Remove 12h < hours < 13h
date_list = filter(lambda x: x.hour<12 or x.hour>=13, date_list) date_list = filter(lambda x: x.hour < 12 or x.hour >= 13, date_list)
return date_list return date_list
@property @property
@@ -125,6 +138,7 @@ class JM2L_Year(Base):
from .upload import MediaPath from .upload import MediaPath
return sorted(MediaPath().get_all('presse', self.year_uid)) return sorted(MediaPath().get_all('presse', self.year_uid))
class User(Base): class User(Base):
__tablename__ = 'users' __tablename__ = 'users'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
@@ -152,8 +166,8 @@ class User(Base):
wifi_pass = Column(Unicode(80), nullable=True) wifi_pass = Column(Unicode(80), nullable=True)
# relations # relations
tiers = relationship('Tiers', secondary='user_tiers_link' ) tiers = relationship('Tiers', secondary='user_tiers_link')
events = relationship('Event', secondary='user_event_link' ) events = relationship('Event', secondary='user_event_link')
tiersship = relationship('User_Tiers', backref="matching_users") tiersship = relationship('User_Tiers', backref="matching_users")
@classmethod @classmethod
@@ -179,7 +193,7 @@ class User(Base):
@classmethod @classmethod
def by_hash(cls, tsthash): def by_hash(cls, tsthash):
for u in DBSession.query(cls): for u in DBSession.query(cls):
if u.my_hash==tsthash: if u.my_hash == tsthash:
return u return u
return None return None
@@ -187,53 +201,51 @@ class User(Base):
def is_Intervenant(self): def is_Intervenant(self):
""" This property will return if User do an event on specified year """ """ This property will return if User do an event on specified year """
return DBSession.query(Event).join(User_Event) \ return DBSession.query(Event).join(User_Event) \
.filter(User_Event.user_uid==self.uid) \ .filter(User_Event.user_uid == self.uid) \
.filter(Event.for_year==CurrentYear).count() .filter(Event.for_year == CurrentYear).count()
def is_IntervenantOnYear(self, year=CurrentYear): def is_IntervenantOnYear(self, year=CurrentYear):
""" This property will return if User do an event on specified year """ """ This property will return if User do an event on specified year """
return DBSession.query(Event).join(User_Event) \ return DBSession.query(Event).join(User_Event) \
.filter(User_Event.user_uid==self.uid) \ .filter(User_Event.user_uid == self.uid) \
.filter(Event.for_year==year).count() .filter(Event.for_year == year).count()
@property @property
def is_crew(self, year=CurrentYear): def is_crew(self, year=CurrentYear):
""" This property will return if User subscribe orga task on specified year """ """ This property will return if User subscribe orga task on specified year """
orga_checked = DBSession.query(User, Sejour.orga_part)\ orga_checked = DBSession.query(User, Sejour.orga_part) \
.outerjoin(Sejour) \ .outerjoin(Sejour) \
.filter(Sejour.for_year == year)\ .filter(Sejour.for_year == year) \
.filter(User.uid == self.uid).first() .filter(User.uid == self.uid).first()
if orga_checked: if orga_checked:
return orga_checked return orga_checked
else: else:
return False return False
def year_events(self, EventType='All', year=CurrentYear): def year_events(self, EventType='All', year=CurrentYear):
if EventType=='All': if EventType == 'All':
return filter(lambda e: e.for_year==year, self.events) return list(filter(lambda e: e.for_year == year, self.events))
else: else:
return filter(lambda e: e.for_year==year and e.event_type==EventType, self.events) return list(filter(lambda e: e.for_year == year and e.event_type == EventType, self.events))
@property @property
def my_hash(self): def my_hash(self):
m = hashlib.sha1() m = hashlib.sha1()
m.update("Nobody inspects ") m.update("Nobody inspects ".encode('utf-8'))
if self.nom: if self.nom:
m.update(unicode.encode(self.nom,'utf8')) m.update(self.nom.encode('utf-8')) # unicode.encode(self.nom, 'utf8'))
if self.pseudo: if self.pseudo:
m.update(unicode.encode(self.pseudo,'utf8')) m.update(self.pseudo.encode('utf-8')) # unicode.encode(self.pseudo, 'utf8'))
if self.prenom: if self.prenom:
m.update(unicode.encode(self.prenom,'utf8')) m.update(self.prenom.encode('utf-8')) # unicode.encode(self.prenom, 'utf8'))
m.update(" the spammish repetition") m.update(" the spammish repetition".encode('utf-8'))
return m.hexdigest() return m.hexdigest()
@property @property
def Photos(self): def Photos(self):
return DBSession.query(Media.filename) \ return DBSession.query(Media.filename) \
.filter(Media.media_table=='users') \ .filter(Media.media_table == 'users') \
.filter(Media.media_type=='Image') \ .filter(Media.media_type == 'Image') \
.filter(Media.link_id == self.user_id).all() .filter(Media.link_id == self.user_id).all()
@property @property
@@ -253,6 +265,7 @@ class User(Base):
return argon2.verify(password, self.password) return argon2.verify(password, self.password)
class TiersOpt(Base): class TiersOpt(Base):
__tablename__ = 'tiers_opt' __tablename__ = 'tiers_opt'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
@@ -270,21 +283,22 @@ class TiersOpt(Base):
@classmethod @classmethod
def get_entity_type(cls): def get_entity_type(cls):
return DBSession.query(cls, func.count(Tiers.ent_type).label('count'))\ return DBSession.query(cls, func.count(Tiers.ent_type).label('count')) \
.outerjoin(Tiers)\ .outerjoin(Tiers) \
.group_by(cls.entity_type).all() .group_by(cls.entity_type).all()
@classmethod @classmethod
def get_entity_sub_type(cls, entity_type): def get_entity_sub_type(cls, entity_type):
return DBSession.query(cls, func.count(Tiers.ent_type).label('count'))\ return DBSession.query(cls, func.count(Tiers.ent_type).label('count')) \
.outerjoin(Tiers)\ .outerjoin(Tiers) \
.filter(cls.entity_type == entity_type)\ .filter(cls.entity_type == entity_type) \
.group_by(cls.entity_subtype).all() .group_by(cls.entity_subtype).all()
@classmethod @classmethod
def by_id(cls, uid): def by_id(cls, uid):
return DBSession.query(cls).filter(cls.uid == uid).first() return DBSession.query(cls).filter(cls.uid == uid).first()
class Tiers(Base): class Tiers(Base):
__tablename__ = 'tiers' __tablename__ = 'tiers'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
@@ -298,14 +312,14 @@ class Tiers(Base):
last_change = Column(DateTime, default=datetime.datetime.now) last_change = Column(DateTime, default=datetime.datetime.now)
# relations # relations
ent_type = relationship('TiersOpt') ent_type = relationship('TiersOpt')
#members = relationship('User', secondary='user_tiers_link' ) # members = relationship('User', secondary='user_tiers_link' )
members = relationship(User, members = relationship(User,
secondary='user_tiers_link', secondary='user_tiers_link',
backref=backref('associate', uselist=False), backref=backref('associate', uselist=False),
lazy='dynamic') lazy='dynamic')
creator_id = Column(Integer) creator_id = Column(Integer)
membership = relationship('User_Tiers', backref="matching_tiers") membership = relationship('User_Tiers', backref="matching_tiers")
roles = relationship('Role_Tiers', backref="roles_tiers") #secondary='role_tiers_link' ) roles = relationship('Role_Tiers', backref="roles_tiers") # secondary='role_tiers_link' )
@classmethod @classmethod
def by_id(cls, uid): def by_id(cls, uid):
@@ -317,7 +331,7 @@ class Tiers(Base):
@property @property
def get_entity_type(self): def get_entity_type(self):
return DBSession.query(TiersOpt)\ return DBSession.query(TiersOpt) \
.filter(TiersOpt.uid == self.tiers_type).first() .filter(TiersOpt.uid == self.tiers_type).first()
@property @property
@@ -330,8 +344,8 @@ class Tiers(Base):
@property @property
def DocLinks(self): def DocLinks(self):
from .upload import MediaPath from .upload import MediaPath
return zip( sorted( MediaPath().get_list('tiers', self.uid, 'Other') ), return zip(sorted(MediaPath().get_list('tiers', self.uid, 'Other')),
sorted( MediaPath().get_thumb('tiers', self.uid, 'Other') ) sorted(MediaPath().get_thumb('tiers', self.uid, 'Other'))
) )
@property @property
@@ -344,32 +358,35 @@ class Tiers(Base):
from .upload import MediaPath from .upload import MediaPath
return MediaPath().get_thumb('tiers', self.uid) return MediaPath().get_thumb('tiers', self.uid)
class Role_Tiers(Base): class Role_Tiers(Base):
""" Créer le lien entre le tiers et son rôle dans l'évenement en fonction de l'année""" """ Créer le lien entre le tiers et son rôle dans l'évenement en fonction de l'année"""
__tablename__ = 'role_tiers_link' __tablename__ = 'role_tiers_link'
uid_role = Column(Integer, primary_key=True) uid_role = Column(Integer, primary_key=True)
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear) year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
tiers_uid = Column(Integer, ForeignKey('tiers.uid')) tiers_uid = Column(Integer, ForeignKey('tiers.uid'))
tiers = relationship(Tiers, backref=backref("roles_assoc") ) tiers = relationship(Tiers, backref=backref("roles_assoc"))
tiers_role = Column(Enum('Exposant', 'Sponsor', 'Donateur')) tiers_role = Column(Enum('Exposant', 'Sponsor', 'Donateur'))
event_uid = Column(Integer, default=None) # Optionnal link with Event event_uid = Column(Integer, default=None) # Optionnal link with Event
class User_Tiers(Base): class User_Tiers(Base):
""" Créer le lien entre la personne et le tiers en fonction de l'année""" """ Créer le lien entre la personne et le tiers en fonction de l'année"""
__tablename__ = 'user_tiers_link' __tablename__ = 'user_tiers_link'
uid_tiers = Column(Integer, primary_key=True) uid_tiers = Column(Integer, primary_key=True)
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear) year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
tiers_uid = Column(Integer, ForeignKey('tiers.uid')) tiers_uid = Column(Integer, ForeignKey('tiers.uid'))
tiers = relationship(Tiers, backref=backref("users_assoc") ) tiers = relationship(Tiers, backref=backref("users_assoc"))
user_uid = Column(Integer, ForeignKey('users.uid')) user_uid = Column(Integer, ForeignKey('users.uid'))
user = relationship(User, backref=backref("tiers_assoc") ) user = relationship(User, backref=backref("tiers_assoc"))
role = Column(Unicode(80)) role = Column(Unicode(80))
class Media(Base): class Media(Base):
__tablename__ = 'medias' __tablename__ = 'medias'
media_id = Column(Integer, primary_key=True) media_id = Column(Integer, primary_key=True)
for_year = Column(Integer, ForeignKey('jm2l_year.year_uid')) for_year = Column(Integer, ForeignKey('jm2l_year.year_uid'))
media_table = Column(Enum('users', 'tiers', 'place', 'salle', 'RIB', 'Justif', 'event' )) media_table = Column(Enum('users', 'tiers', 'place', 'salle', 'RIB', 'Justif', 'event'))
media_type = Column(Enum('Image', 'Video', 'Pres', 'Document')) media_type = Column(Enum('Image', 'Video', 'Pres', 'Document'))
link_id = Column(Integer) link_id = Column(Integer)
mime_type = Column(Unicode(20)) mime_type = Column(Unicode(20))
@@ -382,9 +399,10 @@ class Media(Base):
@property @property
def get_path(self): def get_path(self):
#return '/upload/%s/%s/%s' % (self.media_type, self.media_table, self.filename) # return '/upload/%s/%s/%s' % (self.media_type, self.media_table, self.filename)
return '/resources/%s/%s/%s' % (self.for_year, self.media_type, self.filename) return '/resources/%s/%s/%s' % (self.for_year, self.media_type, self.filename)
class SallePhy(Base): class SallePhy(Base):
""" Représente une salle dans les locaux """ """ Représente une salle dans les locaux """
__tablename__ = 'phy_salle' __tablename__ = 'phy_salle'
@@ -403,6 +421,7 @@ class SallePhy(Base):
from .upload import MediaPath from .upload import MediaPath
return MediaPath().get_list('salle', self.uid, 'Image') return MediaPath().get_list('salle', self.uid, 'Image')
class Salles(Base): class Salles(Base):
__tablename__ = 'salle' __tablename__ = 'salle'
salle_id = Column(Integer, primary_key=True) salle_id = Column(Integer, primary_key=True)
@@ -415,10 +434,12 @@ class Salles(Base):
last_change = Column(DateTime, default=datetime.datetime.now) last_change = Column(DateTime, default=datetime.datetime.now)
phy = relationship(SallePhy) phy = relationship(SallePhy)
@classmethod @classmethod
def by_id(cls, uid): def by_id(cls, uid):
return DBSession.query(cls).filter(cls.salle_id == uid).first() return DBSession.query(cls).filter(cls.salle_id == uid).first()
class Place(Base): class Place(Base):
__tablename__ = 'place' __tablename__ = 'place'
place_id = Column(Integer, primary_key=True) place_id = Column(Integer, primary_key=True)
@@ -448,7 +469,8 @@ class Place(Base):
if All: if All:
return DBSession.query(cls).all() return DBSession.query(cls).all()
else: else:
return DBSession.query(cls).filter(cls.usage==True).all() return DBSession.query(cls).filter(cls.usage == True).all()
class Itineraire(Base): class Itineraire(Base):
__tablename__ = 'itineraire' __tablename__ = 'itineraire'
@@ -473,6 +495,7 @@ class Itineraire(Base):
start = relationship(Place, foreign_keys=[start_place]) start = relationship(Place, foreign_keys=[start_place])
arrival = relationship(Place, foreign_keys=[arrival_place]) arrival = relationship(Place, foreign_keys=[arrival_place])
class Exchange_Cat(Base): class Exchange_Cat(Base):
__tablename__ = 'exchange_category' __tablename__ = 'exchange_category'
cat_id = Column(Integer, primary_key=True) cat_id = Column(Integer, primary_key=True)
@@ -480,6 +503,7 @@ class Exchange_Cat(Base):
exch_subtype = Column(Unicode(80)) exch_subtype = Column(Unicode(80))
description = Column(UnicodeText) description = Column(UnicodeText)
class Exchange(Base): class Exchange(Base):
__tablename__ = 'exchanges' __tablename__ = 'exchanges'
exch_id = Column(Integer, primary_key=True) exch_id = Column(Integer, primary_key=True)
@@ -516,44 +540,44 @@ class Exchange(Base):
@classmethod @classmethod
def get_counters(cls): def get_counters(cls):
return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id))\ return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id)) \
.filter(cls.for_year==CurrentYear)\ .filter(cls.for_year == CurrentYear) \
.group_by(cls.exch_state, cls.exch_type, cls.exch_done) .group_by(cls.exch_state, cls.exch_type, cls.exch_done)
@classmethod @classmethod
def get_my_counters(cls, uid): def get_my_counters(cls, uid):
return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id))\ return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id)) \
.filter(cls.for_year==CurrentYear)\ .filter(cls.for_year == CurrentYear) \
.filter( or_(cls.asker_id==uid, cls.provider_id==uid) )\ .filter(or_(cls.asker_id == uid, cls.provider_id == uid)) \
.group_by(cls.exch_state, cls.exch_type, cls.exch_done) .group_by(cls.exch_state, cls.exch_type, cls.exch_done)
@classmethod @classmethod
def get_overview(cls, uid): def get_overview(cls, uid):
# Build a Dic with all exchange to save database access # Build a Dic with all exchange to save database access
DicResult= {} DicResult = {}
for extype in ['F','C','H','M']: for extype in ['F', 'C', 'H', 'M']:
DicResult[extype] = {} DicResult[extype] = {}
for exstate in ['Ask','Proposal','Missing','Agree']: for exstate in ['Ask', 'Proposal', 'Missing', 'Agree']:
DicResult[extype][exstate]=[] DicResult[extype][exstate] = []
DicResult[extype]['Counters']={'AllAsk':0, 'AllProp':0, 'AllAgree':0} DicResult[extype]['Counters'] = {'AllAsk': 0, 'AllProp': 0, 'AllAgree': 0}
Query = DBSession.query(cls)\ Query = DBSession.query(cls) \
.filter(cls.for_year==CurrentYear)\ .filter(cls.for_year == CurrentYear) \
.order_by(cls.start_time).all() .order_by(cls.start_time).all()
for item in Query: for item in Query:
if item.exch_done: if item.exch_done:
DicResult[item.exch_type]['Counters']['AllAgree']+=1 DicResult[item.exch_type]['Counters']['AllAgree'] += 1
if item.exch_state=='Ask': if item.exch_state == 'Ask':
DicResult[item.exch_type]['Counters']['AllAsk']+=1 DicResult[item.exch_type]['Counters']['AllAsk'] += 1
if item.exch_state=='Proposal': if item.exch_state == 'Proposal':
DicResult[item.exch_type]['Counters']['AllProp']+=1 DicResult[item.exch_type]['Counters']['AllProp'] += 1
if item.asker_id==uid or item.provider_id==uid: if item.asker_id == uid or item.provider_id == uid:
if item.asker_id==uid and item.exch_state=='Ask': if item.asker_id == uid and item.exch_state == 'Ask':
DicResult[item.exch_type]['Ask'].append(item) DicResult[item.exch_type]['Ask'].append(item)
if item.provider_id==uid and item.exch_state=='Ask': if item.provider_id == uid and item.exch_state == 'Ask':
DicResult[item.exch_type]['Proposal'].append(item) DicResult[item.exch_type]['Proposal'].append(item)
if item.asker_id==uid and item.exch_state=='Proposal': if item.asker_id == uid and item.exch_state == 'Proposal':
DicResult[item.exch_type]['Ask'].append(item) DicResult[item.exch_type]['Ask'].append(item)
if item.provider_id==uid and item.exch_state=='Proposal': if item.provider_id == uid and item.exch_state == 'Proposal':
DicResult[item.exch_type]['Proposal'].append(item) DicResult[item.exch_type]['Proposal'].append(item)
if item.exch_done: if item.exch_done:
DicResult[item.exch_type]['Agree'].append(item) DicResult[item.exch_type]['Agree'].append(item)
@@ -564,28 +588,29 @@ class Exchange(Base):
@classmethod @classmethod
def get_pub_list(cls, exch_type): def get_pub_list(cls, exch_type):
return DBSession.query(cls).filter(cls.for_year==CurrentYear and cls.exch_state in ['Ask','Proposal'])\ return DBSession.query(cls).filter(cls.for_year == CurrentYear and cls.exch_state in ['Ask', 'Proposal']) \
.filter(cls.exch_type=='%s' % exch_type)\ .filter(cls.exch_type == '%s' % exch_type) \
.filter(cls.exch_done==False)\ .filter(cls.exch_done == False) \
.all() .all()
@classmethod @classmethod
def get_my_list(cls, uid, exch_type): def get_my_list(cls, uid, exch_type):
DicResult = {} DicResult = {}
DicResult['Ask']=DBSession.query(cls)\ DicResult['Ask'] = DBSession.query(cls) \
.filter(cls.for_year==CurrentYear)\ .filter(cls.for_year == CurrentYear) \
.filter( or_(cls.asker_id==uid, cls.provider_id==uid) )\ .filter(or_(cls.asker_id == uid, cls.provider_id == uid)) \
.filter(cls.exch_type=='%s' % exch_type)\ .filter(cls.exch_type == '%s' % exch_type) \
.filter(cls.exch_state=='Ask')\ .filter(cls.exch_state == 'Ask') \
.order_by(cls.start_time).all() .order_by(cls.start_time).all()
DicResult['Proposal']=DBSession.query(cls)\ DicResult['Proposal'] = DBSession.query(cls) \
.filter(cls.for_year==CurrentYear)\ .filter(cls.for_year == CurrentYear) \
.filter( or_(cls.asker_id==uid, cls.provider_id==uid) )\ .filter(or_(cls.asker_id == uid, cls.provider_id == uid)) \
.filter(cls.exch_type=='%s' % exch_type)\ .filter(cls.exch_type == '%s' % exch_type) \
.filter(cls.exch_state=='Proposal')\ .filter(cls.exch_state == 'Proposal') \
.order_by(cls.start_time).all() .order_by(cls.start_time).all()
return DicResult return DicResult
class Sejour(Base): class Sejour(Base):
__tablename__ = 'sejour' __tablename__ = 'sejour'
sej_id = Column(Integer, primary_key=True) sej_id = Column(Integer, primary_key=True)
@@ -609,11 +634,12 @@ class Sejour(Base):
@classmethod @classmethod
def by_user(cls, uid, year): def by_user(cls, uid, year):
return DBSession.query(cls)\ return DBSession.query(cls) \
.filter(cls.user_id == uid)\ .filter(cls.user_id == uid) \
.filter(cls.for_year == year)\ .filter(cls.for_year == year) \
.first() .first()
class Event(Base): class Event(Base):
__tablename__ = 'events' __tablename__ = 'events'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
@@ -637,26 +663,25 @@ class Event(Base):
@classmethod @classmethod
def by_id(cls, uid): def by_id(cls, uid):
return DBSession.query(cls)\ return DBSession.query(cls) \
.filter(cls.uid == uid).first() .filter(cls.uid == uid).first()
@classmethod @classmethod
def by_slug(cls, slug, year=None): def by_slug(cls, slug, year=None):
if not year is None: if not year is None:
return DBSession.query(cls)\ return DBSession.query(cls) \
.filter(cls.for_year==year)\ .filter(cls.for_year == year) \
.filter(cls.slug == slug).first() .filter(cls.slug == slug).first()
else: else:
return DBSession.query(cls)\ return DBSession.query(cls) \
.filter(cls.slug == slug).first() .filter(cls.slug == slug).first()
def get_linked_tiers(self): def get_linked_tiers(self):
ListLink = DBSession.query(Role_Tiers.tiers_uid) \ ListLink = DBSession.query(Role_Tiers.tiers_uid) \
.filter(Role_Tiers.year_uid==self.for_year) \ .filter(Role_Tiers.year_uid == self.for_year) \
.filter(Role_Tiers.tiers_role=="Exposant") \ .filter(Role_Tiers.tiers_role == "Exposant") \
.filter(Role_Tiers.event_uid==self.uid) .filter(Role_Tiers.event_uid == self.uid)
return DBSession.query(Tiers).filter( Tiers.uid.in_( ListLink ) ) return DBSession.query(Tiers).filter(Tiers.uid.in_(ListLink))
@property @property
def video(self): def video(self):
@@ -676,6 +701,7 @@ class Event(Base):
def created_in_words(self): def created_in_words(self):
return time_ago_in_words(self.created) return time_ago_in_words(self.created)
class Entry(Base): class Entry(Base):
__tablename__ = 'entries' __tablename__ = 'entries'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
@@ -706,7 +732,8 @@ class Entry(Base):
page_url = PageURL_WebOb(request) page_url = PageURL_WebOb(request)
return Page(Entry.all(), page, url=page_url, items_per_page=5) return Page(Entry.all(), page, url=page_url, items_per_page=5)
#class Seances(Base):
# class Seances(Base):
# __tablename__ = 'seances' # __tablename__ = 'seances'
def get_user(request): def get_user(request):
# the below line is just an example, use your own method of # the below line is just an example, use your own method of
@@ -717,28 +744,28 @@ def get_user(request):
if userid is not None: if userid is not None:
# this should return None if the user doesn't exist # this should return None if the user doesn't exist
# in the database # in the database
return DBSession.query(User).filter(User.uid==userid).first() return DBSession.query(User).filter(User.uid == userid).first()
def get_sponsors(request, Year): def get_sponsors(request, Year):
if Year: if Year:
return DBSession.query(Tiers)\ return DBSession.query(Tiers) \
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\ .join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
.filter( Role_Tiers.tiers_role == 'Sponsor')\ .filter(Role_Tiers.tiers_role == 'Sponsor') \
.filter( Role_Tiers.year_uid == Year) .filter(Role_Tiers.year_uid == Year)
else: else:
return DBSession.query(Tiers)\ return DBSession.query(Tiers) \
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\ .join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
.filter( Role_Tiers.tiers_role == 'Sponsor') .filter(Role_Tiers.tiers_role == 'Sponsor')
def get_exposants(request, Year): def get_exposants(request, Year):
if Year: if Year:
return DBSession.query(Tiers)\ return DBSession.query(Tiers) \
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\ .join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
.filter( Role_Tiers.tiers_role == 'Exposant')\ .filter(Role_Tiers.tiers_role == 'Exposant') \
.filter( Role_Tiers.year_uid == Year) .filter(Role_Tiers.year_uid == Year)
else: else:
return DBSession.query(Tiers)\ return DBSession.query(Tiers) \
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\ .join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
.filter( Role_Tiers.tiers_role == 'Exposant') .filter(Role_Tiers.tiers_role == 'Exposant')
+12 -13
View File
@@ -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('Processing', table_name)
print 'Pulling schema from source server' 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)
+1 -1
View File
@@ -58,7 +58,7 @@
% if reason: % if reason:
<p>${reason}</p> <p>${reason}</p>
% else: % else:
<p>Vous n'êtes pas authentifi&eacute;, ou n'avez pas les authorisations n&eacute;cessaires.</p> <p>Vous n'êtes pas authentifié, ou n'avez pas les authorisations nécessaires.</p>
% endif % endif
</body> </body>
</html> </html>
+1 -1
View File
@@ -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&eacute;e</h1> <h1>Page non trouvée</h1>
% if reason: % if reason:
<p>${reason}</p> <p>${reason}</p>
% else: % else:
+12 -12
View File
@@ -10,7 +10,7 @@
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>Conf&eacute;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&eacute;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&eacute; 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&eacute; d'intervention %s." % CurEvent
% if Type=='C': % if Type=='C':
<p> <p>
<strong>Proposer une conf&eacute;rence / un lighting talk</strong><br/> <strong>Proposer une conférence / un lighting talk</strong><br/>
<ul> <ul>
<li>Si vous avez une exp&eacute;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 dun des sujets actuels qui menacent ou qui <li>Si vous êtes acteur dun des sujets actuels qui menacent ou qui
promeuvent le logiciel libre.</li> promeuvent le logiciel libre.</li>
<li>Si vous voulez pr&eacute;senter un logiciel libre dont vous êtes lauteur.</li> <li>Si vous voulez présenter un logiciel libre dont vous êtes lauteur.</li>
</ul> </ul>
Nous serons heureux de vous &eacute;couter. Nous serons heureux de vous écouter.
<br> <br>
Nous souhaitons proposer des conf&eacute;rences pour un public d&eacute;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&eacute;ment être techniques, mais aussi dordre g&eacute;n&eacute;ral avec la seule forcément être techniques, mais aussi dordre 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&eacute; ou de vos propres exp&eacute;riences dutilisateur quotidien. <br> communauté ou de vos propres exp&eacute;riences dutilisateur quotidien. <br>
Le but de ces conf&eacute;rences est double : Le but de ces conf&eacute;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&eacute; 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&eacute;sol&eacute;, Il n'y a rien dans l'historique vous concernant." NothingTitle = u"D&eacute;sol&eacute;, Il n'y a rien dans l'historique vous concernant."
%> %>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
+2 -2
View File
@@ -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')} <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').decode('utf-8')} vers ${Exch.end_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>
+17 -17
View File
@@ -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&eacute;</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;">&#127869;</span> Miam</a> </li> <li> <a href="#Miam" data-toggle="tab"><span style="font-size:1.8em;">&#127869;</span> Miam</a> </li>
<li> <a href="#Covoiturage" data-toggle="tab"><span style="font-size:1.8em;">&#128664;</span> Covoiturage</a> </li> <li> <a href="#Covoiturage" data-toggle="tab"><span style="font-size:1.8em;">&#128664;</span> Covoiturage</a> </li>
<li> <a href="#Hebergement" data-toggle="tab"><span style="font-size:1.8em;">&#127962;</span> H&eacute;bergement</a> </li> <li> <a href="#Hebergement" data-toggle="tab"><span style="font-size:1.8em;">&#127962;</span> Hébergement</a> </li>
<li> <a href="#Materiel" data-toggle="tab"><span style="font-size:1.8em;">&#128722;</span> Mat&eacute;riel</a> </li> <li> <a href="#Materiel" data-toggle="tab"><span style="font-size:1.8em;">&#128722;</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 &eacute;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&eacute;tez dès à pr&eacute;sent votre partie repas afin que l'on puisse faire les r&eacute;servations n&eacute;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&eacute;renciers viennent de très loin et seront pr&eacute;sent d&eacute;s le vendredi.<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&eacute;, à la CASA.<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>
&Agrave; la pause du midi, nous vous proposons un repas avec le food-truck 'les frères toqu&eacute;s' qui sera pr&eacute;sent sur le parking de PolyTech<br /> &Agrave; 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&eacute;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 &eacute;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&eacute;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 &eacute;change ${CurTitle} propos&eacute; 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')} de ${item.start_time.strftime('%a %d %b %Hh%M')}
à ${item.end_time.strftime('%a %d %b %Hh%M').decode('utf-8')} à ${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´&eacute;v&eacute;nement</a> <a class="accordion-toggle" data-toggle="collapse" data-parent="#AccordionCounter" href="#collapseAll">Les compteurs de l´év&eacute;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">
+4 -4
View File
@@ -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')} de ${item.start_time.strftime('%A %d %b %Y')} 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> à ${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:
+4 -4
View File
@@ -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&eacute;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&eacute; 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&eacute;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&eacute; 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}
+13 -13
View File
@@ -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&eacute; votre venue aux JM2L ${CurrentYear} Vous n'avez pas confirmé votre venue aux JM2L ${CurrentYear}
</legend> </legend>
<h4 class="lowshadow">Compl&eacute;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&eacute;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&eacute; r&eacute;duite (PMR)" type="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&eacute; r&eacute;duite (PMR)</input></label> 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&eacute;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&eacute;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&eacute;cisions à propos de mon arriv&eacute;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&eacute;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: &nbsp;&nbsp;<small style="color: #aaa;">(Cochez les cases correspondantes)</small> Je vais avoir besoin: &nbsp;&nbsp;<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&eacute; r&eacute;duite (PMR)" type="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&eacute; r&eacute;duite (PMR)</input> 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&eacute;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&eacute;cisions à propos de mon d&eacute;part…" /> placeholder="Précisions à propos de mon départ…" />
</div> </div>
</li> </li>
</ul> </ul>
+1 -1
View File
@@ -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;">
+2 -2
View File
@@ -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&eacute;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&eacute;er</a> ] [ <a href="/PhySalles">Créer</a> ]
% endif % endif
</div> </div>
+2 -2
View File
@@ -29,9 +29,9 @@
%endif %endif
<% <%
DicForm = { DicForm = {
'year_uid': {'PlaceHolder':u"Ann&eacute;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'&eacute;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" },
} }
+1 -1
View File
@@ -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}">
+1 -1
View File
@@ -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>
+3 -3
View File
@@ -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">&nbsp;</div> <div class="clearfix">&nbsp;</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/>
+14 -14
View File
@@ -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&eacute;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&eacute;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&eacute; 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&eacute;sol&eacute;, 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}:
+7 -7
View File
@@ -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&eacute;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&eacute;</a> </li> <li class="active"> <a href="#ResumePart" data-toggle="tab">Resumé</a> </li>
<li> <a href="#Conference" data-toggle="tab">Conf&eacute;rence</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'&eacute;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&eacute;rence ou une table ronde</strong> aux JM2L ${CurrentYear}.</li> <li>Vous animez <strong>un atelier, une conférence ou une table ronde</strong> aux JM2L ${CurrentYear}.</li>
<li>Votre fiche est renseign&eacute;e avec <strong>votre RIB</strong>.</li> <li>Votre fiche est renseignée avec <strong>votre RIB</strong>.</li>
<li>Votre fiche est renseign&eacute;e avec <strong>les preuves</strong> de vos achats.</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>
+16 -16
View File
@@ -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> <H1>JM2L 2020</H1>
<h3>Choisissez ici votre logo pr&eacute;f&eacute;r&eacute; !</h3> <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&eacute;sitez pas à envoyer vos propositions par mail à l'&eacute;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&nbsp;<span class="caret"></span></a> Édition&nbsp;<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&eacute;rer les intervenants</a></li> <li><a href="/${DisplayYear}/ListParticipant">Gérer les intervenants</a></li>
<li><a href="/ListSalles">G&eacute;rer les salles</a></li> <li><a href="/ListSalles">Gérer les salles</a></li>
<li><a href="/entities">G&eacute;rer les entit&eacute;s</a></li> <li><a href="/entities">Gérer les entités</a></li>
<li><a href="/${DisplayYear}/ListOrga">Participations &agrave; l'orga</a></li> <li><a href="/${DisplayYear}/ListOrga">Participations &agrave; l'orga</a></li>
<li><a href="/${DisplayYear}/Staff/compta">Comptabilit&eacute;</a></li> <li><a href="/${DisplayYear}/Staff/compta">Comptabilité</a></li>
<li><a href="/ListSallesPhy">Les salles &agrave; Poly'tech</a></li> <li><a href="/ListSallesPhy">Les salles &agrave; 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&eacute;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&eacute; 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&eacute;berg&eacute; 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&eacute; 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&eacute;f&eacute;r&eacute; ! "); $('.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 ! ");
+3 -3
View File
@@ -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 !
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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>
+2 -2
View File
@@ -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">&nbsp;</div> <div class="clearfix">&nbsp;</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>
+1 -1
View File
@@ -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/>
+1 -1
View File
@@ -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>
+4 -1
View File
@@ -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
+113 -109
View File
@@ -9,7 +9,10 @@ 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
@@ -30,90 +33,88 @@ ACCEPTED_MIMES = ['application/pdf',
'application/vnd.oasis.opendocument.spreadsheet-template', 'application/vnd.oasis.opendocument.spreadsheet-template',
'image/svg+xml', 'image/svg+xml',
'application/x-blender' 'application/x-blender'
] ]
ACCEPT_FILE_TYPES = IMAGE_TYPES ACCEPT_FILE_TYPES = IMAGE_TYPES
THUMBNAIL_SIZE = 80 THUMBNAIL_SIZE = 80
EXPIRATION_TIME = 300 # seconds EXPIRATION_TIME = 300 # seconds
IMAGEPATH = [ 'images' ] IMAGEPATH = ['images']
DOCPATH = [ 'document' ] DOCPATH = ['document']
THUMBNAILPATH = [ 'images', 'thumbnails' ] 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 ) filename, ext = os.path.splitext(f)
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:
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")): if os.path.exists(os.path.join(thumbpath, f + ".jpg")):
filelist.append((ress_url, thumb_url +".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 ) filename, ext = os.path.splitext(f)
tmpurl = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ","%20")) 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 ) filename, ext = os.path.splitext(f)
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:
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
@@ -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 ] src = IMAGEPATH + [media_table, from_id]
dst = IMAGEPATH + [ media_table, to_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 ] p = IMAGEPATH + [media_table, slug]
elif media_table=='presse': elif media_table == 'presse':
# Use Year in linked_id # Use Year in linked_id
p = IMAGEPATH + [ media_table, linked_id ] p = IMAGEPATH + [media_table, linked_id]
elif media_table=='tasks': elif media_table == 'tasks':
# 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=='poles': 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 ] p = IMAGEPATH + [media_table, slug]
elif media_table=='event': 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):
@@ -266,7 +268,7 @@ class MediaUpload(MediaPath):
result['type'] = found_mime result['type'] = found_mime
# Reject mime type that don't match # Reject mime type that don't match
if found_mime!=result['type']: 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
@@ -294,36 +296,36 @@ class MediaUpload(MediaPath):
fileobj.seek(0) # Reset the file position to the beginning fileobj.seek(0) # Reset the file position to the beginning
return size return size
def thumbnailurl(self,name): def thumbnailurl(self, name):
return self.request.route_url('media_view',name='thumbnails', return self.request.route_url('media_view', name='thumbnails',
media_table=self.media_table, media_table=self.media_table,
uid=self.linked_id) + '/' + name 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 ) timage.save(TargetFileName)
return self.thumbnailurl( os.path.basename(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: if Result == 0:
image = Image.open( TargetFileName+"_.jpg" ) image = Image.open(TargetFileName + "_.jpg")
pdf_indicator = Image.open( "jm2l/static/img/PDF_Thumb_Stamp.png" ) 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
@@ -333,21 +335,21 @@ class MediaUpload(MediaPath):
# 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') timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG')
os.unlink(TargetFileName+"_.jpg") os.unlink(TargetFileName + "_.jpg")
return self.thumbnailurl( os.path.basename(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: if Result == 0:
image = Image.open( TargetFileName+"_.jpg" ) image = Image.open(TargetFileName + "_.jpg")
pdf_indicator = Image.open( "jm2l/static/img/svg-icon.png" ) 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
@@ -357,12 +359,12 @@ class MediaUpload(MediaPath):
# 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') timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG')
os.unlink(TargetFileName+"_.jpg") os.unlink(TargetFileName + "_.jpg")
return self.thumbnailurl( os.path.basename(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,16 +372,17 @@ 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 ) f, ext = os.path.splitext(filename)
istamp = [ ('Writer','odt'), istamp = [('Writer', 'odt'),
('Impress','odp'), ('Impress', 'odp'),
('Calc','ods'), ('Calc', 'ods'),
('Draw','odg')] ('Draw', 'odg')]
stampfilename = filter(lambda (x,y): ext.endswith(y), istamp) stampfilename = filter(lambda x, y: ext.endswith(y), istamp)
stamp = Image.open( "jm2l/static/img/%s-icon.png" % stampfilename[0][0]) 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(
@@ -388,11 +391,11 @@ class MediaUpload(MediaPath):
# 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') timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG')
return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") ) return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg"))
def blendthumbnail(self, filename): def blendthumbnail(self, filename):
blendfile = self.mediapath(filename) blendfile = self.mediapath(filename)
@@ -411,7 +414,7 @@ class MediaUpload(MediaPath):
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,17 +424,17 @@ 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") timage.save(TargetFileName + ".png")
return self.thumbnailurl( os.path.basename(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): def fileinfo(self, name):
filename = self.mediapath(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)
@@ -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 ): if os.path.exists(thumb + thumbext):
info['thumbnailUrl'] = self.thumbnailurl(name)+thumbext info['thumbnailUrl'] = self.thumbnailurl(name) + thumbext
else: else:
info['thumbnailUrl'] = self.ExtMimeIcon(mime) info['thumbnailUrl'] = self.ExtMimeIcon(mime)
else: else:
@@ -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):
@@ -506,7 +509,7 @@ class MediaUpload(MediaPath):
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: except OSError:
@@ -523,7 +526,7 @@ class MediaUpload(MediaPath):
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,26 +534,26 @@ 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'] ) filename, file_extension = os.path.splitext(result['name'])
local_filename = slugify( filename ) + file_extension 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: with open(self.mediapath(local_filename), 'wb') as f:
shutil.copyfileobj( fieldStorage.file , 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'])
@@ -568,26 +571,27 @@ class MediaUpload(MediaPath):
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
+629 -560
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -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',