Compare commits
3 Commits
master
..
2b3e8116d5
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b3e8116d5 | |||
| 588ce76eee | |||
| ad9883ae09 |
+11
@@ -36,3 +36,14 @@ If no error occurs, the webserver should be available on http://localhost:8080/
|
||||
pserve development.ini
|
||||
|
||||
Enjoy !
|
||||
|
||||
|
||||
sudo apt install virtualenv git python3-virtualenv imagemagick
|
||||
|
||||
sudo mkdir -p /srv/jm2l
|
||||
cd /srv/jm2l/
|
||||
cd /srv
|
||||
sudo chown luna jm2l
|
||||
cd jm2l/
|
||||
virtualenv -p python3 .venv_jm2l
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ pyramid.debug_notfound = false
|
||||
pyramid.debug_routematch = false
|
||||
pyramid.default_locale_name = en
|
||||
pyramid.includes =
|
||||
pyramid_mailer.testing
|
||||
pyramid_debugtoolbar
|
||||
pyramid_tm
|
||||
pyramid_mako
|
||||
|
||||
+19
-12
@@ -3,10 +3,12 @@ try:
|
||||
except ImportError:
|
||||
from cgi import escape
|
||||
|
||||
#from wtforms import widgets
|
||||
from wtforms.widgets import HTMLString, html_params
|
||||
# from wtforms import widgets
|
||||
from wtforms.widgets import html_params
|
||||
from wtforms.fields.core import Field
|
||||
from wtforms.compat import text_type, izip
|
||||
from markupsafe import Markup
|
||||
|
||||
|
||||
class MySelect(object):
|
||||
"""
|
||||
@@ -19,6 +21,7 @@ class MySelect(object):
|
||||
call on rendering; this method must yield tuples of
|
||||
`(value, label, selected)`.
|
||||
"""
|
||||
|
||||
def __init__(self, multiple=False):
|
||||
self.multiple = multiple
|
||||
|
||||
@@ -34,13 +37,13 @@ class MySelect(object):
|
||||
elif last_group != group:
|
||||
html.append(self.render_optgroup(last_group, group))
|
||||
html.append(self.render_option(val, label, selected))
|
||||
last_group=group
|
||||
last_group = group
|
||||
else:
|
||||
html.append(self.render_option(val, label, selected))
|
||||
if last_group:
|
||||
html.append(self.render_optgroup(last_group, None))
|
||||
html.append('</select>')
|
||||
return HTMLString(''.join(html))
|
||||
return Markup(''.join(html))
|
||||
|
||||
@classmethod
|
||||
def render_option(cls, value, label, selected, **kwargs):
|
||||
@@ -51,17 +54,19 @@ class MySelect(object):
|
||||
options = dict(kwargs, value=value)
|
||||
if selected:
|
||||
options['selected'] = True
|
||||
return HTMLString('<option %s>%s</option>' % (html_params(**options), escape(text_type(label), quote=False)))
|
||||
return Markup('<option %s>%s</option>' % (html_params(**options), escape(text_type(label), quote=False)))
|
||||
|
||||
@classmethod
|
||||
def render_optgroup(cls, previous_label, label, **kwargs):
|
||||
options = dict(kwargs)
|
||||
if previous_label is None:
|
||||
return HTMLString('<optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
|
||||
return Markup(
|
||||
'<optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
|
||||
elif label is None:
|
||||
return HTMLString('</optgroup>')
|
||||
return Markup('</optgroup>')
|
||||
else:
|
||||
return HTMLString('</optgroup><optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
|
||||
return Markup(
|
||||
'</optgroup><optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
|
||||
|
||||
|
||||
class MyOption(object):
|
||||
@@ -71,12 +76,13 @@ class MyOption(object):
|
||||
This is just a convenience for various custom rendering situations, and an
|
||||
option by itself does not constitute an entire field.
|
||||
"""
|
||||
|
||||
def __call__(self, field, **kwargs):
|
||||
return MySelect.render_option(field._value(), field.label.text, field.checked, **kwargs)
|
||||
|
||||
|
||||
class MySelectFieldBase(Field):
|
||||
#option_widget = widgets.Option()
|
||||
# option_widget = widgets.Option()
|
||||
option_widget = MyOption()
|
||||
|
||||
"""
|
||||
@@ -85,6 +91,7 @@ class MySelectFieldBase(Field):
|
||||
This isn't a field, but an abstract base class for fields which want to
|
||||
provide this functionality.
|
||||
"""
|
||||
|
||||
def __init__(self, label=None, validators=None, option_widget=None, **kwargs):
|
||||
super(MySelectFieldBase, self).__init__(label, validators, **kwargs)
|
||||
|
||||
@@ -114,7 +121,7 @@ class MySelectFieldBase(Field):
|
||||
|
||||
|
||||
class MySelectField(MySelectFieldBase):
|
||||
#widget = widgets.Select()
|
||||
# widget = widgets.Select()
|
||||
widget = MySelect()
|
||||
|
||||
def __init__(self, label=None, validators=None, coerce=text_type, choices=None, **kwargs):
|
||||
@@ -128,11 +135,11 @@ class MySelectField(MySelectFieldBase):
|
||||
# We should consider choiceA as an optgroup label
|
||||
group_label = choiceA
|
||||
for value, label in choiceB:
|
||||
yield (group_label, value, label, self.coerce(value) == self.data)
|
||||
yield group_label, value, label, self.coerce(value) == self.data
|
||||
else:
|
||||
value, label = choiceA, choiceB
|
||||
# Not an optgroup, let's fallback to classic usage
|
||||
yield (None, value, label, self.coerce(value) == self.data)
|
||||
yield None, value, label, self.coerce(value) == self.data
|
||||
|
||||
def process_data(self, value):
|
||||
try:
|
||||
|
||||
+64
-61
@@ -19,51 +19,53 @@ from pyramid.request import Request
|
||||
from mako.template import Template
|
||||
from .models import User
|
||||
from jm2l.const import CurrentYear
|
||||
from models import JM2L_Year
|
||||
|
||||
from .models import JM2L_Year
|
||||
import logging
|
||||
|
||||
|
||||
def add_renderer_globals(event):
|
||||
event['mytrip'] = Sejour_helpers(event)
|
||||
event['myorga'] = Orga_helpers(event)
|
||||
event['SelectedYear'] = CurrentYear
|
||||
event['CurrentYear'] = CurrentYear
|
||||
|
||||
#@sched.scheduled_job('cron', day_of_week='sun', hour=22, minute=07)
|
||||
|
||||
# @sched.scheduled_job('cron', day_of_week='sun', hour=22, minute=7)
|
||||
def mailer_tasks(config):
|
||||
# Send the Welcome Mail
|
||||
mailer = config.registry['mailer']
|
||||
Contact = DBSession.query(User).filter(User.uid==1).one()
|
||||
contact = DBSession.query(User).filter(User.uid == 1).one()
|
||||
request = Request.blank('/', base_url='http://jm2l.linux-azur.org')
|
||||
request.registry = config.registry
|
||||
for StaffUser in DBSession.query(User).filter(User.Staff == True):
|
||||
for staff_user in DBSession.query(User).filter(User.Staff is True):
|
||||
# Skip mail to contact
|
||||
if StaffUser==Contact:
|
||||
if staff_user == contact:
|
||||
continue
|
||||
# Skip those that have no task assigned
|
||||
if len(filter(lambda k:not k.closed, StaffUser.task_assoc))==0:
|
||||
if len(filter(lambda k: not k.closed, staff_user.task_assoc)) == 0:
|
||||
continue
|
||||
|
||||
# Prepare Plain Text Message :
|
||||
Mail_template = Template(filename='jm2l/templates/mail_plain.mako')
|
||||
mail_plain = Mail_template.render(request=request, User=StaffUser, Contact=Contact, action="Tasks")
|
||||
mail_template = Template(filename='jm2l/templates/mail_plain.mako')
|
||||
mail_plain = mail_template.render(request=request, User=staff_user, Contact=contact, action="Tasks")
|
||||
# Prepare HTML Message :
|
||||
Mail_template = Template(filename='jm2l/templates/mail_html.mako')
|
||||
mail_html = Mail_template.render(request=request, User=StaffUser, Contact=Contact, action="Tasks")
|
||||
mail_template = Template(filename='jm2l/templates/mail_html.mako')
|
||||
mail_html = mail_template.render(request=request, User=staff_user, Contact=contact, action="Tasks")
|
||||
# Prepare Message
|
||||
message = Message(subject="[JM2L] Le mail de rappel pour les JM2L !",
|
||||
sender="contact@jm2l.linux-azur.org",
|
||||
recipients=[StaffUser.mail],
|
||||
recipients=[staff_user.mail],
|
||||
body=mail_plain, html=mail_html)
|
||||
|
||||
message.add_bcc("spam@style-python.fr")
|
||||
|
||||
mailer.send_immediately(message)
|
||||
|
||||
|
||||
def main(global_config, **settings):
|
||||
""" This function returns a Pyramid WSGI application.
|
||||
"""
|
||||
#locale.setlocale(locale.LC_ALL, "fr_FR.UTF-8")
|
||||
# locale.setlocale(locale.LC_ALL, "fr_FR.UTF-8")
|
||||
locale.setlocale(locale.LC_ALL, "fr_FR.utf8")
|
||||
engine = engine_from_config(settings, 'sqlalchemy.')
|
||||
DBSession.configure(bind=engine)
|
||||
@@ -79,11 +81,14 @@ def main(global_config, **settings):
|
||||
authentication_policy=authentication_policy,
|
||||
authorization_policy=authorization_policy
|
||||
)
|
||||
#config.include('pyramid_mailer')
|
||||
config.include('pyramid_mailer.debug')
|
||||
config.add_subscriber(add_renderer_globals, BeforeRender)
|
||||
config.registry['mailer'] = mailer_factory_from_settings(settings)
|
||||
print(settings)
|
||||
# config.registry['mailer'] = mailer_factory_from_settings(settings)
|
||||
config.registry['event_date'] = JM2L_Year.get_latest_jm2l_startdate()
|
||||
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])
|
||||
sched.start() # start the scheduler
|
||||
config.add_renderer('json', JSON(indent=4))
|
||||
config.add_renderer('jsonp', JSONP(param_name='callback'))
|
||||
@@ -100,85 +105,85 @@ def main(global_config, **settings):
|
||||
config.add_static_view('resources', 'resources', cache_max_age=3600)
|
||||
|
||||
# ICal Routes
|
||||
config.add_route('progr_iCal', '/{year:\d+}/JM2L.ics')
|
||||
config.add_route('progr_dyn_iCal', '/{year:\d+}/JM2L_dyn.ics')
|
||||
config.add_route('progr_iCal', r'/{year:\d+}/JM2L.ics')
|
||||
config.add_route('progr_dyn_iCal', r'/{year:\d+}/JM2L_dyn.ics')
|
||||
|
||||
# JSON Routes
|
||||
config.add_route('users_json', '/json-users')
|
||||
config.add_route('tiers_json', '/json-tiers')
|
||||
config.add_route('progr_json', '/{year:\d+}/le-prog-json')
|
||||
config.add_route('timeline_json', '/{year:\d+}/timeline-json')
|
||||
config.add_route('progr_json', r'/{year:\d+}/le-prog-json')
|
||||
config.add_route('timeline_json', r'/{year:\d+}/timeline-json')
|
||||
|
||||
# Session setting Routes
|
||||
config.add_route('year', '/year/{year:\d+}')
|
||||
config.add_route('vote_logo', '/vote_logo/{num:\d+}')
|
||||
config.add_route('year', r'/year/{year:\d+}')
|
||||
config.add_route('vote_logo', r'/vote_logo/{num:\d+}')
|
||||
|
||||
# HTML Routes - Staff
|
||||
config.add_route('Live', '/Live')
|
||||
config.add_route('list_expenses', '/{year:\d+}/Staff/compta')
|
||||
config.add_route('list_task', '/{year:\d+}/Staff')
|
||||
config.add_route('handle_pole', '/{year:\d+}/Staff/poles{sep:/*}{pole_id:(\d+)?}')
|
||||
config.add_route('handle_task', '/{year:\d+}/Staff/tasks{sep:/*}{task_id:(\d+)?}')
|
||||
config.add_route('action_task', '/{year:\d+}/Staff/{action:(\w+)}/{task_id:(\d+)}')
|
||||
config.add_route('action_task_area', '/{year:\d+}/Staff/pole/{action:(\w+)}/{pole_id:(\d+)}')
|
||||
config.add_route('list_expenses', r'/{year:\d+}/Staff/compta')
|
||||
config.add_route('list_task', r'/{year:\d+}/Staff')
|
||||
config.add_route('handle_pole', r'/{year:\d+}/Staff/poles{sep:/*}{pole_id:(\d+)?}')
|
||||
config.add_route('handle_task', r'/{year:\d+}/Staff/tasks{sep:/*}{task_id:(\d+)?}')
|
||||
config.add_route('action_task', r'/{year:\d+}/Staff/{action:(\w+)}/{task_id:(\d+)}')
|
||||
config.add_route('action_task_area', r'/{year:\d+}/Staff/pole/{action:(\w+)}/{pole_id:(\d+)}')
|
||||
|
||||
config.add_route('list_salles', '/ListSalles')
|
||||
config.add_route('list_salles_phy', '/ListSallesPhy')
|
||||
config.add_route('handle_salle', '/Salles{sep:/*}{salle_id:(\d+)?}')
|
||||
config.add_route('handle_salle_phy', '/PhySalles{sep:/*}{salle_id:(\d+)?}')
|
||||
config.add_route('action_salle', '/Salles/{action:(\w+)}/{salle_id:(\d+)}')
|
||||
config.add_route('pict_salle', '/salle_picture/{salle_id:(\d+)}')
|
||||
config.add_route('handle_salle', r'/Salles{sep:/*}{salle_id:(\d+)?}')
|
||||
config.add_route('handle_salle_phy', r'/PhySalles{sep:/*}{salle_id:(\d+)?}')
|
||||
config.add_route('action_salle', r'/Salles/{action:(\w+)}/{salle_id:(\d+)}')
|
||||
config.add_route('pict_salle', r'/salle_picture/{salle_id:(\d+)}')
|
||||
|
||||
config.add_route('list_users', '/{year:\d+}/ListParticipant')
|
||||
config.add_route('list_users_csv', '/{year:\d+}/ListParticipant.csv')
|
||||
config.add_route('list_orga', '/{year:\d+}/ListOrga')
|
||||
config.add_route('list_users', r'/{year:\d+}/ListParticipant')
|
||||
config.add_route('list_users_csv', r'/{year:\d+}/ListParticipant.csv')
|
||||
config.add_route('list_orga', r'/{year:\d+}/ListOrga')
|
||||
|
||||
# HTML Routes - Public
|
||||
config.add_route('home', '/{year:(\d+/)?}')
|
||||
config.add_route('edit_index', '/{year:\d+}/edit')
|
||||
config.add_route('presse', '/{year:\d+}/dossier-de-presse')
|
||||
config.add_route('edit_presse', '/{year:\d+}/dossier-de-presse/edit')
|
||||
config.add_route('programme', '/{year:\d+}/le-programme')
|
||||
config.add_route('home', r'/{year:(\d+/)?}')
|
||||
config.add_route('edit_index', r'/{year:\d+}/edit')
|
||||
config.add_route('presse', r'/{year:\d+}/dossier-de-presse')
|
||||
config.add_route('edit_presse', r'/{year:\d+}/dossier-de-presse/edit')
|
||||
config.add_route('programme', r'/{year:\d+}/le-programme')
|
||||
config.add_route('plan', 'nous-rejoindre')
|
||||
config.add_route('participer', 'participer-l-evenement')
|
||||
config.add_route('captcha', '/captcha')
|
||||
|
||||
## Events
|
||||
config.add_route('event', '/event/{year:\d+}/{event_id:([\w-]+)?}')
|
||||
config.add_route('link_event_user', '/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/link_user')
|
||||
config.add_route('delete_link_u', '/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/delete_link_user')
|
||||
config.add_route('link_event_tiers', '/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/link_tiers')
|
||||
config.add_route('delete_link_t', '/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/delete_link_tiers')
|
||||
config.add_route('edit_event', '/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}')
|
||||
config.add_route('delete_event', '/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}/delete')
|
||||
config.add_route('event', r'/event/{year:\d+}/{event_id:([\w-]+)?}')
|
||||
config.add_route('link_event_user', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/link_user')
|
||||
config.add_route('delete_link_u', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/delete_link_user')
|
||||
config.add_route('link_event_tiers', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/link_tiers')
|
||||
config.add_route('delete_link_t', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}/delete_link_tiers')
|
||||
config.add_route('edit_event', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}')
|
||||
config.add_route('delete_event', r'/MesJM2L/{year:\d+}/{intervention:[\s\w]+}{sep:/*}{event_id:([\w-]+)?}/delete')
|
||||
|
||||
## Entities
|
||||
config.add_route('entities', '/entities') #{sep:/*}{Nature:\w+?}')
|
||||
# Entities
|
||||
config.add_route('entities', '/entities') # {sep:/*}{Nature:\w+?}')
|
||||
config.add_route('add_entity', '/entity')
|
||||
config.add_route('delete_entity', '/entity/{entity_id:(\d+)}/delete')
|
||||
config.add_route('show_entity', '/entity/{tiers_type:(\w+)}/{entity_id:([\w-]+)?}')
|
||||
config.add_route('edit_entity', '/entity/{tiers_type:(\w+)}/{entity_id:([\w-]+)}/edit')
|
||||
config.add_route('delete_entity', r'/entity/{entity_id:(\d+)}/delete')
|
||||
config.add_route('show_entity', r'/entity/{tiers_type:(\w+)}/{entity_id:([\w-]+)?}')
|
||||
config.add_route('edit_entity', r'/entity/{tiers_type:(\w+)}/{entity_id:([\w-]+)}/edit')
|
||||
config.add_route('edit_entity_cat', '/categorie/entity')
|
||||
|
||||
## Users
|
||||
# Users
|
||||
config.add_route('pict_user', '/user_picture')
|
||||
config.add_route('show_user', '/user/{user_slug:([\w-]+)?}')
|
||||
config.add_route('badge_user', '/user/{user_slug:([\w-]+)?}/badge')
|
||||
config.add_route('show_user', r'/user/{user_slug:([\w-]+)?}')
|
||||
config.add_route('badge_user', r'/user/{user_slug:([\w-]+)?}/badge')
|
||||
config.add_route('all_badges', '/badges')
|
||||
config.add_route('place_print', '/place_print')
|
||||
config.add_route('stand_print', '/stand_print')
|
||||
|
||||
# HTML Routes - Logged
|
||||
#config.add_route('profil', 'MesJM2L')
|
||||
# config.add_route('profil', 'MesJM2L')
|
||||
config.add_route('jm2l', '/MesJM2L')
|
||||
config.add_route('drop_sejour', '/DropSejour')
|
||||
config.add_route('miam', '/MonMiam')
|
||||
config.add_route('sejour', '/MonSejour')
|
||||
config.add_route('orga', '/MonOrga')
|
||||
config.add_route('modal', '/{year:\d+}/modal/{modtype:\w+}/{id:(\d+)}')
|
||||
config.add_route('modal', r'/{year:\d+}/modal/{modtype:\w+}/{id:(\d+)}')
|
||||
|
||||
# Handle exchanges
|
||||
config.add_route('exchange', '/{year:\d+}/exchange/{modtype:\w+}/{id:(\d+)}/{action:\w+}')
|
||||
config.add_route('exchange', r'/{year:\d+}/exchange/{modtype:\w+}/{id:(\d+)}/{action:\w+}')
|
||||
|
||||
# Handle authentication
|
||||
config.add_route('register', '/register')
|
||||
@@ -186,10 +191,8 @@ def main(global_config, **settings):
|
||||
config.add_route('bymail', '/sign/jm2l/{hash}')
|
||||
|
||||
# Handle Multimedia and Uploads
|
||||
config.add_route('media_view', '/image/{media_table:\w+}/{uid:\d+}/{name:.+}')
|
||||
config.add_route('media_upload', '/uploader/{media_table:\w+}/{uid:\d+}/proceed{sep:/*}{name:.*}')
|
||||
config.add_route('media_view', r'/image/{media_table:\w+}/{uid:\d+}/{name:.+}')
|
||||
config.add_route('media_upload', r'/uploader/{media_table:\w+}/{uid:\d+}/proceed{sep:/*}{name:.*}')
|
||||
|
||||
config.scan()
|
||||
return config.make_wsgi_app()
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ from pyramid_mailer import get_mailer
|
||||
from pyramid_mailer.message import Attachment, Message
|
||||
from .forms import UserPasswordForm
|
||||
from passlib.hash import argon2
|
||||
from security import check_logged
|
||||
from .security import check_logged
|
||||
import datetime
|
||||
import re
|
||||
|
||||
|
||||
+136
-123
@@ -1,7 +1,12 @@
|
||||
# -*- coding: utf8 -*-
|
||||
from pyramid.httpexceptions import HTTPNotFound, HTTPForbidden
|
||||
from pyramid.response import Response
|
||||
import cStringIO as StringIO
|
||||
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
import io
|
||||
from pyramid.view import view_config
|
||||
from .models import DBSession, User
|
||||
from reportlab.pdfgen import canvas
|
||||
@@ -12,78 +17,86 @@ import qrcode
|
||||
import subprocess
|
||||
from .upload import MediaPath
|
||||
from jm2l.const import CurrentYear
|
||||
|
||||
# Create PDF container
|
||||
EXPIRATION_TIME = 300 # seconds
|
||||
WIDTH = 85 * mm
|
||||
HEIGHT = 60 * mm
|
||||
ICONSIZE = 10 * mm
|
||||
|
||||
def JM2L_Logo(canvas, Offset=(0,0)):
|
||||
OffX, OffY = Offset
|
||||
logoobject = canvas.beginText()
|
||||
logoobject.setFont('Logo', 32)
|
||||
logoobject.setFillColorRGB(.83,0,.33)
|
||||
logoobject.setTextOrigin(OffX+5, OffY+17)
|
||||
logoobject.textLines("JM2L")
|
||||
canvas.drawText(logoobject)
|
||||
|
||||
yearobject = canvas.beginText()
|
||||
yearobject.setFont("Helvetica-Bold", 10)
|
||||
yearobject.setFillColorRGB(1,1,1)
|
||||
yearobject.setTextRenderMode(0)
|
||||
yearobject.setTextOrigin(OffX+12 , OffY+35)
|
||||
yearobject.setWordSpace(13)
|
||||
yearobject.textLines(" ".join(str(CurrentYear)))
|
||||
canvas.drawText(yearobject)
|
||||
def JM2L_Logo(canvas, Offset=(0, 0)):
|
||||
off_x, off_y = Offset
|
||||
logo_object = canvas.beginText()
|
||||
logo_object.setFont('Logo', 32)
|
||||
logo_object.setFillColorRGB(.83, 0, .33)
|
||||
logo_object.setTextOrigin(off_x + 5, off_y + 17)
|
||||
logo_object.textLines("JM2L")
|
||||
canvas.drawText(logo_object)
|
||||
|
||||
def Tiers_Logo(canvas, DispUser, StartPos=None, Offset=(0,0)):
|
||||
Border = 0
|
||||
OffX, OffY = Offset
|
||||
if StartPos is None:
|
||||
StartPos = ( 30 * mm, 2 )
|
||||
StartX, StartY = StartPos
|
||||
MaxX, MaxY = 34*mm, 18*mm
|
||||
year_object = canvas.beginText()
|
||||
year_object.setFont("Helvetica-Bold", 10)
|
||||
year_object.setFillColorRGB(1, 1, 1)
|
||||
year_object.setTextRenderMode(0)
|
||||
year_object.setTextOrigin(off_x + 12, off_y + 35)
|
||||
year_object.setWordSpace(13)
|
||||
year_object.textLines(" ".join(str(CurrentYear)))
|
||||
canvas.drawText(year_object)
|
||||
|
||||
|
||||
def Tiers_Logo(canvas, DispUser, start_pos=None, Offset=(0, 0)):
|
||||
border = 0
|
||||
off_x, off_y = Offset
|
||||
if start_pos is None:
|
||||
start_pos = (30 * mm, 2)
|
||||
start_x, start_y = start_pos
|
||||
max_x, max_y = 34 * mm, 18 * mm
|
||||
num = 0
|
||||
canvas.setStrokeColorRGB(0.5,0.5,0.5)
|
||||
Logos = filter(lambda x:x.ThumbLinks, DispUser.tiers)[:3]
|
||||
canvas.setStrokeColorRGB(0.5, 0.5, 0.5)
|
||||
list_logos = list()
|
||||
for thumb in DispUser.tiers:
|
||||
if thumb.ThumbLinks:
|
||||
list_logos.append(thumb.ThumbLinks[:3])
|
||||
# list_logos = list(filter(lambda x: x.ThumbLinks, DispUser.tiers)[:3])
|
||||
# Should We compute a better positionning for logos ?
|
||||
DicPos = {}
|
||||
DicPos[1] = { 0:(1./2, 1./2) }
|
||||
DicPos[2] = { 0:(1./3, 1./2), 1:(2./3, 1./2) }
|
||||
DicPos[3] = { 0:(1./2, 1./4), 1:(1./3, 3./4), 2:(2./3, 3./4) }
|
||||
DicPos[4] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./3, 3./4),
|
||||
3:(2./3, 3./4) }
|
||||
DicPos[5] = { 0:(1./3, 1./4), 1:(2./3, 1./4), 2:(1./6, 3./4),
|
||||
3:(3./6, 3./4), 4:(5./6, 3./4) }
|
||||
DicPos[6] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4),
|
||||
3:(1./6, 3./4), 4:(3./6, 3./4), 5:(5./6, 3./4) }
|
||||
DicPos[7] = { 0:(1./6, 1./4), 1:(3./6, 1./4), 2:(5./6, 1./4),
|
||||
3:(1./8, 3./4), 4:(3./8, 3./4), 5:(5./8, 3./4),
|
||||
6:(7./8, 3./4) }
|
||||
DicPos[8] = { 0:(1./8, 1./4), 1:(3./8, 1./4), 2:(5./8, 1./4),
|
||||
3:(7./8, 1./4), 4:(1./8, 3./4), 5:(3./8, 3./4),
|
||||
6:(5./8, 3./4), 7:(7./8, 3./4) }
|
||||
DicPos[1] = {0: (1. / 2, 1. / 2)}
|
||||
DicPos[2] = {0: (1. / 3, 1. / 2), 1: (2. / 3, 1. / 2)}
|
||||
DicPos[3] = {0: (1. / 2, 1. / 4), 1: (1. / 3, 3. / 4), 2: (2. / 3, 3. / 4)}
|
||||
DicPos[4] = {0: (1. / 3, 1. / 4), 1: (2. / 3, 1. / 4), 2: (1. / 3, 3. / 4),
|
||||
3: (2. / 3, 3. / 4)}
|
||||
DicPos[5] = {0: (1. / 3, 1. / 4), 1: (2. / 3, 1. / 4), 2: (1. / 6, 3. / 4),
|
||||
3: (3. / 6, 3. / 4), 4: (5. / 6, 3. / 4)}
|
||||
DicPos[6] = {0: (1. / 6, 1. / 4), 1: (3. / 6, 1. / 4), 2: (5. / 6, 1. / 4),
|
||||
3: (1. / 6, 3. / 4), 4: (3. / 6, 3. / 4), 5: (5. / 6, 3. / 4)}
|
||||
DicPos[7] = {0: (1. / 6, 1. / 4), 1: (3. / 6, 1. / 4), 2: (5. / 6, 1. / 4),
|
||||
3: (1. / 8, 3. / 4), 4: (3. / 8, 3. / 4), 5: (5. / 8, 3. / 4),
|
||||
6: (7. / 8, 3. / 4)}
|
||||
DicPos[8] = {0: (1. / 8, 1. / 4), 1: (3. / 8, 1. / 4), 2: (5. / 8, 1. / 4),
|
||||
3: (7. / 8, 1. / 4), 4: (1. / 8, 3. / 4), 5: (3. / 8, 3. / 4),
|
||||
6: (5. / 8, 3. / 4), 7: (7. / 8, 3. / 4)}
|
||||
# draw overall border
|
||||
# canvas.roundRect(StartX, StartY, MaxX, MaxY, radius=2, stroke=True)
|
||||
for tiers in Logos:
|
||||
FileName = tiers.ThumbLinks.pop().split("/")[-1]
|
||||
ImagePath = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, FileName)
|
||||
PosX = OffX+StartX + DicPos[len(Logos)][num][0] * MaxX - (ICONSIZE+Border)/2
|
||||
PosY = OffY+StartY + DicPos[len(Logos)][num][1] * MaxY - (ICONSIZE+Border)/2
|
||||
# canvas.roundRect(start_x, start_y, max_x, max_y, radius=2, stroke=True)
|
||||
for tiers in list_logos:
|
||||
file_name = tiers.ThumbLinks.pop().split("/")[-1]
|
||||
image_path = "jm2l/upload/images/tiers/%s/%s" % (tiers.slug, file_name)
|
||||
pos_x = off_x + start_x + DicPos[len(list_logos)][num][0] * max_x - (ICONSIZE + border) / 2
|
||||
pos_y = off_y + start_y + DicPos[len(list_logos)][num][1] * max_y - (ICONSIZE + border) / 2
|
||||
canvas.setLineWidth(.1)
|
||||
if len(Logos)>1:
|
||||
if len(list_logos) > 1:
|
||||
size = ICONSIZE
|
||||
else:
|
||||
size = ICONSIZE*1.5
|
||||
canvas.drawImage(ImagePath,
|
||||
PosX, PosY, size, size,\
|
||||
size = ICONSIZE * 1.5
|
||||
canvas.drawImage(image_path,
|
||||
pos_x, pos_y, size, size,
|
||||
preserveAspectRatio=True,
|
||||
anchor='c',
|
||||
mask='auto'
|
||||
)
|
||||
# draw icon border
|
||||
# canvas.roundRect(PosX, PosY, ICONSIZE, ICONSIZE, radius=2, stroke=True)
|
||||
num+=1
|
||||
# canvas.roundRect(pos_x, pos_y, ICONSIZE, ICONSIZE, radius=2, stroke=True)
|
||||
num += 1
|
||||
|
||||
|
||||
def QRCode(DispUser):
|
||||
qr = qrcode.QRCode(
|
||||
@@ -98,78 +111,79 @@ def QRCode(DispUser):
|
||||
|
||||
return qr.make_image()
|
||||
|
||||
def one_badge(c, DispUser, Offset=(0,0)):
|
||||
|
||||
def one_badge(c, DispUser, Offset=(0, 0)):
|
||||
# Logo on Top
|
||||
JM2L_Logo(c, Offset)
|
||||
OffX, OffY = Offset
|
||||
off_x, off_y = Offset
|
||||
|
||||
c.rect(OffX-3, OffY-3, WIDTH+6, HEIGHT+6, fill=0, stroke=1)
|
||||
c.rect(off_x - 3, off_y - 3, WIDTH + 6, HEIGHT + 6, fill=0, stroke=1)
|
||||
if DispUser.Staff:
|
||||
# Staff
|
||||
c.setFillColorRGB(.83,0,.33)
|
||||
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFillColorRGB(.83, 0, .33)
|
||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1, 1, 1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "STAFF")
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "STAFF")
|
||||
elif DispUser.is_Intervenant:
|
||||
# Intervenant
|
||||
c.setFillColorRGB(.21,.67,.78)
|
||||
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFillColorRGB(.21, .67, .78)
|
||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1, 1, 1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Intervenant")
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Intervenant")
|
||||
elif DispUser.is_crew:
|
||||
# Benevole
|
||||
c.setFillColorRGB(.18,.76,.23)
|
||||
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFillColorRGB(.18, .76, .23)
|
||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1, 1, 1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Bénévole")
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Bénévole")
|
||||
else:
|
||||
# Visiteur
|
||||
c.setFillColorRGB(.8,.8,.8)
|
||||
c.rect(OffX-3, OffY+HEIGHT-30, WIDTH+6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1,1,1)
|
||||
c.setFillColorRGB(.8, .8, .8)
|
||||
c.rect(off_x - 3, off_y + HEIGHT - 30, WIDTH + 6, 33, fill=1, stroke=0)
|
||||
c.setFillColorRGB(1, 1, 1)
|
||||
c.setFont('Liberation', 30)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT-24, "Visiteur")
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT - 24, "Visiteur")
|
||||
|
||||
c.restoreState()
|
||||
|
||||
c.setFont('Liberation', 18)
|
||||
c.setStrokeColorRGB(0,0,0)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
c.setStrokeColorRGB(0, 0, 0)
|
||||
c.setFillColorRGB(0, 0, 0)
|
||||
# Feed Name and SurName
|
||||
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:
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 0 * mm , "%s" % DispUser.prenom )
|
||||
#c.setFont('Courier', 17)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom )
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 0 * mm, "%s" % DispUser.prenom)
|
||||
# c.setFont('Courier', 17)
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom)
|
||||
else:
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 4 * mm , "%s" % DispUser.prenom )
|
||||
#c.setFont('Courier', 17)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 - 8 * mm , "%s" % DispUser.nom )
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 4 * mm, "%s" % DispUser.prenom)
|
||||
# c.setFont('Courier', 17)
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 - 8 * mm, "%s" % DispUser.nom)
|
||||
else:
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 0 * mm , "%s %s" % (DispUser.prenom, DispUser.nom) )
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 0 * mm, "%s %s" % (DispUser.prenom, DispUser.nom))
|
||||
|
||||
if DispUser.pseudo:
|
||||
c.setFont("Helvetica-Oblique", 18)
|
||||
c.drawCentredString(OffX+WIDTH/2, OffY+HEIGHT/2 + 10 * mm , "%s" % DispUser.pseudo )
|
||||
c.drawCentredString(off_x + WIDTH / 2, off_y + HEIGHT / 2 + 10 * mm, "%s" % DispUser.pseudo)
|
||||
|
||||
# Put QR code to user profile
|
||||
c.drawInlineImage(QRCode(DispUser), \
|
||||
OffX+WIDTH - 20 * mm -5, OffY+5, \
|
||||
20 * mm, 20 * mm, \
|
||||
preserveAspectRatio=True, \
|
||||
# Put QR code to user profile
|
||||
c.drawInlineImage(QRCode(DispUser),
|
||||
off_x + WIDTH - 20 * mm - 5, off_y + 5,
|
||||
20 * mm, 20 * mm,
|
||||
preserveAspectRatio=True,
|
||||
anchor='s')
|
||||
|
||||
Tiers_Logo(c, DispUser, None, Offset)
|
||||
|
||||
|
||||
@view_config(route_name='badge_user', http_cache = (EXPIRATION_TIME, {'public':True}))
|
||||
@view_config(route_name='badge_user') # , http_cache=(EXPIRATION_TIME, {'public': True}))
|
||||
def badge_user(request):
|
||||
isoutpng = request.params.get('png')
|
||||
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")
|
||||
# Query database
|
||||
DispUser = User.by_slug(user_slug)
|
||||
@@ -179,16 +193,16 @@ def badge_user(request):
|
||||
# Ok let's generate a PDF Badge
|
||||
|
||||
# Register LiberationMono font
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
# Import font
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file))
|
||||
# Import font
|
||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo))
|
||||
|
||||
pdf = StringIO.StringIO()
|
||||
out_img = StringIO.StringIO()
|
||||
pdf = io.BytesIO()
|
||||
out_img = io.BytesIO()
|
||||
|
||||
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
|
||||
c = canvas.Canvas(pdf, pagesize=(WIDTH, HEIGHT))
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
@@ -198,27 +212,26 @@ def badge_user(request):
|
||||
c.saveState()
|
||||
|
||||
one_badge(c, DispUser)
|
||||
|
||||
out_pdf = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.pdf')
|
||||
c.showPage()
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
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:
|
||||
out_png = MediaPath().get_mediapath("badge", DispUser.uid, 'badge.png')
|
||||
# Let's generate a png file for website
|
||||
with open("./%s" % out_pdf, 'wb') as pdff:
|
||||
pdff.write(pdf.read())
|
||||
|
||||
Command = ["convert","-density","150x150", OutPDF, OutPNG]
|
||||
Command = ["convert", "-density", "150x150", out_pdf, out_png]
|
||||
subprocess.call(Command)
|
||||
|
||||
with open( OutPNG, 'rb') as pngfile:
|
||||
out_img.write(pngfile.read())
|
||||
with open("./%s" % out_png, 'rb') as pngfile:
|
||||
out_img.write(pngfile.read()) # pngfile.read(), "utf8"))
|
||||
|
||||
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:
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
return Response(app_iter=pdf, content_type='application/pdf')
|
||||
|
||||
|
||||
@view_config(route_name='all_badges')
|
||||
@@ -232,34 +245,34 @@ def planche_badge(request):
|
||||
# .filter(User_Event.year_uid == year)
|
||||
|
||||
# Register LiberationMono font
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
# Import font
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file))
|
||||
# Import font
|
||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo))
|
||||
|
||||
pdf = StringIO.StringIO()
|
||||
pdf = io.BytesIO()
|
||||
|
||||
FULLWIDTH = 210 * mm
|
||||
FULLHEIGHT = 297 * mm
|
||||
|
||||
c = canvas.Canvas( pdf, pagesize=(FULLWIDTH, FULLHEIGHT) )
|
||||
c = canvas.Canvas(pdf, pagesize=(FULLWIDTH, FULLHEIGHT))
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
c.setCreator("linux-azur.org")
|
||||
c.setTitle("Badge")
|
||||
t=0
|
||||
ListUser = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users)
|
||||
for num, DispUser in enumerate(ListUser):
|
||||
t = 0
|
||||
list_user = filter(lambda x: x.is_Intervenant or x.Staff or x.is_crew, Users)
|
||||
for num, disp_user in enumerate(list_user):
|
||||
c.saveState()
|
||||
Offsets = (((num-t)%2)*(WIDTH+40)+40, ((num-t)/2)*(HEIGHT+25)+40)
|
||||
one_badge(c, DispUser, Offsets)
|
||||
if num%8==7:
|
||||
t=num+1
|
||||
offsets = (((num - t) % 2) * (WIDTH + 40) + 40, int(((num - t) / 2)) * (HEIGHT + 25) + 40)
|
||||
one_badge(c, disp_user, offsets)
|
||||
if num % 8 == 7:
|
||||
t = num + 1
|
||||
c.showPage()
|
||||
|
||||
c.showPage()
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
return Response(app_iter=pdf, content_type='application/pdf')
|
||||
|
||||
+51
-46
@@ -3,18 +3,20 @@
|
||||
|
||||
import random
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||
import cStringIO as StringIO
|
||||
import io
|
||||
# from io import StringIO
|
||||
import math
|
||||
from pyramid.view import view_config
|
||||
from .words import TabMots
|
||||
from pyramid.response import Response
|
||||
|
||||
|
||||
class Captcha_Img(object):
|
||||
def __init__( self, width, height):
|
||||
def __init__(self, width, height):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self._layers = [
|
||||
_PyCaptcha_SineWarp(amplitudeRange = (4, 8) , periodRange=(0.65,0.73) ),
|
||||
_PyCaptcha_SineWarp(amplitudeRange=(4, 8), periodRange=(0.65, 0.73)),
|
||||
]
|
||||
|
||||
def getImg(self):
|
||||
@@ -25,14 +27,15 @@ class Captcha_Img(object):
|
||||
|
||||
def render(self):
|
||||
"""Render this CAPTCHA, returning a PIL image"""
|
||||
size = (self.width,self.height)
|
||||
#img = Image.new("RGB", size )
|
||||
size = (self.width, self.height)
|
||||
# img = Image.new("RGB", size )
|
||||
img = self._image
|
||||
for layer in self._layers:
|
||||
img = layer.render( img ) or img
|
||||
img = layer.render(img) or img
|
||||
self._image = img
|
||||
return self._image
|
||||
|
||||
|
||||
class _PyCaptcha_WarpBase(object):
|
||||
"""Abstract base class for image warping. Subclasses define a
|
||||
function that maps points in the output image to points in the input image.
|
||||
@@ -55,15 +58,15 @@ class _PyCaptcha_WarpBase(object):
|
||||
# Create a list of arrays with transformed points
|
||||
xRows = []
|
||||
yRows = []
|
||||
for j in xrange(yPoints):
|
||||
for j in range(int(yPoints)):
|
||||
xRow = []
|
||||
yRow = []
|
||||
for i in xrange(xPoints):
|
||||
x, y = f(i*r, j*r)
|
||||
for i in range(int(xPoints)):
|
||||
x, y = f(i * r, j * r)
|
||||
|
||||
# Clamp the edges so we don't get black undefined areas
|
||||
x = max(0, min(image.size[0]-1, x))
|
||||
y = max(0, min(image.size[1]-1, y))
|
||||
x = max(0, min(image.size[0] - 1, x))
|
||||
y = max(0, min(image.size[1] - 1, y))
|
||||
|
||||
xRow.append(x)
|
||||
yRow.append(y)
|
||||
@@ -73,27 +76,28 @@ class _PyCaptcha_WarpBase(object):
|
||||
# Create the mesh list, with a transformation for
|
||||
# each square between points on the grid
|
||||
mesh = []
|
||||
for j in xrange(yPoints-1):
|
||||
for i in xrange(xPoints-1):
|
||||
for j in range(int(yPoints - 1)):
|
||||
for i in range(int(xPoints - 1)):
|
||||
mesh.append((
|
||||
# Destination rectangle
|
||||
(i*r, j*r,
|
||||
(i+1)*r, (j+1)*r),
|
||||
(i * r, j * r,
|
||||
(i + 1) * r, (j + 1) * r),
|
||||
# Source quadrilateral
|
||||
(xRows[j ][i ], yRows[j ][i ],
|
||||
xRows[j+1][i ], yRows[j+1][i ],
|
||||
xRows[j+1][i+1], yRows[j+1][i+1],
|
||||
xRows[j ][i+1], yRows[j ][i+1]),
|
||||
(xRows[j][i], yRows[j][i],
|
||||
xRows[j + 1][i], yRows[j + 1][i],
|
||||
xRows[j + 1][i + 1], yRows[j + 1][i + 1],
|
||||
xRows[j][i + 1], yRows[j][i + 1]),
|
||||
))
|
||||
|
||||
return image.transform(image.size, Image.MESH, mesh, self.filtering)
|
||||
|
||||
|
||||
class _PyCaptcha_SineWarp(_PyCaptcha_WarpBase):
|
||||
"""Warp the image using a random composition of sine waves"""
|
||||
|
||||
def __init__(self,
|
||||
amplitudeRange = (1,1),#(2, 6),
|
||||
periodRange = (1,1)#(0.65, 0.73),
|
||||
amplitudeRange=(1, 1), # (2, 6),
|
||||
periodRange=(1, 1) # (0.65, 0.73),
|
||||
):
|
||||
self.amplitude = random.uniform(*amplitudeRange)
|
||||
self.period = random.uniform(*periodRange)
|
||||
@@ -102,50 +106,51 @@ class _PyCaptcha_SineWarp(_PyCaptcha_WarpBase):
|
||||
|
||||
def get_transform(self, image):
|
||||
return (lambda x, y,
|
||||
a = self.amplitude,
|
||||
p = self.period,
|
||||
o = self.offset:
|
||||
(math.sin( (y+o[0])*p )*a + x,
|
||||
math.sin( (x+o[1])*p )*a + y))
|
||||
a=self.amplitude,
|
||||
p=self.period,
|
||||
o=self.offset:
|
||||
(math.sin((y + o[0]) * p) * a + x,
|
||||
math.sin((x + o[1]) * p) * a + y))
|
||||
|
||||
|
||||
@view_config(route_name='captcha')
|
||||
def DoCaptcha(request):
|
||||
ImgSize = (230,100)
|
||||
WorkImg = Image.new( 'RGBA', ImgSize, (255, 255, 255, 0) )
|
||||
Xmax, Ymax = WorkImg.size
|
||||
img_size = (230, 100)
|
||||
work_img = Image.new('RGBA', img_size, (255, 255, 255, 0))
|
||||
Xmax, Ymax = work_img.size
|
||||
# Write something on it
|
||||
draw = ImageDraw.Draw(WorkImg)
|
||||
draw = ImageDraw.Draw(work_img)
|
||||
|
||||
# use a truetype font
|
||||
#font = ImageFont.truetype("/var/lib/defoma/gs.d/dirs/fonts/LiberationMono-Regular.ttf", 40)
|
||||
# font = ImageFont.truetype("/var/lib/defoma/gs.d/dirs/fonts/LiberationMono-Regular.ttf", 40)
|
||||
# use it
|
||||
font = ImageFont.truetype("jm2l/static/fonts/LiberationMono-Regular.ttf",40)
|
||||
font = ImageFont.truetype("jm2l/static/fonts/LiberationMono-Regular.ttf", 40)
|
||||
# Re-position
|
||||
# Choose a word for captcha
|
||||
text = random.choice(TabMots)
|
||||
Xt, Yt = font.getsize(text)
|
||||
OrX, OrY = (ImgSize[0]-Xt)/2, (ImgSize[1]-Yt)/2
|
||||
OrX, OrY = (img_size[0] - Xt) / 2, (img_size[1] - Yt) / 2
|
||||
draw.text((OrX, OrY), text, font=font, fill="#000000")
|
||||
# Apply a Blur
|
||||
# WorkImg=WorkImg.filter(ImageFilter.BLUR)
|
||||
# work_img=work_img.filter(ImageFilter.BLUR)
|
||||
# Apply a DETAIL
|
||||
WorkImg=WorkImg.filter(ImageFilter.DETAIL)
|
||||
work_img = work_img.filter(ImageFilter.DETAIL)
|
||||
# randomize parameters for perspective
|
||||
ax, ay = (random.uniform(0.9,1.2) , random.uniform(0.9,1.2))
|
||||
tx, ty = (random.uniform(0,0.0003),random.uniform(0,0.0003))
|
||||
bx, by = (random.uniform(0.5,0.8),random.uniform(0,0.2))
|
||||
ax, ay = (random.uniform(0.9, 1.2), random.uniform(0.9, 1.2))
|
||||
tx, ty = (random.uniform(0, 0.0003), random.uniform(0, 0.0003))
|
||||
bx, by = (random.uniform(0.5, 0.8), random.uniform(0, 0.2))
|
||||
# Apply perspective to Captcha
|
||||
WorkImg= WorkImg.transform(ImgSize, Image.PERSPECTIVE, (ax, bx, -25, by, ay, -10, tx, ty))
|
||||
work_img = work_img.transform(img_size, Image.PERSPECTIVE, (ax, bx, -25, by, ay, -10, tx, ty))
|
||||
# Apply SinWarp to Captcha
|
||||
tr = Captcha_Img(Xmax, Ymax)
|
||||
tr._image = WorkImg
|
||||
WorkImg = tr.render()
|
||||
tr._image = work_img
|
||||
work_img = tr.render()
|
||||
# Apply a Smooth on it
|
||||
WorkImg=WorkImg.filter(random.choice([ImageFilter.SMOOTH, ImageFilter.SMOOTH_MORE]))
|
||||
work_img = work_img.filter(random.choice([ImageFilter.SMOOTH, ImageFilter.SMOOTH_MORE]))
|
||||
# Save Result
|
||||
request.session['Captcha'] = text
|
||||
#session.save()
|
||||
ImgHandle = StringIO.StringIO()
|
||||
WorkImg.save(ImgHandle,'png')
|
||||
# session.save()
|
||||
ImgHandle = io.BytesIO()
|
||||
work_img.save(ImgHandle, 'png')
|
||||
ImgHandle.seek(0)
|
||||
return Response(app_iter=ImgHandle, content_type = 'image/png')
|
||||
return Response(app_iter=ImgHandle, content_type='image/png')
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
CurrentYear = 2018
|
||||
CurrentYear = 2020
|
||||
|
||||
+186
-115
@@ -1,52 +1,72 @@
|
||||
# -*- coding: utf8 -*-
|
||||
import random
|
||||
import string
|
||||
from wtforms import Form, BooleanField, StringField, TextAreaField, SelectField
|
||||
from wtforms import SubmitField, validators, FieldList, PasswordField
|
||||
#import .ExtWforms
|
||||
# import .ExtWforms
|
||||
from .ExtWtforms import MySelectField
|
||||
from wtforms import HiddenField, DecimalField, DateTimeField, FormField, DateField
|
||||
from wtforms.validators import ValidationError
|
||||
strip_filter = lambda x: x.strip() if x else None
|
||||
from wtforms.csrf.session import SessionCSRF
|
||||
from datetime import timedelta
|
||||
from jm2l.const import CurrentYear
|
||||
|
||||
|
||||
# What about an helper function
|
||||
def strip_filter(x):
|
||||
# strip_filter = lambda x: x.strip() if x else None
|
||||
if x:
|
||||
return x.strip()
|
||||
return None
|
||||
|
||||
|
||||
# get random string password with letters, digits, and symbols
|
||||
def get_random_string(length):
|
||||
csrf_characters = string.ascii_letters + string.digits + string.punctuation
|
||||
csrf = ''.join(random.choice(csrf_characters) for i in range(length))
|
||||
return bytes(csrf, 'utf8')
|
||||
|
||||
|
||||
class MyBaseForm(Form):
|
||||
class Meta:
|
||||
csrf = True
|
||||
csrf_class = SessionCSRF
|
||||
csrf_secret = b'lJDQtOAMC2qe89doIn8u3Mch_DgeLSKO'
|
||||
# csrf_secret = b'lJDQtOAMC2qe89doIn8u3Mch_DgeLSKO'
|
||||
csrf_secret = get_random_string(32)
|
||||
csrf_time_limit = timedelta(minutes=60)
|
||||
|
||||
|
||||
class BlogCreateForm(MyBaseForm):
|
||||
title = StringField('Entry title', [validators.Length(min=1, max=255)],
|
||||
filters=[strip_filter])
|
||||
body = TextAreaField('Entry body', [validators.Length(min=1)],
|
||||
filters=[strip_filter])
|
||||
|
||||
|
||||
class BlogUpdateForm(BlogCreateForm):
|
||||
id = HiddenField()
|
||||
|
||||
|
||||
PLACE_TYPE = [('Aeroport', u'Aéroport'), ('Gare','Gare'), ('JM2L','JM2L'),
|
||||
('Hotel',u'Hôtel'), ('Habitant','Habitant'),
|
||||
('Restaurant','Restaurant'), ('Autres','Autres')]
|
||||
PLACE_TYPE = [('Aeroport', u'Aéroport'), ('Gare', 'Gare'), ('JM2L', 'JM2L'),
|
||||
('Hotel', u'Hôtel'), ('Habitant', 'Habitant'),
|
||||
('Restaurant', 'Restaurant'), ('Autres', 'Autres')]
|
||||
|
||||
TIERS_ROLE = [('Exposant','Exposant'), ('Sponsor','Sponsor'),
|
||||
('Donateur','Donateur')]
|
||||
TIERS_ROLE = [('Exposant', 'Exposant'), ('Sponsor', 'Sponsor'),
|
||||
('Donateur', 'Donateur')]
|
||||
|
||||
YESNO = [("0","Non"), ("1","Oui")]
|
||||
YESNO = [("0", "Non"), ("1", "Oui")]
|
||||
|
||||
EVENT_TYPE = ['Stand', 'Table ronde', 'Atelier', 'Concert', 'Conference', 'Repas']
|
||||
|
||||
CONF_DURATION = [ (15,u'Lighting talk ( 5 min)'),
|
||||
(30,u'Conférence (20 min)'),
|
||||
(60,u'Conférence (50 min)'),
|
||||
(90,u'Conférence (75 min)'),]
|
||||
CONF_DURATION = [(15, u'Lighting talk ( 5 min)'),
|
||||
(30, u'Conférence (20 min)'),
|
||||
(60, u'Conférence (50 min)'),
|
||||
(90, u'Conférence (75 min)'), ]
|
||||
|
||||
ATELIER_DURATION = [ (15,u'Lighting talk ( 5 min)'),
|
||||
(30,u'Conférence (20 min)'),
|
||||
(60,u'Conférence (50 min)'),
|
||||
(90,u'Conférence (75 min)'),]
|
||||
ATELIER_DURATION = [(15, u'Lighting talk ( 5 min)'),
|
||||
(30, u'Conférence (20 min)'),
|
||||
(60, u'Conférence (50 min)'),
|
||||
(90, u'Conférence (75 min)'), ]
|
||||
|
||||
|
||||
class StaffArea(MyBaseForm):
|
||||
@@ -56,46 +76,56 @@ class StaffArea(MyBaseForm):
|
||||
)
|
||||
year_uid = HiddenField('year', default=str(CurrentYear))
|
||||
|
||||
|
||||
class EditStaffArea(StaffArea):
|
||||
uid = HiddenField()
|
||||
|
||||
|
||||
class StaffTasks(MyBaseForm):
|
||||
name = StringField(u'Nom de la tâche', [validators.Required()])
|
||||
area_uid = SelectField(u'Pôle concerné', coerce=int )
|
||||
closed_by = SelectField(u'Assigné à', coerce=int )
|
||||
area_uid = SelectField(u'Pôle concerné', coerce=int)
|
||||
closed_by = SelectField(u'Assigné à', coerce=int)
|
||||
due_date = DateField(u'Date prévue', format='%d/%m/%Y')
|
||||
description = TextAreaField('Description', [validators.optional(), validators.Length(max=1000000)],
|
||||
filters=[strip_filter])
|
||||
year_uid = HiddenField('year', default=str(CurrentYear))
|
||||
|
||||
|
||||
class EditStaffTasks(StaffTasks):
|
||||
uid = HiddenField()
|
||||
|
||||
|
||||
class DossPresse(MyBaseForm):
|
||||
year_uid = HiddenField()
|
||||
doss_presse = TextAreaField('Dossier de Presse', [validators.optional(), validators.Length(max=1000000)],
|
||||
filters=[strip_filter])
|
||||
|
||||
|
||||
class IndexForm(MyBaseForm):
|
||||
year_uid = HiddenField()
|
||||
description = TextAreaField('Index', [validators.optional(), validators.Length(max=1000000)],
|
||||
filters=[strip_filter])
|
||||
|
||||
|
||||
class TiersMember(MyBaseForm):
|
||||
class Meta:
|
||||
csrf = False
|
||||
|
||||
year_uid = SelectField(u'Année', coerce=int, choices=zip(range(2006,CurrentYear+1),range(2006,CurrentYear+1)))
|
||||
year_uid = SelectField(u'Année', coerce=int,
|
||||
choices=zip(range(2006, CurrentYear + 1), range(2006, CurrentYear + 1)))
|
||||
user_uid = StringField(u'user')
|
||||
role = StringField(u'Role')
|
||||
|
||||
|
||||
class TiersRole(MyBaseForm):
|
||||
class Meta:
|
||||
csrf = False
|
||||
|
||||
year_uid = SelectField(u'Année', coerce=int, choices=zip(range(2006,CurrentYear+1),range(2006,CurrentYear+1)))
|
||||
year_uid = SelectField(u'Année', coerce=int,
|
||||
choices=zip(range(2006, CurrentYear + 1), range(2006, CurrentYear + 1)))
|
||||
tiers_role = SelectField(u'Role', choices=TIERS_ROLE)
|
||||
|
||||
|
||||
class TiersChoice(MyBaseForm):
|
||||
class Meta:
|
||||
csrf = False
|
||||
@@ -105,71 +135,84 @@ class TiersChoice(MyBaseForm):
|
||||
tiers_uid = StringField(u'Entité')
|
||||
role = StringField(u'Role')
|
||||
|
||||
|
||||
class AddIntervenant(MyBaseForm):
|
||||
class Meta:
|
||||
csrf = False
|
||||
|
||||
event_uid = HiddenField()
|
||||
intervenant = SelectField(u'Intervenant', coerce=int )
|
||||
intervenant = SelectField(u'Intervenant', coerce=int)
|
||||
|
||||
|
||||
class AddTiers(MyBaseForm):
|
||||
class Meta:
|
||||
csrf = False
|
||||
|
||||
event_uid = HiddenField()
|
||||
tiers = SelectField(u'Entité', coerce=int )
|
||||
tiers = SelectField(u'Entité', coerce=int)
|
||||
|
||||
|
||||
class ConfCreateForm(MyBaseForm):
|
||||
|
||||
event_type = HiddenField()
|
||||
for_year = HiddenField()
|
||||
start_time = HiddenField()
|
||||
end_time = HiddenField()
|
||||
|
||||
start_sel = SelectField(u'Début', coerce=int,
|
||||
description=u"C'est une heure indicative correspondant au mieux à vos préférences "+
|
||||
start_sel = SelectField(
|
||||
u'Début', coerce=int,
|
||||
description=u"C'est une heure indicative correspondant au mieux à vos préférences "
|
||||
u"personnelles. Vous pouvez prendre un créneau horaire déjà réservé si vous avez des contraintes "
|
||||
u"particulières. L'équipe des JM2L mettra à disposition plus de salle si nécessaire. En cas de conflit,"+
|
||||
u"particulières. L'équipe des JM2L mettra à disposition plus de salle si nécessaire. "
|
||||
u"En cas de conflit,"
|
||||
u"l'organisation se réserve le droit de changer la salle et l'heure avec votre accord."
|
||||
)
|
||||
duration = SelectField(u'Durée', coerce=int,
|
||||
description=u"Précisez ici la durée de votre intervention"
|
||||
|
||||
duration = SelectField(
|
||||
u'Durée', coerce=int,
|
||||
description=u"Précisez ici la durée de votre intervention")
|
||||
|
||||
salle_uid = SelectField(
|
||||
u'Salle', coerce=int,
|
||||
description=u"Choisissez ici la salle en fonction du nombres de personnes potentiellement "
|
||||
u"intéressé par votre intervention l'organisation se réserve le droit de changer"
|
||||
u" la salle (avec votre accord)."
|
||||
)
|
||||
|
||||
salle_uid = SelectField(u'Salle', coerce=int,
|
||||
description=u"Choisissez ici la salle en fonction "
|
||||
u"du nombres de personnes potentiellement intéressé par votre intervention "+
|
||||
u"l'organisation se réserve le droit de changer la salle (avec votre accord)."
|
||||
|
||||
)
|
||||
|
||||
name = StringField(u'Le nom de votre ',
|
||||
name = StringField(
|
||||
u'Le nom de votre ',
|
||||
[validators.DataRequired(u'Vous devez spécifier un nom pour votre intérvention'),
|
||||
validators.Length(min=1, max=80, message='entre 1 et 80 car')],
|
||||
filters=[strip_filter])
|
||||
filters=[strip_filter]
|
||||
)
|
||||
|
||||
description = TextAreaField(u'Décrivez ici quelques détails à propos de votre intervention ',
|
||||
description = TextAreaField(
|
||||
u'Décrivez ici quelques détails à propos de votre intervention ',
|
||||
[validators.Optional(), validators.Length(max=1000000)],
|
||||
filters=[strip_filter]
|
||||
)
|
||||
|
||||
|
||||
class ConfUpdateForm(ConfCreateForm):
|
||||
uid = HiddenField()
|
||||
|
||||
|
||||
class SalleForm(MyBaseForm):
|
||||
year_uid = SelectField(u'Année', coerce=int)
|
||||
phy_salle_id = SelectField('Salle Physique', coerce=int)
|
||||
place_type = SelectField('Type', choices=[('Conference',u'Conférence'),
|
||||
('Stand','Stand'), ('Atelier','Atelier'), ('Table ronde','Table ronde'),
|
||||
('MAO','MAO'), ('Repas','Repas / Snack'), ('Autres','Autres') ])
|
||||
place_type = SelectField('Type', choices=[('Conference', u'Conférence'),
|
||||
('Stand', 'Stand'), ('Atelier', 'Atelier'),
|
||||
('Table ronde', 'Table ronde'),
|
||||
('MAO', 'MAO'), ('Repas', 'Repas / Snack'), ('Autres', 'Autres')])
|
||||
name = StringField('Nom de la salle', [validators.Length(min=1, max=40)],
|
||||
filters=[strip_filter])
|
||||
description = TextAreaField('Description',
|
||||
filters=[strip_filter])
|
||||
|
||||
|
||||
class EditSalleForm(SalleForm):
|
||||
salle_id = HiddenField()
|
||||
|
||||
|
||||
class SallePhyForm(MyBaseForm):
|
||||
name = StringField('Nom de la salle', [validators.Length(min=1, max=40)],
|
||||
filters=[strip_filter])
|
||||
@@ -177,19 +220,21 @@ class SallePhyForm(MyBaseForm):
|
||||
description = TextAreaField('Description',
|
||||
filters=[strip_filter])
|
||||
|
||||
|
||||
class EditSallePhyForm(SallePhyForm):
|
||||
uid = HiddenField()
|
||||
|
||||
class PlaceCreateForm(MyBaseForm):
|
||||
|
||||
class PlaceCreateForm(MyBaseForm):
|
||||
place_type = SelectField('Type', choices=PLACE_TYPE)
|
||||
|
||||
display_name = StringField(u'Nom affiché', [validators.Length(min=1, max=20)],
|
||||
filters=[strip_filter])
|
||||
name = StringField('Nom Complet', [validators.Length(min=1, max=80)],
|
||||
filters=[strip_filter])
|
||||
gps_coord = StringField(u'Coordonnées GPS', [validators.Length(max=30),
|
||||
validators.Regexp( "^[0-9]+\.?[0-9]+,[0-9]+\.?[0-9]+$",
|
||||
gps_coord = StringField(u'Coordonnées GPS',
|
||||
[validators.Length(max=30),
|
||||
validators.Regexp("^[0-9]+\.?[0-9]+,[0-9]+\.?[0-9]+$",
|
||||
message=u"Le GPS devrait être sous la forme 43.6158372,7.0723401")],
|
||||
filters=[strip_filter])
|
||||
adresse = TextAreaField('Adresse', [validators.Length(max=100)],
|
||||
@@ -205,29 +250,31 @@ class PlaceCreateForm(MyBaseForm):
|
||||
|
||||
created_by = HiddenField()
|
||||
|
||||
|
||||
class PlaceUpdateForm(PlaceCreateForm):
|
||||
place_id = HiddenField()
|
||||
|
||||
|
||||
def captcha_check(form, field):
|
||||
if form.meta.csrf_context.get('Captcha')!=field.data:
|
||||
if form.meta.csrf_context.get('Captcha') != field.data:
|
||||
raise ValidationError(u"la vérification captcha est invalide.")
|
||||
|
||||
|
||||
class UserPasswordForm(MyBaseForm):
|
||||
uid = HiddenField()
|
||||
password = PasswordField("Mot de passe",[
|
||||
password = PasswordField("Mot de passe", [
|
||||
validators.Length(max=128, message=u"128 car. maximum"),
|
||||
validators.required(message=u"Ce champ est obligatoire"),
|
||||
validators.EqualTo('confirm', message=u'Les password ne sont pas équivalents') ],
|
||||
validators.EqualTo('confirm', message=u'Les password ne sont pas équivalents')],
|
||||
filters=[strip_filter]
|
||||
)
|
||||
confirm = PasswordField('Confirmez')
|
||||
|
||||
class UserRegisterForm(MyBaseForm):
|
||||
|
||||
class UserRegisterForm(MyBaseForm):
|
||||
nom = StringField(u'Nom', [
|
||||
validators.Length(max=80, message=u"80 car. maximum"),
|
||||
validators.required(message=u"Ce champ est obligatoire") ],
|
||||
validators.required(message=u"Ce champ est obligatoire")],
|
||||
filters=[strip_filter]
|
||||
)
|
||||
prenom = StringField(u'Prénom', [
|
||||
@@ -240,45 +287,47 @@ class UserRegisterForm(MyBaseForm):
|
||||
validators.Email(message=u"Essayez aussi avec une adresse e-mail valide"),
|
||||
validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = u"Une adresse e-mail valide." +
|
||||
u"Cette adresse ne sera pas rendue publique, "+
|
||||
description=u"Une adresse e-mail valide." +
|
||||
u"Cette adresse ne sera pas rendue publique, " +
|
||||
u"et ne sera pas divulguée à des tiers."
|
||||
)
|
||||
captcha = StringField(u'Captcha', [validators.Length(max=8), captcha_check],
|
||||
filters=[strip_filter]
|
||||
)
|
||||
|
||||
|
||||
class ProfilForm(MyBaseForm):
|
||||
id = HiddenField()
|
||||
user_id = HiddenField()
|
||||
nom = StringField(u'Nom', [validators.Length(max=80)],
|
||||
filters=[strip_filter],
|
||||
description = u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
description=u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
u"pas autorisée à l'exception des points, traits d'union, " +
|
||||
u"apostrophes et tirets bas."
|
||||
)
|
||||
prenom = StringField(u'Prénom', [validators.Length(max=80)],
|
||||
filters=[strip_filter],
|
||||
description = u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
description=u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
u"pas autorisée à l'exception des points, traits d'union, " +
|
||||
u"apostrophes et tirets bas."
|
||||
)
|
||||
pseudo = StringField(u'Pseudo', [validators.Length(max=80)],
|
||||
filters=[strip_filter],
|
||||
description = "Votre pseudo d'usage sur la toile."
|
||||
description="Votre pseudo d'usage sur la toile."
|
||||
)
|
||||
mail = StringField(u'Adresse électronique', [validators.optional(), validators.Email(), validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = u"Une adresse e-mail valide. Tous les messages de ce système" +
|
||||
u"seront envoyés à cette adresse. Cette adresse ne sera pas rendue publique,"+
|
||||
description=u"Une adresse e-mail valide. Tous les messages de ce système" +
|
||||
u"seront envoyés à cette adresse. Cette adresse ne sera pas rendue publique," +
|
||||
u"et ne sera utilisée que si vous désirez obtenir un nouveau mot de passe ou" +
|
||||
u"recevoir personnellement certaines nouvelles ou avertissements."
|
||||
)
|
||||
|
||||
phone = StringField(u'Mobile', [validators.optional(), validators.Length(max=10),
|
||||
validators.Regexp("\d+", message=u"Le numéro de téléphone mobile ne doit contenir que des chiffres")],
|
||||
validators.Regexp("\d+",
|
||||
message=u"Le numéro de téléphone mobile ne doit contenir que des chiffres")],
|
||||
filters=[strip_filter],
|
||||
description = u"Un numéro de mobile valide. Afin de pouvoir rester en" +
|
||||
description=u"Un numéro de mobile valide. Afin de pouvoir rester en" +
|
||||
u"contact avec les personne de l'organisation, et pour vos échanges. " +
|
||||
u"Ce numéro ne sera pas publié, et ne sera utilisé que si " +
|
||||
u"vous désirez recevoir personnellement certaines nouvelles ou alertes."
|
||||
@@ -286,19 +335,19 @@ class ProfilForm(MyBaseForm):
|
||||
|
||||
website = StringField(u'Site web', [validators.optional(), validators.URL(), validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = "Renseignez ici votre site Web."
|
||||
description="Renseignez ici votre site Web."
|
||||
)
|
||||
|
||||
gpg_key = TextAreaField(u'Ma clé GPG',
|
||||
[validators.optional(), validators.Length(max=9000)],
|
||||
filters=[strip_filter],
|
||||
description = u"Vous pouvez insérer votre clé GPG publique pour " +
|
||||
description=u"Vous pouvez insérer votre clé GPG publique pour " +
|
||||
u"échanger des données sécurisées."
|
||||
)
|
||||
soc_link = TextAreaField('Mes autres identifiants',
|
||||
[validators.optional(), validators.Length(max=1000000)],
|
||||
filters=[strip_filter],
|
||||
description = u"Vous pouvez insérer ici d'autres identifiants " +
|
||||
description=u"Vous pouvez insérer ici d'autres identifiants " +
|
||||
u"permettant aux autres de vous retrouver sur la toile (IRC, jabber, réseaux sociaux etc)."
|
||||
)
|
||||
|
||||
@@ -312,16 +361,16 @@ class ProfilForm(MyBaseForm):
|
||||
class MiamForm(MyBaseForm):
|
||||
RepasVendredi = SelectField(u'Je viens au dîner convivial vendredi soir',
|
||||
choices=YESNO,
|
||||
description = u"L'organisation réserve le " +
|
||||
description=u"L'organisation réserve le " +
|
||||
u"restaurant pour ce dîner convivial. De petites " +
|
||||
u"animations vous seront proposées. " +
|
||||
u"Il nous faut savoir si on vous réserve une place !"
|
||||
)
|
||||
|
||||
RepasSamediMidi = SelectField(u'Je déjeune sur place samedi midi', choices=YESNO )
|
||||
RepasSamediMidi = SelectField(u'Je déjeune sur place samedi midi', choices=YESNO)
|
||||
|
||||
RepasSamediSoir = SelectField(u'Je viens au repas de clôture samedi soir', choices=YESNO,
|
||||
description = u"L'organisation réserve le " +
|
||||
description=u"L'organisation réserve le " +
|
||||
u"restaurant pour le dîner de clôture. De petites " +
|
||||
u"animations vous seront proposées. " +
|
||||
u"Il nous faut savoir si on vous réserve une place !"
|
||||
@@ -329,14 +378,14 @@ class MiamForm(MyBaseForm):
|
||||
|
||||
Allergies = TextAreaField(u'Allergies', [validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = u"Entrez ici vos allergies éventuelles, " +
|
||||
description=u"Entrez ici vos allergies éventuelles, " +
|
||||
u"Ce que votre organisme ne supporte absolument pas." +
|
||||
u"L'organisation fera alors en sorte de les éviter ou " +
|
||||
u"de les identifier explicitement."
|
||||
)
|
||||
Contraintes = TextAreaField(u'Contraintes', [validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = u"Entrez ici ce que vous n'aimez pas, " +
|
||||
description=u"Entrez ici ce que vous n'aimez pas, " +
|
||||
u"Cela ne consititue pas pour vous un allérgène, " +
|
||||
u"mais vous n'aimez simplement pas. (Gluten / Laitage etc ...)"
|
||||
)
|
||||
@@ -344,13 +393,13 @@ class MiamForm(MyBaseForm):
|
||||
|
||||
class DateStartConfidenceForm(MyBaseForm):
|
||||
ConfidenceLevel = [
|
||||
("0",u"exactement à"),
|
||||
("1",u"approximativement à"),
|
||||
("2",u"à peu près (5 à 15 min) vers"),
|
||||
("3",u"à une vache près (1h) vers")
|
||||
("0", u"exactement à"),
|
||||
("1", u"approximativement à"),
|
||||
("2", u"à peu près (5 à 15 min) vers"),
|
||||
("3", u"à une vache près (1h) vers")
|
||||
]
|
||||
DayChoice = [("4","Jeudi"), ("5","Vendredi"), ("6","Samedi"), ("0","Dimanche"), ("1","Lundi")]
|
||||
Day = SelectField(u'Jour', choices=DayChoice )
|
||||
DayChoice = [("4", "Jeudi"), ("5", "Vendredi"), ("6", "Samedi"), ("0", "Dimanche"), ("1", "Lundi")]
|
||||
Day = SelectField(u'Jour', choices=DayChoice)
|
||||
Confidence = SelectField(u'Confiance', choices=ConfidenceLevel)
|
||||
Hour = StringField(u'Heure', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
@@ -359,13 +408,14 @@ class DateStartConfidenceForm(MyBaseForm):
|
||||
filters=[strip_filter])
|
||||
start_time = HiddenField()
|
||||
|
||||
|
||||
class ItineraireForm(Form):
|
||||
start_place = SelectField(u'En partant de', coerce=int)
|
||||
arrival_place = SelectField(u'et à destination de', coerce=int)
|
||||
itin_id = HiddenField()
|
||||
|
||||
class AddItineraireForm(Form):
|
||||
|
||||
class AddItineraireForm(Form):
|
||||
itin = FormField(ItineraireForm)
|
||||
distance = DecimalField(u'Distance', [validators.Length(min=1, max=4)],
|
||||
filters=[strip_filter])
|
||||
@@ -382,32 +432,34 @@ class AddItineraireForm(Form):
|
||||
tr_avion = BooleanField(u'en avion')
|
||||
description = TextAreaField(u'Description de l\'itinéraire')
|
||||
|
||||
|
||||
class AddMember(MyBaseForm):
|
||||
tiers_uid = HiddenField()
|
||||
nom = StringField(u'Nom', [validators.Length(max=80)],
|
||||
filters=[strip_filter],
|
||||
description = u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
description=u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
u"pas autorisée à l'exception des points, traits d'union, " +
|
||||
u"apostrophes et tirets bas."
|
||||
)
|
||||
prenom = StringField(u'Prénom', [validators.Length(max=80)],
|
||||
filters=[strip_filter],
|
||||
description = u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
description=u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
u"pas autorisée à l'exception des points, traits d'union, " +
|
||||
u"apostrophes et tirets bas."
|
||||
)
|
||||
email = StringField(u'Email', [validators.required(),
|
||||
validators.length(max=10),
|
||||
validators.Email(message='Ceci ne ressemble pas à une adresse valide')],
|
||||
description=u"Afin d'éviter la duplication d'information et les doublons inutile, "+
|
||||
u"pensez d'abord à lui demander de confirmer le mail qu'il a utilisé lors de "+
|
||||
description=u"Afin d'éviter la duplication d'information et les doublons inutile, " +
|
||||
u"pensez d'abord à lui demander de confirmer le mail qu'il a utilisé lors de " +
|
||||
u"son inscription sur le site.")
|
||||
add = SubmitField('Ajouter des membres')
|
||||
|
||||
|
||||
class TiersForm(MyBaseForm):
|
||||
name = StringField(u'Nom', [validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
description=u"Les espaces sont autorisés, la ponctuation n'est " +
|
||||
u"pas autorisée à l'exception des points, traits d'union, " +
|
||||
u"apostrophes et tirets bas."
|
||||
)
|
||||
@@ -416,19 +468,20 @@ class TiersForm(MyBaseForm):
|
||||
|
||||
website = StringField(u'Site web', [validators.optional(), validators.URL(), validators.Length(max=100)],
|
||||
filters=[strip_filter],
|
||||
description = "Renseignez ici le site Web."
|
||||
description="Renseignez ici le site Web."
|
||||
)
|
||||
|
||||
description = TextAreaField('Descriptif',
|
||||
[validators.optional(), validators.Length(max=1000000)],
|
||||
filters=[strip_filter],
|
||||
description = u"Vous pouvez insérer les détails"
|
||||
description=u"Vous pouvez insérer les détails"
|
||||
)
|
||||
|
||||
membership = FieldList(FormField(TiersMember))
|
||||
|
||||
roles = FieldList(FormField(TiersRole))
|
||||
|
||||
|
||||
class UpdateTiersForm(TiersForm):
|
||||
uid = HiddenField()
|
||||
tiers_id = HiddenField()
|
||||
@@ -438,23 +491,25 @@ class ExchCateg(MyBaseForm):
|
||||
exch_type = HiddenField()
|
||||
exch_subtype = StringField(u'Catégorie', [validators.Length(max=80)],
|
||||
filters=[strip_filter],
|
||||
description = "Le nom de la categorie"
|
||||
description="Le nom de la categorie"
|
||||
)
|
||||
description = TextAreaField('Description',
|
||||
filters=[strip_filter])
|
||||
|
||||
|
||||
class UpdateExchangeForm(MyBaseForm):
|
||||
exch_id = HiddenField()
|
||||
|
||||
|
||||
class AskCForm(ItineraireForm):
|
||||
ConfidenceLevel = [
|
||||
("0",u"exactement à"),
|
||||
("1",u"approximativement à"),
|
||||
("2",u"à peu près (5 à 15 min) vers"),
|
||||
("3",u"à une vache près (1h) vers")
|
||||
("0", u"exactement à"),
|
||||
("1", u"approximativement à"),
|
||||
("2", u"à peu près (5 à 15 min) vers"),
|
||||
("3", u"à une vache près (1h) vers")
|
||||
]
|
||||
DayChoice = [("4","Jeudi"), ("5","Vendredi"), ("6","Samedi"), ("0","Dimanche"), ("1","Lundi")]
|
||||
Day_start = SelectField(u'Jour', choices=DayChoice )
|
||||
DayChoice = [("4", "Jeudi"), ("5", "Vendredi"), ("6", "Samedi"), ("0", "Dimanche"), ("1", "Lundi")]
|
||||
Day_start = SelectField(u'Jour', choices=DayChoice)
|
||||
Confidence = SelectField(u'Confiance', choices=ConfidenceLevel)
|
||||
Hour_start = StringField(u'Heure', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
@@ -466,25 +521,28 @@ class AskCForm(ItineraireForm):
|
||||
arrival_place = SelectField(u'et à destination de', coerce=int)
|
||||
itin_id = HiddenField()
|
||||
|
||||
|
||||
class AskHForm(MyBaseForm):
|
||||
DayChoice = [("4",u"Jeudi à Vendredi"), ("5",u"Vendredi à Samedi"), ("6",u"Samedi à Dimanche"), ("0",u"Dimanche à Lundi")]
|
||||
Day_start = SelectField(u'Pour la nuit de', choices=DayChoice )
|
||||
DayChoice = [("4", u"Jeudi à Vendredi"), ("5", u"Vendredi à Samedi"), ("6", u"Samedi à Dimanche"),
|
||||
("0", u"Dimanche à Lundi")]
|
||||
Day_start = SelectField(u'Pour la nuit de', choices=DayChoice)
|
||||
start_time = HiddenField()
|
||||
description = TextAreaField(u'Description de vos contraintes éventuelles', filters=[strip_filter],
|
||||
description = u"Décrivez ici vos souhaits et éventuellement "
|
||||
description=u"Décrivez ici vos souhaits et éventuellement "
|
||||
+ u"les contraintes à prendre en compte. N'hésitez pas à donner des détails."
|
||||
)
|
||||
|
||||
|
||||
class AskMForm(MyBaseForm):
|
||||
DayChoice = [("4","Jeudi"), ("5","Vendredi"), ("6","Samedi"), ("0","Dimanche"), ("1","Lundi")]
|
||||
Day_start = SelectField(u"à partir de", choices=DayChoice )
|
||||
DayChoice = [("4", "Jeudi"), ("5", "Vendredi"), ("6", "Samedi"), ("0", "Dimanche"), ("1", "Lundi")]
|
||||
Day_start = SelectField(u"à partir de", choices=DayChoice)
|
||||
Hour_start = StringField(u'vers', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
validators.Regexp("\d+:\d+",
|
||||
message=u"doit être sous la forme HH:MM")],
|
||||
filters=[strip_filter])
|
||||
start_time = HiddenField()
|
||||
Day_end = SelectField(u"Jusqu'à", choices=DayChoice )
|
||||
Day_end = SelectField(u"Jusqu'à", choices=DayChoice)
|
||||
Hour_end = StringField(u'vers', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
validators.Regexp("\d+:\d+",
|
||||
@@ -492,22 +550,23 @@ class AskMForm(MyBaseForm):
|
||||
filters=[strip_filter])
|
||||
end_time = HiddenField()
|
||||
exch_categ = SelectField(u'Catégorie de matériel', coerce=int,
|
||||
description = u"Choisissez une catégorie de bien"
|
||||
description=u"Choisissez une catégorie de bien"
|
||||
)
|
||||
description = TextAreaField(u'Description du bien', filters=[strip_filter],
|
||||
description = u"Décrivez ici les biens que vous souhaitez"
|
||||
description=u"Décrivez ici les biens que vous souhaitez"
|
||||
+ u"échanger. N'hésitez pas à donner des détails."
|
||||
)
|
||||
|
||||
|
||||
class PropCForm(ItineraireForm):
|
||||
ConfidenceLevel = [
|
||||
("0",u"exactement à"),
|
||||
("1",u"approximativement à"),
|
||||
("2",u"à peu près (5 à 15 min) vers"),
|
||||
("3",u"à une vache près (1h) vers")
|
||||
("0", u"exactement à"),
|
||||
("1", u"approximativement à"),
|
||||
("2", u"à peu près (5 à 15 min) vers"),
|
||||
("3", u"à une vache près (1h) vers")
|
||||
]
|
||||
DayChoice = [("4","Jeudi"), ("5","Vendredi"), ("6","Samedi"), ("0","Dimanche"), ("1","Lundi")]
|
||||
Day_start = SelectField(u'Jour', choices=DayChoice )
|
||||
DayChoice = [("4", "Jeudi"), ("5", "Vendredi"), ("6", "Samedi"), ("0", "Dimanche"), ("1", "Lundi")]
|
||||
Day_start = SelectField(u'Jour', choices=DayChoice)
|
||||
Confidence = SelectField(u'Confiance', choices=ConfidenceLevel)
|
||||
Hour_start = StringField(u'Heure', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
@@ -519,57 +578,69 @@ class PropCForm(ItineraireForm):
|
||||
arrival_place = SelectField(u'et à destination de', coerce=int)
|
||||
itin_id = HiddenField()
|
||||
|
||||
|
||||
class PropHForm(MyBaseForm):
|
||||
DayChoice = [("4",u"Jeudi à Vendredi"), ("5",u"Vendredi à Samedi"), ("6",u"Samedi à Dimanche"), ("0",u"Dimanche à Lundi")]
|
||||
Day_start = SelectField(u'Pour la nuit de', choices=DayChoice )
|
||||
DayChoice = [("4", u"Jeudi à Vendredi"), ("5", u"Vendredi à Samedi"), ("6", u"Samedi à Dimanche"),
|
||||
("0", u"Dimanche à Lundi")]
|
||||
Day_start = SelectField(u'Pour la nuit de', choices=DayChoice)
|
||||
start_time = HiddenField()
|
||||
exch_categ = SelectField(u'Type de couchage', coerce=int,
|
||||
description = u"Indiquez ici le type de couchage proposé")
|
||||
description=u"Indiquez ici le type de couchage proposé")
|
||||
description = TextAreaField(u'Quelques mots autour du logement que vous proposez', filters=[strip_filter],
|
||||
description = u"Décrivez ici quelques détails sur le logement que vous souhaitez "
|
||||
description=u"Décrivez ici quelques détails sur le logement que vous souhaitez "
|
||||
+ u"proposer, les contraintes à prendre en compte. N'hésitez pas à donner des détails."
|
||||
)
|
||||
place_id = SelectField(u'Emplacement', coerce=int,
|
||||
description = u"Indiquez ici une des adresses que vous avez proposé")
|
||||
description=u"Indiquez ici une des adresses que vous avez proposé")
|
||||
|
||||
|
||||
class PropMForm(MyBaseForm):
|
||||
DayChoice = [("4","Jeudi"), ("5","Vendredi"), ("6","Samedi"), ("0","Dimanche"), ("1","Lundi")]
|
||||
Day_start = SelectField(u"à partir de", choices=DayChoice )
|
||||
DayChoice = [("4", "Jeudi"), ("5", "Vendredi"), ("6", "Samedi"), ("0", "Dimanche"), ("1", "Lundi")]
|
||||
Day_start = SelectField(u"à partir de", choices=DayChoice)
|
||||
Hour_start = StringField(u'vers', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
validators.Regexp("\d+:\d+",
|
||||
message=u"doit être sous la forme HH:MM")],
|
||||
filters=[strip_filter])
|
||||
start_time = HiddenField()
|
||||
Day_end = SelectField(u"Jusqu'a ", choices=DayChoice )
|
||||
Day_end = SelectField(u"Jusqu'a ", choices=DayChoice)
|
||||
Hour_end = StringField(u'vers', [validators.Length(max=5,
|
||||
message=u"doit faire au maximum 5 caractères"),
|
||||
validators.Regexp("\d+:\d+",
|
||||
message=u"doit être sous la forme HH:MM")],
|
||||
filters=[strip_filter])
|
||||
end_time = HiddenField()
|
||||
exch_categ = SelectField(u'Catégorie de matériel', coerce=int,
|
||||
description = u"Choisissez une catégorie de bien matériel"
|
||||
exch_categ = SelectField(
|
||||
u'Catégorie de matériel', coerce=int,
|
||||
description=u"Choisissez une catégorie de bien matériel"
|
||||
)
|
||||
description = TextAreaField(u'Ajoutez quelques mots autour du matériel que vous proposez', filters=[strip_filter],
|
||||
description = u"Décrivez ici quelques détails sur le matériel que vous souhaitez "
|
||||
+ u"proposer. N'hésitez pas à donner des détails."
|
||||
description = TextAreaField(
|
||||
u'Ajoutez quelques mots autour du matériel que vous proposez',
|
||||
filters=[strip_filter],
|
||||
description=u"Décrivez ici quelques détails sur le matériel "
|
||||
u"que vous souhaitez proposer. N'hésitez pas à donner des détails."
|
||||
)
|
||||
|
||||
|
||||
class UpdateAskCForm(AskCForm, UpdateExchangeForm):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateAskHForm(AskHForm, UpdateExchangeForm):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateAskMForm(AskMForm, UpdateExchangeForm):
|
||||
pass
|
||||
|
||||
|
||||
class UpdatePropCForm(PropCForm, UpdateExchangeForm):
|
||||
pass
|
||||
|
||||
|
||||
class UpdatePropHForm(PropHForm, UpdateExchangeForm):
|
||||
pass
|
||||
|
||||
|
||||
class UpdatePropMForm(PropMForm, UpdateExchangeForm):
|
||||
pass
|
||||
|
||||
+62
-54
@@ -4,18 +4,25 @@ from datetime import timedelta, datetime
|
||||
import itertools
|
||||
from jm2l.const import CurrentYear
|
||||
|
||||
|
||||
def get_current_year():
|
||||
""" This function is intended to return the year of the next edition """
|
||||
return CurrentYear
|
||||
|
||||
|
||||
class DummySejour(object):
|
||||
|
||||
def __init__(self, event):
|
||||
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
|
||||
if self.Me:
|
||||
self.Sejour = DBSession.query(Sejour)\
|
||||
.filter(Sejour.user_id==self.Me.uid)\
|
||||
.filter(Sejour.for_year==self.CurrentEventYear.year_uid)\
|
||||
self.Sejour = DBSession.query(Sejour) \
|
||||
.filter(Sejour.user_id == self.Me.uid) \
|
||||
.filter(Sejour.for_year == self.CurrentEventYear.year_uid) \
|
||||
.first()
|
||||
|
||||
|
||||
class Sejour_helpers(DummySejour):
|
||||
|
||||
def __init__(self, event):
|
||||
@@ -27,78 +34,78 @@ class Sejour_helpers(DummySejour):
|
||||
# This function return the start of the event
|
||||
return self.CurrentYear
|
||||
|
||||
def PossibleDate(self, typedate="arrival"):
|
||||
def PossibleDate(self, type_date="arrival"):
|
||||
arrival, departure = False, False
|
||||
TabResult = list()
|
||||
if typedate == "arrival":
|
||||
tab_result = list()
|
||||
if type_date == "arrival":
|
||||
# Let's say people should arrive until 2 day before
|
||||
arrival = True
|
||||
myDayRange = xrange(2,-1,-1)
|
||||
elif typedate == "departure":
|
||||
my_day_range = range(2, -1, -1)
|
||||
elif type_date == "departure":
|
||||
# Let's say people should go back home until 2 day after
|
||||
departure = True
|
||||
myDayRange = xrange(3)
|
||||
my_day_range = range(3)
|
||||
else:
|
||||
return TabResult
|
||||
return tab_result
|
||||
|
||||
if self.Sejour:
|
||||
ArrDate = datetime.strftime(self.Sejour.arrival_time,"%d %B %Y").decode('utf-8')
|
||||
DepDate = datetime.strftime(self.Sejour.depart_time,"%d %B %Y").decode('utf-8')
|
||||
arr_date = datetime.strftime(self.Sejour.arrival_time, "%d %B %Y")
|
||||
dep_date = datetime.strftime(self.Sejour.depart_time, "%d %B %Y")
|
||||
else:
|
||||
ArrDate = datetime.strftime( self.CurrentEventYear.start_time,"%d %B %Y" ).decode('utf-8')
|
||||
DepDate = datetime.strftime( self.CurrentEventYear.end_time,"%d %B %Y" ).decode('utf-8')
|
||||
arr_date = datetime.strftime(self.CurrentEventYear.start_time, "%d %B %Y")
|
||||
dep_date = datetime.strftime(self.CurrentEventYear.end_time, "%d %B %Y")
|
||||
|
||||
for oneday in myDayRange:
|
||||
for one_day in my_day_range:
|
||||
if arrival:
|
||||
TmpDay = self.CurrentEventYear.end_time - timedelta(days=oneday)
|
||||
tmp_day = self.CurrentEventYear.end_time - timedelta(days=one_day)
|
||||
elif departure:
|
||||
TmpDay = self.CurrentEventYear.start_time + timedelta(days=oneday)
|
||||
DayName = datetime.strftime(TmpDay,"%A")
|
||||
DayNum = datetime.strftime(TmpDay,"%d/%m/%y")
|
||||
DayString = datetime.strftime(TmpDay,"%d %B %Y").decode('utf-8')
|
||||
if arrival and ArrDate==DayString:
|
||||
TabResult.append((DayNum, DayName, 'selected="selected"'))
|
||||
elif departure and DepDate==DayString:
|
||||
TabResult.append((DayNum, DayName, 'selected="selected"'))
|
||||
tmp_day = self.CurrentEventYear.start_time + timedelta(days=one_day)
|
||||
day_name = datetime.strftime(tmp_day, "%A")
|
||||
day_num = datetime.strftime(tmp_day, "%d/%m/%y")
|
||||
day_string = datetime.strftime(tmp_day, "%d %B %Y")
|
||||
if arrival and arr_date == day_string:
|
||||
tab_result.append((day_num, day_name, 'selected="selected"'))
|
||||
elif departure and dep_date == day_string:
|
||||
tab_result.append((day_num, day_name, 'selected="selected"'))
|
||||
else:
|
||||
TabResult.append((DayNum, DayName, ""))
|
||||
return TabResult
|
||||
tab_result.append((day_num, day_name, ""))
|
||||
return tab_result
|
||||
|
||||
def PossibleTime(self, typedate="arrival"):
|
||||
ArrTime, DepTime = "10:00", "19:00"
|
||||
TabResult = list()
|
||||
def PossibleTime(self, type_date="arrival"):
|
||||
arr_time, dep_time = "10:00", "19:00"
|
||||
tab_result = list()
|
||||
|
||||
if self.Sejour:
|
||||
ArrTime = datetime.strftime(self.Sejour.arrival_time,"%H:%M")
|
||||
DepTime = datetime.strftime(self.Sejour.depart_time,"%H:%M")
|
||||
arr_time = datetime.strftime(self.Sejour.arrival_time, "%H:%M")
|
||||
dep_time = datetime.strftime(self.Sejour.depart_time, "%H:%M")
|
||||
|
||||
for hour in range(24):
|
||||
for minutes in range(0,60,10):
|
||||
StrTime = "%.2d:%.2d" % (hour, minutes)
|
||||
DispTime = "%dh%.2d" % (hour, minutes)
|
||||
if typedate == "arrival" and StrTime==ArrTime:
|
||||
TabResult.append( (StrTime, DispTime, 'selected="selected"') )
|
||||
elif typedate == "departure" and StrTime==DepTime:
|
||||
TabResult.append( (StrTime, DispTime, 'selected="selected"') )
|
||||
for minutes in range(0, 60, 10):
|
||||
str_time = "%.2d:%.2d" % (hour, minutes)
|
||||
disp_time = "%dh%.2d" % (hour, minutes)
|
||||
if type_date == "arrival" and str_time == arr_time:
|
||||
tab_result.append((str_time, disp_time, 'selected="selected"'))
|
||||
elif type_date == "departure" and str_time == dep_time:
|
||||
tab_result.append((str_time, disp_time, 'selected="selected"'))
|
||||
else:
|
||||
TabResult.append( (StrTime, DispTime, "") )
|
||||
return TabResult
|
||||
tab_result.append((str_time, disp_time, ""))
|
||||
return tab_result
|
||||
|
||||
def IsCheck(self, InputControl):
|
||||
ListControlA = ['Arrival', 'Departure']
|
||||
ListControlB = ['PMR', 'Cov', 'Bras', 'Other']
|
||||
if InputControl not in map(':'.join, itertools.product(ListControlA, ListControlB)):
|
||||
list_control_a = ['Arrival', 'Departure']
|
||||
list_control_b = ['PMR', 'Cov', 'Bras', 'Other']
|
||||
if InputControl not in map(':'.join, itertools.product(list_control_a, list_control_b)):
|
||||
return ""
|
||||
if self.Sejour:
|
||||
if InputControl.startswith('Arrival'):
|
||||
CtrlVal = 2**ListControlB.index(InputControl[8:])
|
||||
if self.Sejour.arrival_check & CtrlVal == CtrlVal:
|
||||
ctrl_val = 2 ** list_control_b.index(InputControl[8:])
|
||||
if self.Sejour.arrival_check & ctrl_val == ctrl_val:
|
||||
return "checked=\"checked\""
|
||||
else:
|
||||
return ""
|
||||
elif InputControl.startswith('Departure'):
|
||||
CtrlVal = 2**ListControlB.index(InputControl[10:])
|
||||
if self.Sejour.depart_check & CtrlVal == CtrlVal:
|
||||
ctrl_val = 2 ** list_control_b.index(InputControl[10:])
|
||||
if self.Sejour.depart_check & ctrl_val == ctrl_val:
|
||||
return "checked=\"checked\""
|
||||
else:
|
||||
return ""
|
||||
@@ -107,6 +114,7 @@ class Sejour_helpers(DummySejour):
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
class Orga_helpers(DummySejour):
|
||||
|
||||
def __init__(self, event):
|
||||
@@ -132,7 +140,7 @@ class Orga_helpers(DummySejour):
|
||||
]
|
||||
|
||||
def IsChecked(self, nb):
|
||||
nb = 2**nb
|
||||
nb = 2 ** nb
|
||||
if self.Sejour and self.Sejour.orga_part:
|
||||
if self.Sejour.orga_part & nb == nb:
|
||||
return "checked=\"checked\""
|
||||
@@ -143,9 +151,9 @@ class Orga_helpers(DummySejour):
|
||||
|
||||
def ChoosedList(self):
|
||||
""" Return choice validated by user """
|
||||
ListOrga = []
|
||||
for num in range(0,len(self.Orga_tasks)):
|
||||
curs = 2**num
|
||||
list_orga = []
|
||||
for num in range(0, len(self.Orga_tasks)):
|
||||
curs = 2 ** num
|
||||
if self.Sejour.orga_part & curs == curs:
|
||||
ListOrga.append(self.Orga_tasks[num])
|
||||
return ListOrga
|
||||
list_orga.append(self.Orga_tasks[num])
|
||||
return list_orga
|
||||
|
||||
+152
-125
@@ -15,29 +15,39 @@ from sqlalchemy import (
|
||||
Enum,
|
||||
Boolean,
|
||||
ForeignKey
|
||||
)
|
||||
)
|
||||
|
||||
from slugify import slugify
|
||||
from webhelpers.text import urlify
|
||||
from webhelpers.paginate import PageURL_WebOb, Page
|
||||
from webhelpers.date import time_ago_in_words
|
||||
# from webhelpers.text import urlify
|
||||
from paginate import Page # PageURL_WebOb
|
||||
|
||||
from webhelpers2.date import time_ago_in_words
|
||||
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
from sqlalchemy.orm import (
|
||||
scoped_session,
|
||||
sessionmaker
|
||||
)
|
||||
)
|
||||
|
||||
from zope.sqlalchemy import ZopeTransactionExtension
|
||||
# from zope.sqlalchemy import ZopeTransactionExtension
|
||||
from zope.sqlalchemy import register
|
||||
from jm2l.const import CurrentYear
|
||||
|
||||
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()
|
||||
|
||||
|
||||
class TasksArea(Base):
|
||||
__tablename__ = 'staff_tasks_area'
|
||||
uid = Column(Integer, primary_key=True)
|
||||
@@ -49,40 +59,43 @@ class TasksArea(Base):
|
||||
def by_id(cls, uid):
|
||||
return DBSession.query(cls).filter(cls.uid == uid).first()
|
||||
|
||||
|
||||
class Tasks(Base):
|
||||
__tablename__ = 'staff_tasks'
|
||||
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)
|
||||
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 = Column(Integer, default=0)
|
||||
name = Column(Unicode(80))
|
||||
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
|
||||
def by_id(cls, uid):
|
||||
return DBSession.query(cls).filter(cls.uid == uid).first()
|
||||
|
||||
|
||||
class User_Event(Base):
|
||||
""" Créer le lien entre la personne et l' évenement en fonction de l'année"""
|
||||
__tablename__ = 'user_event_link'
|
||||
uid = Column(Integer, primary_key=True)
|
||||
event_uid = Column(Integer, ForeignKey('events.uid') )
|
||||
#, primary_key=True)
|
||||
event_uid = Column(Integer, ForeignKey('events.uid'))
|
||||
# , primary_key=True)
|
||||
#
|
||||
user_uid = Column(Integer, ForeignKey('users.uid') )
|
||||
#, primary_key=True)
|
||||
user_uid = Column(Integer, ForeignKey('users.uid'))
|
||||
# , primary_key=True)
|
||||
#
|
||||
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
|
||||
role = Column(Unicode(80))
|
||||
# Define some relation
|
||||
#user = relationship('User', backref=backref("events_assoc") )
|
||||
#event = relationship('events', backref=backref("users_assoc") )
|
||||
# user = relationship('User', backref=backref("events_assoc") )
|
||||
# event = relationship('events', backref=backref("users_assoc") )
|
||||
|
||||
|
||||
class JM2L_Year(Base):
|
||||
__tablename__ = 'jm2l_year'
|
||||
@@ -102,22 +115,22 @@ class JM2L_Year(Base):
|
||||
.filter(JM2L_Year.start_time ==
|
||||
DBSession.query(func.max(JM2L_Year.start_time))
|
||||
).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
|
||||
def AvailableTimeSlots(self, TimeStep=30):
|
||||
Available = self.end_time - self.start_time
|
||||
NbMinutes = Available.total_seconds()/60
|
||||
NbSteps = NbMinutes/TimeStep
|
||||
NbMinutes = Available.total_seconds() / 60
|
||||
NbSteps = NbMinutes / TimeStep
|
||||
# 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 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
|
||||
date_list = filter(lambda x:x.hour >= 10, date_list)
|
||||
date_list = filter(lambda x: x.hour >= 10, date_list)
|
||||
# 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
|
||||
|
||||
@property
|
||||
@@ -125,6 +138,7 @@ class JM2L_Year(Base):
|
||||
from .upload import MediaPath
|
||||
return sorted(MediaPath().get_all('presse', self.year_uid))
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = 'users'
|
||||
uid = Column(Integer, primary_key=True)
|
||||
@@ -152,8 +166,8 @@ class User(Base):
|
||||
wifi_pass = Column(Unicode(80), nullable=True)
|
||||
|
||||
# relations
|
||||
tiers = relationship('Tiers', secondary='user_tiers_link' )
|
||||
events = relationship('Event', secondary='user_event_link' )
|
||||
tiers = relationship('Tiers', secondary='user_tiers_link')
|
||||
events = relationship('Event', secondary='user_event_link')
|
||||
tiersship = relationship('User_Tiers', backref="matching_users")
|
||||
|
||||
@classmethod
|
||||
@@ -179,7 +193,7 @@ class User(Base):
|
||||
@classmethod
|
||||
def by_hash(cls, tsthash):
|
||||
for u in DBSession.query(cls):
|
||||
if u.my_hash==tsthash:
|
||||
if u.my_hash == tsthash:
|
||||
return u
|
||||
return None
|
||||
|
||||
@@ -187,53 +201,51 @@ class User(Base):
|
||||
def is_Intervenant(self):
|
||||
""" This property will return if User do an event on specified year """
|
||||
return DBSession.query(Event).join(User_Event) \
|
||||
.filter(User_Event.user_uid==self.uid) \
|
||||
.filter(Event.for_year==CurrentYear).count()
|
||||
.filter(User_Event.user_uid == self.uid) \
|
||||
.filter(Event.for_year == CurrentYear).count()
|
||||
|
||||
def is_IntervenantOnYear(self, year=CurrentYear):
|
||||
""" This property will return if User do an event on specified year """
|
||||
return DBSession.query(Event).join(User_Event) \
|
||||
.filter(User_Event.user_uid==self.uid) \
|
||||
.filter(Event.for_year==year).count()
|
||||
.filter(User_Event.user_uid == self.uid) \
|
||||
.filter(Event.for_year == year).count()
|
||||
|
||||
@property
|
||||
def is_crew(self, year=CurrentYear):
|
||||
""" 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) \
|
||||
.filter(Sejour.for_year == year)\
|
||||
.filter(Sejour.for_year == year) \
|
||||
.filter(User.uid == self.uid).first()
|
||||
if orga_checked:
|
||||
return orga_checked
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def year_events(self, EventType='All', year=CurrentYear):
|
||||
if EventType=='All':
|
||||
return filter(lambda e: e.for_year==year, self.events)
|
||||
if EventType == 'All':
|
||||
return list(filter(lambda e: e.for_year == year, self.events))
|
||||
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
|
||||
def my_hash(self):
|
||||
m = hashlib.sha1()
|
||||
m.update("Nobody inspects ")
|
||||
m.update("Nobody inspects ".encode('utf-8'))
|
||||
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:
|
||||
m.update(unicode.encode(self.pseudo,'utf8'))
|
||||
m.update(self.pseudo.encode('utf-8')) # unicode.encode(self.pseudo, 'utf8'))
|
||||
if self.prenom:
|
||||
m.update(unicode.encode(self.prenom,'utf8'))
|
||||
m.update(" the spammish repetition")
|
||||
m.update(self.prenom.encode('utf-8')) # unicode.encode(self.prenom, 'utf8'))
|
||||
m.update(" the spammish repetition".encode('utf-8'))
|
||||
return m.hexdigest()
|
||||
|
||||
@property
|
||||
def Photos(self):
|
||||
return DBSession.query(Media.filename) \
|
||||
.filter(Media.media_table=='users') \
|
||||
.filter(Media.media_type=='Image') \
|
||||
.filter(Media.media_table == 'users') \
|
||||
.filter(Media.media_type == 'Image') \
|
||||
.filter(Media.link_id == self.user_id).all()
|
||||
|
||||
@property
|
||||
@@ -253,6 +265,7 @@ class User(Base):
|
||||
|
||||
return argon2.verify(password, self.password)
|
||||
|
||||
|
||||
class TiersOpt(Base):
|
||||
__tablename__ = 'tiers_opt'
|
||||
uid = Column(Integer, primary_key=True)
|
||||
@@ -270,21 +283,22 @@ class TiersOpt(Base):
|
||||
|
||||
@classmethod
|
||||
def get_entity_type(cls):
|
||||
return DBSession.query(cls, func.count(Tiers.ent_type).label('count'))\
|
||||
.outerjoin(Tiers)\
|
||||
return DBSession.query(cls, func.count(Tiers.ent_type).label('count')) \
|
||||
.outerjoin(Tiers) \
|
||||
.group_by(cls.entity_type).all()
|
||||
|
||||
@classmethod
|
||||
def get_entity_sub_type(cls, entity_type):
|
||||
return DBSession.query(cls, func.count(Tiers.ent_type).label('count'))\
|
||||
.outerjoin(Tiers)\
|
||||
.filter(cls.entity_type == entity_type)\
|
||||
return DBSession.query(cls, func.count(Tiers.ent_type).label('count')) \
|
||||
.outerjoin(Tiers) \
|
||||
.filter(cls.entity_type == entity_type) \
|
||||
.group_by(cls.entity_subtype).all()
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, uid):
|
||||
return DBSession.query(cls).filter(cls.uid == uid).first()
|
||||
|
||||
|
||||
class Tiers(Base):
|
||||
__tablename__ = 'tiers'
|
||||
uid = Column(Integer, primary_key=True)
|
||||
@@ -298,14 +312,14 @@ class Tiers(Base):
|
||||
last_change = Column(DateTime, default=datetime.datetime.now)
|
||||
# relations
|
||||
ent_type = relationship('TiersOpt')
|
||||
#members = relationship('User', secondary='user_tiers_link' )
|
||||
# members = relationship('User', secondary='user_tiers_link' )
|
||||
members = relationship(User,
|
||||
secondary='user_tiers_link',
|
||||
backref=backref('associate', uselist=False),
|
||||
lazy='dynamic')
|
||||
creator_id = Column(Integer)
|
||||
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
|
||||
def by_id(cls, uid):
|
||||
@@ -317,7 +331,7 @@ class Tiers(Base):
|
||||
|
||||
@property
|
||||
def get_entity_type(self):
|
||||
return DBSession.query(TiersOpt)\
|
||||
return DBSession.query(TiersOpt) \
|
||||
.filter(TiersOpt.uid == self.tiers_type).first()
|
||||
|
||||
@property
|
||||
@@ -330,8 +344,8 @@ class Tiers(Base):
|
||||
@property
|
||||
def DocLinks(self):
|
||||
from .upload import MediaPath
|
||||
return zip( sorted( MediaPath().get_list('tiers', self.uid, 'Other') ),
|
||||
sorted( MediaPath().get_thumb('tiers', self.uid, 'Other') )
|
||||
return zip(sorted(MediaPath().get_list('tiers', self.uid, 'Other')),
|
||||
sorted(MediaPath().get_thumb('tiers', self.uid, 'Other'))
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -344,32 +358,35 @@ class Tiers(Base):
|
||||
from .upload import MediaPath
|
||||
return MediaPath().get_thumb('tiers', self.uid)
|
||||
|
||||
|
||||
class Role_Tiers(Base):
|
||||
""" Créer le lien entre le tiers et son rôle dans l'évenement en fonction de l'année"""
|
||||
__tablename__ = 'role_tiers_link'
|
||||
uid_role = Column(Integer, primary_key=True)
|
||||
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
|
||||
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'))
|
||||
event_uid = Column(Integer, default=None) # Optionnal link with Event
|
||||
|
||||
|
||||
class User_Tiers(Base):
|
||||
""" Créer le lien entre la personne et le tiers en fonction de l'année"""
|
||||
__tablename__ = 'user_tiers_link'
|
||||
uid_tiers = Column(Integer, primary_key=True)
|
||||
year_uid = Column(Integer, ForeignKey('jm2l_year.year_uid'), default=CurrentYear)
|
||||
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 = relationship(User, backref=backref("tiers_assoc") )
|
||||
user = relationship(User, backref=backref("tiers_assoc"))
|
||||
role = Column(Unicode(80))
|
||||
|
||||
|
||||
class Media(Base):
|
||||
__tablename__ = 'medias'
|
||||
media_id = Column(Integer, primary_key=True)
|
||||
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'))
|
||||
link_id = Column(Integer)
|
||||
mime_type = Column(Unicode(20))
|
||||
@@ -382,9 +399,10 @@ class Media(Base):
|
||||
|
||||
@property
|
||||
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)
|
||||
|
||||
|
||||
class SallePhy(Base):
|
||||
""" Représente une salle dans les locaux """
|
||||
__tablename__ = 'phy_salle'
|
||||
@@ -403,6 +421,7 @@ class SallePhy(Base):
|
||||
from .upload import MediaPath
|
||||
return MediaPath().get_list('salle', self.uid, 'Image')
|
||||
|
||||
|
||||
class Salles(Base):
|
||||
__tablename__ = 'salle'
|
||||
salle_id = Column(Integer, primary_key=True)
|
||||
@@ -415,10 +434,12 @@ class Salles(Base):
|
||||
last_change = Column(DateTime, default=datetime.datetime.now)
|
||||
|
||||
phy = relationship(SallePhy)
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, uid):
|
||||
return DBSession.query(cls).filter(cls.salle_id == uid).first()
|
||||
|
||||
|
||||
class Place(Base):
|
||||
__tablename__ = 'place'
|
||||
place_id = Column(Integer, primary_key=True)
|
||||
@@ -448,7 +469,8 @@ class Place(Base):
|
||||
if All:
|
||||
return DBSession.query(cls).all()
|
||||
else:
|
||||
return DBSession.query(cls).filter(cls.usage==True).all()
|
||||
return DBSession.query(cls).filter(cls.usage == True).all()
|
||||
|
||||
|
||||
class Itineraire(Base):
|
||||
__tablename__ = 'itineraire'
|
||||
@@ -473,6 +495,7 @@ class Itineraire(Base):
|
||||
start = relationship(Place, foreign_keys=[start_place])
|
||||
arrival = relationship(Place, foreign_keys=[arrival_place])
|
||||
|
||||
|
||||
class Exchange_Cat(Base):
|
||||
__tablename__ = 'exchange_category'
|
||||
cat_id = Column(Integer, primary_key=True)
|
||||
@@ -480,6 +503,7 @@ class Exchange_Cat(Base):
|
||||
exch_subtype = Column(Unicode(80))
|
||||
description = Column(UnicodeText)
|
||||
|
||||
|
||||
class Exchange(Base):
|
||||
__tablename__ = 'exchanges'
|
||||
exch_id = Column(Integer, primary_key=True)
|
||||
@@ -516,44 +540,44 @@ class Exchange(Base):
|
||||
|
||||
@classmethod
|
||||
def get_counters(cls):
|
||||
return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id))\
|
||||
.filter(cls.for_year==CurrentYear)\
|
||||
return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id)) \
|
||||
.filter(cls.for_year == CurrentYear) \
|
||||
.group_by(cls.exch_state, cls.exch_type, cls.exch_done)
|
||||
|
||||
@classmethod
|
||||
def get_my_counters(cls, uid):
|
||||
return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id))\
|
||||
.filter(cls.for_year==CurrentYear)\
|
||||
.filter( or_(cls.asker_id==uid, cls.provider_id==uid) )\
|
||||
return DBSession.query(cls.exch_state, cls.exch_type, cls.exch_done, func.count(cls.exch_id)) \
|
||||
.filter(cls.for_year == CurrentYear) \
|
||||
.filter(or_(cls.asker_id == uid, cls.provider_id == uid)) \
|
||||
.group_by(cls.exch_state, cls.exch_type, cls.exch_done)
|
||||
|
||||
@classmethod
|
||||
def get_overview(cls, uid):
|
||||
# Build a Dic with all exchange to save database access
|
||||
DicResult= {}
|
||||
for extype in ['F','C','H','M']:
|
||||
DicResult = {}
|
||||
for extype in ['F', 'C', 'H', 'M']:
|
||||
DicResult[extype] = {}
|
||||
for exstate in ['Ask','Proposal','Missing','Agree']:
|
||||
DicResult[extype][exstate]=[]
|
||||
DicResult[extype]['Counters']={'AllAsk':0, 'AllProp':0, 'AllAgree':0}
|
||||
Query = DBSession.query(cls)\
|
||||
.filter(cls.for_year==CurrentYear)\
|
||||
for exstate in ['Ask', 'Proposal', 'Missing', 'Agree']:
|
||||
DicResult[extype][exstate] = []
|
||||
DicResult[extype]['Counters'] = {'AllAsk': 0, 'AllProp': 0, 'AllAgree': 0}
|
||||
Query = DBSession.query(cls) \
|
||||
.filter(cls.for_year == CurrentYear) \
|
||||
.order_by(cls.start_time).all()
|
||||
for item in Query:
|
||||
if item.exch_done:
|
||||
DicResult[item.exch_type]['Counters']['AllAgree']+=1
|
||||
if item.exch_state=='Ask':
|
||||
DicResult[item.exch_type]['Counters']['AllAsk']+=1
|
||||
if item.exch_state=='Proposal':
|
||||
DicResult[item.exch_type]['Counters']['AllProp']+=1
|
||||
if item.asker_id==uid or item.provider_id==uid:
|
||||
if item.asker_id==uid and item.exch_state=='Ask':
|
||||
DicResult[item.exch_type]['Counters']['AllAgree'] += 1
|
||||
if item.exch_state == 'Ask':
|
||||
DicResult[item.exch_type]['Counters']['AllAsk'] += 1
|
||||
if item.exch_state == 'Proposal':
|
||||
DicResult[item.exch_type]['Counters']['AllProp'] += 1
|
||||
if item.asker_id == uid or item.provider_id == uid:
|
||||
if item.asker_id == uid and item.exch_state == 'Ask':
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
if item.exch_done:
|
||||
DicResult[item.exch_type]['Agree'].append(item)
|
||||
@@ -564,28 +588,29 @@ class Exchange(Base):
|
||||
|
||||
@classmethod
|
||||
def get_pub_list(cls, exch_type):
|
||||
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_done==False)\
|
||||
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_done == False) \
|
||||
.all()
|
||||
|
||||
@classmethod
|
||||
def get_my_list(cls, uid, exch_type):
|
||||
DicResult = {}
|
||||
DicResult['Ask']=DBSession.query(cls)\
|
||||
.filter(cls.for_year==CurrentYear)\
|
||||
.filter( or_(cls.asker_id==uid, cls.provider_id==uid) )\
|
||||
.filter(cls.exch_type=='%s' % exch_type)\
|
||||
.filter(cls.exch_state=='Ask')\
|
||||
DicResult['Ask'] = DBSession.query(cls) \
|
||||
.filter(cls.for_year == CurrentYear) \
|
||||
.filter(or_(cls.asker_id == uid, cls.provider_id == uid)) \
|
||||
.filter(cls.exch_type == '%s' % exch_type) \
|
||||
.filter(cls.exch_state == 'Ask') \
|
||||
.order_by(cls.start_time).all()
|
||||
DicResult['Proposal']=DBSession.query(cls)\
|
||||
.filter(cls.for_year==CurrentYear)\
|
||||
.filter( or_(cls.asker_id==uid, cls.provider_id==uid) )\
|
||||
.filter(cls.exch_type=='%s' % exch_type)\
|
||||
.filter(cls.exch_state=='Proposal')\
|
||||
DicResult['Proposal'] = DBSession.query(cls) \
|
||||
.filter(cls.for_year == CurrentYear) \
|
||||
.filter(or_(cls.asker_id == uid, cls.provider_id == uid)) \
|
||||
.filter(cls.exch_type == '%s' % exch_type) \
|
||||
.filter(cls.exch_state == 'Proposal') \
|
||||
.order_by(cls.start_time).all()
|
||||
return DicResult
|
||||
|
||||
|
||||
class Sejour(Base):
|
||||
__tablename__ = 'sejour'
|
||||
sej_id = Column(Integer, primary_key=True)
|
||||
@@ -609,11 +634,12 @@ class Sejour(Base):
|
||||
|
||||
@classmethod
|
||||
def by_user(cls, uid, year):
|
||||
return DBSession.query(cls)\
|
||||
.filter(cls.user_id == uid)\
|
||||
.filter(cls.for_year == year)\
|
||||
return DBSession.query(cls) \
|
||||
.filter(cls.user_id == uid) \
|
||||
.filter(cls.for_year == year) \
|
||||
.first()
|
||||
|
||||
|
||||
class Event(Base):
|
||||
__tablename__ = 'events'
|
||||
uid = Column(Integer, primary_key=True)
|
||||
@@ -637,26 +663,25 @@ class Event(Base):
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, uid):
|
||||
return DBSession.query(cls)\
|
||||
return DBSession.query(cls) \
|
||||
.filter(cls.uid == uid).first()
|
||||
|
||||
|
||||
@classmethod
|
||||
def by_slug(cls, slug, year=None):
|
||||
if not year is None:
|
||||
return DBSession.query(cls)\
|
||||
.filter(cls.for_year==year)\
|
||||
return DBSession.query(cls) \
|
||||
.filter(cls.for_year == year) \
|
||||
.filter(cls.slug == slug).first()
|
||||
else:
|
||||
return DBSession.query(cls)\
|
||||
return DBSession.query(cls) \
|
||||
.filter(cls.slug == slug).first()
|
||||
|
||||
def get_linked_tiers(self):
|
||||
ListLink = DBSession.query(Role_Tiers.tiers_uid) \
|
||||
.filter(Role_Tiers.year_uid==self.for_year) \
|
||||
.filter(Role_Tiers.tiers_role=="Exposant") \
|
||||
.filter(Role_Tiers.event_uid==self.uid)
|
||||
return DBSession.query(Tiers).filter( Tiers.uid.in_( ListLink ) )
|
||||
.filter(Role_Tiers.year_uid == self.for_year) \
|
||||
.filter(Role_Tiers.tiers_role == "Exposant") \
|
||||
.filter(Role_Tiers.event_uid == self.uid)
|
||||
return DBSession.query(Tiers).filter(Tiers.uid.in_(ListLink))
|
||||
|
||||
@property
|
||||
def video(self):
|
||||
@@ -676,6 +701,7 @@ class Event(Base):
|
||||
def created_in_words(self):
|
||||
return time_ago_in_words(self.created)
|
||||
|
||||
|
||||
class Entry(Base):
|
||||
__tablename__ = 'entries'
|
||||
id = Column(Integer, primary_key=True)
|
||||
@@ -706,7 +732,8 @@ class Entry(Base):
|
||||
page_url = PageURL_WebOb(request)
|
||||
return Page(Entry.all(), page, url=page_url, items_per_page=5)
|
||||
|
||||
#class Seances(Base):
|
||||
|
||||
# class Seances(Base):
|
||||
# __tablename__ = 'seances'
|
||||
def get_user(request):
|
||||
# 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:
|
||||
# this should return None if the user doesn't exist
|
||||
# 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):
|
||||
if Year:
|
||||
return DBSession.query(Tiers)\
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\
|
||||
.filter( Role_Tiers.tiers_role == 'Sponsor')\
|
||||
.filter( Role_Tiers.year_uid == Year)
|
||||
return DBSession.query(Tiers) \
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
|
||||
.filter(Role_Tiers.tiers_role == 'Sponsor') \
|
||||
.filter(Role_Tiers.year_uid == Year)
|
||||
else:
|
||||
return DBSession.query(Tiers)\
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\
|
||||
.filter( Role_Tiers.tiers_role == 'Sponsor')
|
||||
return DBSession.query(Tiers) \
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
|
||||
.filter(Role_Tiers.tiers_role == 'Sponsor')
|
||||
|
||||
|
||||
def get_exposants(request, Year):
|
||||
if Year:
|
||||
return DBSession.query(Tiers)\
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\
|
||||
.filter( Role_Tiers.tiers_role == 'Exposant')\
|
||||
.filter( Role_Tiers.year_uid == Year)
|
||||
return DBSession.query(Tiers) \
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
|
||||
.filter(Role_Tiers.tiers_role == 'Exposant') \
|
||||
.filter(Role_Tiers.year_uid == Year)
|
||||
else:
|
||||
return DBSession.query(Tiers)\
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid )\
|
||||
.filter( Role_Tiers.tiers_role == 'Exposant')
|
||||
|
||||
return DBSession.query(Tiers) \
|
||||
.join(Role_Tiers, Role_Tiers.tiers_uid == Tiers.uid) \
|
||||
.filter(Role_Tiers.tiers_role == 'Exposant')
|
||||
|
||||
@@ -48,14 +48,14 @@ def pull_data(from_db, to_db, tables):
|
||||
destination, dengine = make_session(to_db)
|
||||
|
||||
for table_name in tables:
|
||||
print 'Processing', table_name
|
||||
print 'Pulling schema from source server'
|
||||
print('Processing', table_name)
|
||||
print('Pulling schema from source server')
|
||||
table = Table(table_name, smeta, autoload=True)
|
||||
print 'Creating table on destination server'
|
||||
print('Creating table on destination server')
|
||||
table.metadata.create_all(dengine)
|
||||
NewRecord = quick_mapper(table)
|
||||
columns = table.columns.keys()
|
||||
print 'Transferring records'
|
||||
print('Transferring records')
|
||||
for record in source.query(table).all():
|
||||
data = dict(
|
||||
[(str(column), getattr(record, column)) for column in columns]
|
||||
@@ -69,20 +69,20 @@ def pull_data(from_db, to_db, tables):
|
||||
try:
|
||||
destination.merge(NewRecord(**data))
|
||||
except:
|
||||
print data
|
||||
print(data)
|
||||
pass
|
||||
print 'Committing changes'
|
||||
print('Committing changes')
|
||||
destination.commit()
|
||||
|
||||
|
||||
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)
|
||||
DBSession.configure(bind=engine)
|
||||
Users = DBSession.query(User)
|
||||
ListUser = filter(lambda x: x.is_Intervenant, Users)
|
||||
for i in ListUser:
|
||||
print i.mail
|
||||
print(i.mail)
|
||||
|
||||
def main4(argv=sys.argv):
|
||||
import csv
|
||||
@@ -116,7 +116,7 @@ def main4(argv=sys.argv):
|
||||
u.wifi_user = w_user
|
||||
u.wifi_pass = w_pass
|
||||
DBSession.merge(u)
|
||||
print row, u
|
||||
print(row, u)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
@@ -130,7 +130,7 @@ def main_3(argv=sys.argv):
|
||||
connection_string = "sqlite:////home/tr4ck3ur/Dev/jm2l/JM2L.sqlite"
|
||||
engine = create_engine(connection_string, echo=True, convert_unicode=True)
|
||||
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
|
||||
|
||||
## permtation
|
||||
@@ -141,7 +141,7 @@ def main_3(argv=sys.argv):
|
||||
.filter(p0.last_logged<p1.last_logged)\
|
||||
.with_entities(p0.slug,p0.uid,p1.uid).all()
|
||||
for slug, idsrc, iddst in Datas:
|
||||
print slug
|
||||
print(slug)
|
||||
# Events
|
||||
Events = DBSession.query(User_Event)\
|
||||
.filter(User_Event.user_uid==idsrc)
|
||||
@@ -238,5 +238,4 @@ def Initialize():
|
||||
u.password = password
|
||||
u.Staff = 0
|
||||
DBSession.merge(u)
|
||||
print u.nom, u.prenom, u.Staff
|
||||
|
||||
print(u.nom, u.prenom, u.Staff)
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
% if reason:
|
||||
<p>${reason}</p>
|
||||
% else:
|
||||
<p>Vous n'êtes pas authentifié, ou n'avez pas les authorisations nécessaires.</p>
|
||||
<p>Vous n'êtes pas authentifié, ou n'avez pas les authorisations nécessaires.</p>
|
||||
% endif
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<img src="/img/error404.png" width="200px" />
|
||||
<h1>Page non trouvée</h1>
|
||||
<h1>Page non trouvée</h1>
|
||||
% if reason:
|
||||
<p>${reason}</p>
|
||||
% else:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Conférences</td> <td style="text-align:center">
|
||||
<td>Conférences</td> <td style="text-align:center">
|
||||
% if len( request.user.year_events('Conference') ):
|
||||
% for evt in request.user.year_events('Conference'):
|
||||
% endfor
|
||||
@@ -106,11 +106,11 @@ elif Type=='T':
|
||||
%>
|
||||
% if Type!='O':
|
||||
<fieldset>
|
||||
<legend class="lowshadow">Vos ${CurTitles} programmés pour ${CurrentYear}</legend>
|
||||
<legend class="lowshadow">Vos ${CurTitles} programmés pour ${CurrentYear}</legend>
|
||||
<%
|
||||
Selection = filter(lambda x:(x.event_type==CurEventType and x.for_year==CurrentYear), uprofil.events)
|
||||
Selection = list(filter(lambda x:(x.event_type==CurEventType and x.for_year==CurrentYear), uprofil.events))
|
||||
HeadHistTitle = u"L'historique de vos %s ( %d ) " % ( CurTitles, len(Selection) )
|
||||
NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent
|
||||
NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent
|
||||
%>
|
||||
${helpers.show_Interventions(Selection, "Sujet", NothingTitle )}
|
||||
</fieldset>
|
||||
@@ -118,21 +118,21 @@ NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent
|
||||
|
||||
% if Type=='C':
|
||||
<p>
|
||||
<strong>Proposer une conférence / un lighting talk</strong><br/>
|
||||
<strong>Proposer une conférence / un lighting talk</strong><br/>
|
||||
<ul>
|
||||
<li>Si vous avez une expérience particulière avec les logiciels libres
|
||||
<li>Si vous avez une expérience particulière avec les logiciels libres
|
||||
que vous souhaitez partager.</li>
|
||||
<li>Si vous êtes acteur d’un des sujets actuels qui menacent ou qui
|
||||
promeuvent le logiciel libre.</li>
|
||||
<li>Si vous voulez présenter un logiciel libre dont vous êtes l’auteur.</li>
|
||||
<li>Si vous voulez présenter un logiciel libre dont vous êtes l’auteur.</li>
|
||||
</ul>
|
||||
Nous serons heureux de vous écouter.
|
||||
Nous serons heureux de vous écouter.
|
||||
<br>
|
||||
Nous souhaitons proposer des conférences pour un public débutant
|
||||
Nous souhaitons proposer des conférences pour un public débutant
|
||||
autant que pour des visiteurs avertis. Les sujets ne doivent pas
|
||||
forcément être techniques, mais aussi d’ordre général avec la seule
|
||||
forcément être techniques, mais aussi d’ordre général avec la seule
|
||||
contrainte de traiter de près ou de loin des logiciels libres, de la
|
||||
communauté ou de vos propres expériences d’utilisateur quotidien. <br>
|
||||
communauté ou de vos propres expériences d’utilisateur quotidien. <br>
|
||||
Le but de ces conférences est double :
|
||||
<ul>
|
||||
<li>donner confiance aux futurs utilisateurs de logiciels libres</li>
|
||||
@@ -205,7 +205,7 @@ NothingTitle = u"Vous n'avez pas sollicité d'intervention %s." % CurEvent
|
||||
<fieldset>
|
||||
<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) )
|
||||
NothingTitle = u"Désolé, Il n'y a rien dans l'historique vous concernant."
|
||||
%>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<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>
|
||||
</div>
|
||||
Temps de voyage estimé à <span id="summary"></span>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<dd>Un hébergement</dd>
|
||||
% endif
|
||||
<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:
|
||||
<dt>Détails </dt>
|
||||
<dd>${Exch.description}</dd>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<dt>Catégorie</dt>
|
||||
<dd>${Exch.Category.exch_subtype}</dd>
|
||||
<dt>Quand </dt>
|
||||
<dd>de ${Exch.start_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${Exch.start_time.strftime('%Hh%M')}
|
||||
à ${Exch.end_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${Exch.end_time.strftime('%Hh%M')}
|
||||
<dd>de ${Exch.start_time.strftime('%A %d %b %Y')} vers ${Exch.start_time.strftime('%Hh%M')}
|
||||
à ${Exch.end_time.strftime('%A %d %b %Y')} vers ${Exch.end_time.strftime('%Hh%M')}
|
||||
</dd>
|
||||
<dt>Détails </dt>
|
||||
<dd>${Exch.description}</dd>
|
||||
|
||||
@@ -8,11 +8,11 @@ DicExch = Exchanges.get_overview( request.user.uid )
|
||||
<div class="tabbable tabs-left" id="Intendance_tab">
|
||||
|
||||
<ul class="nav nav-tabs navbar" style="margin-bottom:0;background-color: #f7f7f7;">
|
||||
<li class="active"> <a href="#ResumeInt" data-toggle="tab">Resumé</a> </li>
|
||||
<li class="active"> <a href="#ResumeInt" data-toggle="tab">Resumé</a> </li>
|
||||
<li> <a href="#Miam" data-toggle="tab"><span style="font-size:1.8em;">🍽</span> Miam</a> </li>
|
||||
<li> <a href="#Covoiturage" data-toggle="tab"><span style="font-size:1.8em;">🚘</span> Covoiturage</a> </li>
|
||||
<li> <a href="#Hebergement" data-toggle="tab"><span style="font-size:1.8em;">🏚</span> Hébergement</a> </li>
|
||||
<li> <a href="#Materiel" data-toggle="tab"><span style="font-size:1.8em;">🛒</span> Matériel</a> </li>
|
||||
<li> <a href="#Hebergement" data-toggle="tab"><span style="font-size:1.8em;">🏚</span> Hébergement</a> </li>
|
||||
<li> <a href="#Materiel" data-toggle="tab"><span style="font-size:1.8em;">🛒</span> Matériel</a> </li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
@@ -30,7 +30,7 @@ DicExch = Exchanges.get_overview( request.user.uid )
|
||||
${tables.DoTable(Type, 'Ask', DicExch)}
|
||||
${tables.DoTable(Type, 'Proposal', DicExch)}
|
||||
<fieldset>
|
||||
<legend>Tous les échanges</legend>
|
||||
<legend>Tous les échanges</legend>
|
||||
${Missing(Type, DicExch['Missing'])}
|
||||
</fieldset>
|
||||
</%def>
|
||||
@@ -59,23 +59,23 @@ DicForm = {
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Complétez dès à présent votre partie repas afin que l'on puisse faire les réservations nécessaires !
|
||||
Complétez dès à présent votre partie repas afin que l'on puisse faire les réservations nécessaires !
|
||||
</p>
|
||||
|
||||
<u>Vendredi soir :</u>
|
||||
<p>
|
||||
Certains conférenciers viennent de très loin et seront présent dés le vendredi.<br />
|
||||
Nous vous proposons de nous retrouver à proximité, à la CASA.<br />
|
||||
Certains conférenciers viennent de très loin et seront présent dés le vendredi.<br />
|
||||
Nous vous proposons de nous retrouver à proximité, à la CASA.<br />
|
||||
<a href="http://groupelacasa.com/la-carte-et-les-menus-1-2-75"> La carte CASA </a>
|
||||
le vendredi soir autour d'un verre et d'un bon repas !
|
||||
</p>
|
||||
<u>Samedi Midi :</u>
|
||||
<p>
|
||||
À la pause du midi, nous vous proposons un repas avec le food-truck 'les frères toqués' qui sera présent sur le parking de PolyTech<br />
|
||||
À la pause du midi, nous vous proposons un repas avec le food-truck 'les frères toqués' qui sera présent sur le parking de PolyTech<br />
|
||||
</p>
|
||||
<u>Samedi Soir :</u>
|
||||
<p>
|
||||
Pour conclure la journée nous avons l'habitude de nous retrouver au repas de cloture.<br />
|
||||
Pour conclure la journée nous avons l'habitude de nous retrouver au repas de cloture.<br />
|
||||
Nous vous proposons de nous retrouver à Antibes au restaurant Les Tonnelles<br />
|
||||
<a href="https://fr-fr.facebook.com/lestonnellesantibes/?_fb_noscript=1"> Les Tonnelles </a>
|
||||
</p>
|
||||
@@ -100,7 +100,7 @@ elif Type=='M':
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="5">
|
||||
Les échanges ${CurTitle}
|
||||
Les échanges ${CurTitle}
|
||||
% if 0:
|
||||
<span style="float:right;">
|
||||
<a data-original-title="Afficher les demandes" data-toggle="tooltip" id="${Type}_Demande">
|
||||
@@ -124,7 +124,7 @@ elif Type=='M':
|
||||
|
||||
<tr>
|
||||
<th style="width:1em;"></th>
|
||||
<th>Détails</th>
|
||||
<th>Détails</th>
|
||||
<th style="width:1em;"></th>
|
||||
<tr>
|
||||
</thead>
|
||||
@@ -132,7 +132,7 @@ elif Type=='M':
|
||||
% if len(Selection)==0:
|
||||
<tr>
|
||||
<td colspan="5" style="text-align:center;">
|
||||
<i>Il n'y a aucun échange ${CurTitle} proposé actuellement...</i>
|
||||
<i>Il n'y a aucun échange ${CurTitle} proposé actuellement...</i>
|
||||
</td>
|
||||
</tr>
|
||||
% else:
|
||||
@@ -155,7 +155,7 @@ elif Type=='M':
|
||||
<a href="/user/${item.provider.slug}"> ${item.provider.prenom} ${item.provider.nom} </a> offre
|
||||
% endif
|
||||
% 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>
|
||||
à <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.arrival.place_id}')">${item.Itin.arrival.display_name}</a>
|
||||
% elif item.exch_type=="M":
|
||||
@@ -165,8 +165,8 @@ elif Type=='M':
|
||||
% if item.description:
|
||||
${item.description[:30]}
|
||||
% endif
|
||||
de ${item.start_time.strftime('%a %d %b %Hh%M').decode('utf-8')}
|
||||
à ${item.end_time.strftime('%a %d %b %Hh%M').decode('utf-8')}
|
||||
de ${item.start_time.strftime('%a %d %b %Hh%M')}
|
||||
à ${item.end_time.strftime('%a %d %b %Hh%M')}
|
||||
% else:
|
||||
% if item.Category:
|
||||
<i>${item.Category.exch_subtype}</i>
|
||||
@@ -174,7 +174,7 @@ elif Type=='M':
|
||||
% if item.description:
|
||||
${item.description[:30]}
|
||||
% endif
|
||||
${item.start_time.strftime('%a %d %b').decode('utf-8')} soir
|
||||
${item.start_time.strftime('%a %d %b')} soir
|
||||
% endif
|
||||
</p>
|
||||
</td>
|
||||
@@ -284,7 +284,7 @@ ListWrap = ["Co-voiturage",u"Hébergement","Matos"]
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" data-toggle="collapse" data-parent="#AccordionCounter" href="#collapseAll">Les compteurs de l´événement</a>
|
||||
<a class="accordion-toggle" data-toggle="collapse" data-parent="#AccordionCounter" href="#collapseAll">Les compteurs de l´événement</a>
|
||||
</div>
|
||||
<div id="collapseAll" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
|
||||
@@ -97,17 +97,17 @@ elif Type=='M':
|
||||
</td>
|
||||
<td>
|
||||
%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>
|
||||
à <a href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/${item.Itin.arrival.place_id}')">${item.Itin.arrival.display_name}</a>
|
||||
%elif Type=='H':
|
||||
% if item.Category:
|
||||
<i>${item.Category.exch_subtype}</i>,
|
||||
% 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':
|
||||
de ${item.start_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${item.start_time.strftime('%Hh%M')}
|
||||
à ${item.end_time.strftime('%A %d %b %Y').decode('utf-8')} vers ${item.end_time.strftime('%Hh%M')}<br>
|
||||
de ${item.start_time.strftime('%A %d %b %Y')} vers ${item.start_time.strftime('%Hh%M')}
|
||||
à ${item.end_time.strftime('%A %d %b %Y')} vers ${item.end_time.strftime('%Hh%M')}<br>
|
||||
${item.Category.exch_subtype}
|
||||
%endif
|
||||
%if item.description:
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
<%
|
||||
DicFormA = {
|
||||
'nom': {'PlaceHolder':u"Mon Nom", 'ContainerClass':"span6", 'next':False},
|
||||
'prenom': {'PlaceHolder':u"Mon Prénom", 'ContainerClass':"span6", 'next':True},
|
||||
'prenom': {'PlaceHolder':u"Mon Prénom", 'ContainerClass':"span6", 'next':True},
|
||||
'pseudo': {'PlaceHolder':u"Mon Pseudo", 'ContainerClass':"span6", 'next':False},
|
||||
'mail': {'PlaceHolder':u"mon.mail@fqdn.tld", 'ContainerClass':"span6", 'next':True},
|
||||
'phone': {'PlaceHolder':u"0612345678", 'ContainerClass':"span6", 'next':False},
|
||||
'website': {'PlaceHolder':u"http://ma-page-web.moi",'ContainerClass':"span6", 'next':True},
|
||||
'gpg_key': {'PlaceHolder':u"Ma clé gpg", 'ContainerClass':"span6", 'next':False},
|
||||
'gpg_key': {'PlaceHolder':u"Ma clé gpg", 'ContainerClass':"span6", 'next':False},
|
||||
'soc_link':{'PlaceHolder':u"#jm2l sur irc.freenode.org",'ContainerClass':"span6", 'next':True},
|
||||
'bio': {'Ignore':True},
|
||||
'tiersship': {'Ignore':True},
|
||||
@@ -52,12 +52,12 @@ DicFormB = {
|
||||
|
||||
DicForm2 = {
|
||||
'nom': {'PlaceHolder':u"Mon Nom", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"},
|
||||
'prenom': {'PlaceHolder':u"Mon Prénom", "FieldStyle":"width:16em;"},
|
||||
'prenom': {'PlaceHolder':u"Mon Prénom", "FieldStyle":"width:16em;"},
|
||||
'pseudo': {'PlaceHolder':u"Mon Pseudo", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"},
|
||||
'mail': {'PlaceHolder':u"mon.mail@fqdn.tld", "FieldStyle":"width:16em;"},
|
||||
'phone': {'PlaceHolder':u"0612345678", "FieldStyle":"width:16em;", 'ContainerStyle':"float:left;"},
|
||||
'website': {'PlaceHolder':u"http://ma-page-web.moi","FieldStyle":"width:16em;"},
|
||||
'gpg_key': {'PlaceHolder':u"Ma clé gpg", "FieldStyle":"width:90%;"},
|
||||
'gpg_key': {'PlaceHolder':u"Ma clé gpg", "FieldStyle":"width:90%;"},
|
||||
'soc_link':{'PlaceHolder':u"#jm2l sur irc.freenode.org","FieldStyle":"width:90%;"},
|
||||
'bio': {'PlaceHolder':u"Ma Bilibiographie", "FieldStyle":"width:95%;min-height:150px;", "fieldset":True, "ckeditor":1 },
|
||||
'tiersship': {'Ignore':True}
|
||||
|
||||
@@ -14,14 +14,14 @@ fieldset:disabled {
|
||||
% else:
|
||||
<legend class="lowshadow">
|
||||
<img style="max-height:50px;" src="/img/warn.png" alt="Attention !">
|
||||
Vous n'avez pas confirmé votre venue aux JM2L ${CurrentYear}
|
||||
Vous n'avez pas confirmé votre venue aux JM2L ${CurrentYear}
|
||||
</legend>
|
||||
<h4 class="lowshadow">Complétez et validez vite ce formulaire !</h4>
|
||||
<h4 class="lowshadow">Complétez et validez vite ce formulaire !</h4>
|
||||
% endif
|
||||
|
||||
<form id="ProfilForm" action="/MonSejour" method="POST">
|
||||
<fieldset class="ComeToJM2L">
|
||||
<legend>Arrivée</legend>
|
||||
<legend>Arrivée</legend>
|
||||
<div class="form-inline">
|
||||
J'arrive
|
||||
<select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu">
|
||||
@@ -63,16 +63,16 @@ fieldset:disabled {
|
||||
|
||||
<ul style="list-style-type: none;">
|
||||
<li><label class="checkbox">
|
||||
<input id="PMR" ${mytrip.IsCheck("Arrival:PMR")|n} name="Arrival:PMR" title="Assistance Personne à mobilité réduite (PMR)" type="checkbox">
|
||||
d'assistance : Personne à mobilité réduite (PMR)</input></label>
|
||||
<input id="PMR" ${mytrip.IsCheck("Arrival:PMR")|n} name="Arrival:PMR" title="Assistance Personne à mobilité réduite (PMR)" type="checkbox">
|
||||
d'assistance : Personne à mobilité réduite (PMR)</input></label>
|
||||
</li>
|
||||
<li><label class="checkbox">
|
||||
<input id="Cov" ${mytrip.IsCheck("Arrival:Cov")|n} name="Arrival:Cov" title="Covoiturage" type="checkbox">
|
||||
d'un covoiturage, d'un hébergement...<br>(j'ai rempli/je vais remplir la section Logistique).</input></label>
|
||||
d'un covoiturage, d'un hébergement...<br>(j'ai rempli/je vais remplir la section Logistique).</input></label>
|
||||
</li>
|
||||
<li><label class="checkbox">
|
||||
<input id="Bras" ${mytrip.IsCheck("Arrival:Bras")|n} name="Arrival:Bras" title="Bras" type="checkbox">
|
||||
de bras, car je rapporte plein de matériel. <br>(Je transporte ma maison, mon garage ...)</input></label>
|
||||
de bras, car je rapporte plein de matériel. <br>(Je transporte ma maison, mon garage ...)</input></label>
|
||||
</li>
|
||||
<li>
|
||||
<div class="form-inline">
|
||||
@@ -81,7 +81,7 @@ fieldset:disabled {
|
||||
Autres
|
||||
</input></label>
|
||||
<input type="text" style="width:20em;" name="Arrival:Comment"
|
||||
placeholder="Précisions à propos de mon arrivée…" />
|
||||
placeholder="Précisions à propos de mon arrivée…" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -90,7 +90,7 @@ fieldset:disabled {
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="ComeToJM2L">
|
||||
<legend>Départ</legend>
|
||||
<legend>Départ</legend>
|
||||
<div class="form-inline">
|
||||
Je repars
|
||||
<select style="width:12em;" id="Departure:Place" class="formforform-field" name="Departure:Place" title="Alors, j'arrive">
|
||||
@@ -130,8 +130,8 @@ fieldset:disabled {
|
||||
Je vais avoir besoin: <small style="color: #aaa;">(Cochez les cases correspondantes)</small>
|
||||
<ul style="list-style-type: none;">
|
||||
<li><label class="checkbox">
|
||||
<input id="PMR" ${mytrip.IsCheck("Departure:PMR")|n} name="Departure:PMR" title="d'Assistance : Personne à mobilité réduite (PMR)" type="checkbox">
|
||||
d'assistance : Personne à mobilité réduite (PMR)</input>
|
||||
<input id="PMR" ${mytrip.IsCheck("Departure:PMR")|n} name="Departure:PMR" title="d'Assistance : Personne à mobilité réduite (PMR)" type="checkbox">
|
||||
d'assistance : Personne à mobilité réduite (PMR)</input>
|
||||
</label>
|
||||
</li>
|
||||
<li><label class="checkbox">
|
||||
@@ -141,7 +141,7 @@ fieldset:disabled {
|
||||
</li>
|
||||
<li><label class="checkbox">
|
||||
<input id="Bras" ${mytrip.IsCheck("Departure:Bras")|n} name="Departure:Bras" title="de bras" type="checkbox">
|
||||
de bras, car j'ai en stock plein de matériel (Ma maison).</input>
|
||||
de bras, car j'ai en stock plein de matériel (Ma maison).</input>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
@@ -151,7 +151,7 @@ fieldset:disabled {
|
||||
Autres
|
||||
</input></label>
|
||||
<input type="text" style="width:20em;" name="Departure:Comment"
|
||||
placeholder="Précisions à propos de mon départ…" />
|
||||
placeholder="Précisions à propos de mon départ…" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -111,7 +111,7 @@ if Counter==0:
|
||||
vid = event.video.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")}
|
||||
</td>
|
||||
<td style="position: relative;">
|
||||
|
||||
@@ -24,7 +24,7 @@ from slugify import slugify
|
||||
% if len(DicSallePhy)==0:
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<i>Il n'y a pas de salle définie pour le moment.</i>
|
||||
<i>Il n'y a pas de salle définie pour le moment.</i>
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
@@ -43,7 +43,7 @@ from slugify import slugify
|
||||
% if SallePhy.uid:
|
||||
[ ${SallePhy.nb_places} places ]
|
||||
% else:
|
||||
[ <a href="/PhySalles">Créer</a> ]
|
||||
[ <a href="/PhySalles">Créer</a> ]
|
||||
% endif
|
||||
</div>
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
%endif
|
||||
<%
|
||||
DicForm = {
|
||||
'year_uid': {'PlaceHolder':u"Année", "FieldStyle":"width:7em;", "ContainerStyle":"float:left;" },
|
||||
'year_uid': {'PlaceHolder':u"Année", "FieldStyle":"width:7em;", "ContainerStyle":"float:left;" },
|
||||
'phy_salle_id': {'PlaceHolder':u"Salle Physique", "FieldStyle":"width:20em;", "ContainerStyle":"float:left;" },
|
||||
'place_type': {'PlaceHolder':u"Type d'évènement","FieldStyle":"width:15em;" },
|
||||
'place_type': {'PlaceHolder':u"Type d'évènement","FieldStyle":"width:15em;" },
|
||||
'name': {'PlaceHolder':u"Nom de la salle", "FieldStyle":"width:90%;" },
|
||||
'description': {'PlaceHolder':u"Description", "ContainerStyle":"width:95%;min-height:150px;padding-top: 12px;", "ckeditor":"1" },
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% for item, one_dic in found.iteritems():
|
||||
% for item, one_dic in found.items():
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/user/${item}">
|
||||
|
||||
@@ -63,7 +63,7 @@ from slugify import slugify
|
||||
</a>
|
||||
<span style="float:right;">
|
||||
- <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>
|
||||
% endif
|
||||
</td>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
%endif
|
||||
% if 'uid' in form._fields:
|
||||
<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')}
|
||||
%if event.Salle:
|
||||
- <strong>Salle</strong>: ${event.Salle.name}
|
||||
@@ -184,10 +184,10 @@ DicForm = {
|
||||
|
||||
</fieldset>
|
||||
<div class="clearfix"> </div>
|
||||
<p style="float:right;">Créé le ${event.created.strftime('%d %b %Y').decode('utf-8')}</p>
|
||||
<p style="float:right;">Créé le ${event.created.strftime('%d %b %Y')}</p>
|
||||
%else:
|
||||
<p style="float:right;">Créé le
|
||||
${datetime.now().strftime('%d %b %Y').decode('utf-8')}
|
||||
${datetime.now().strftime('%d %b %Y')}
|
||||
</p>
|
||||
% endif
|
||||
<br/>
|
||||
|
||||
+14
-14
@@ -7,7 +7,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
%>
|
||||
<div class="row-fluid">
|
||||
% 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 %>
|
||||
% endif
|
||||
% if Field.type in ['HiddenField', 'CSRFTokenField']:
|
||||
@@ -27,7 +27,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
</a>
|
||||
% endif
|
||||
</label>
|
||||
% if DicFormat.has_key(Field.name):
|
||||
% if Field.name in DicFormat:
|
||||
<%
|
||||
PlaceHolder = DicFormat[Field.name].get("PlaceHolder")
|
||||
Class = [False,"ckeditor"][ "ckeditor" in DicFormat[Field.name] ]
|
||||
@@ -49,7 +49,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
% endfor
|
||||
</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 class="row-fluid">
|
||||
% endif
|
||||
@@ -72,7 +72,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
TabJs = {'select':[], 'desc':[]}
|
||||
%>
|
||||
% 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 %>
|
||||
% endif
|
||||
% if Field.type in ['HiddenField', 'CSRFTokenField']:
|
||||
@@ -81,11 +81,11 @@ TabJs = {'select':[], 'desc':[]}
|
||||
% elif Field.type=="SelectField":
|
||||
<% TabJs['select'].append(Field.label.field_id) %>
|
||||
% 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>
|
||||
<legend>${Field.label.text}</legend>
|
||||
% 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")}">
|
||||
% else:
|
||||
<div style="padding-right:5px;">
|
||||
@@ -101,7 +101,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
% endif
|
||||
</label>
|
||||
% endif
|
||||
% if DicFormat.has_key(Field.name):
|
||||
% if Field.name in DicFormat:
|
||||
<%
|
||||
PlaceHolder = DicFormat[Field.name].get("PlaceHolder")
|
||||
FieldStyle = DicFormat[Field.name].get("FieldStyle")
|
||||
@@ -122,7 +122,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
${ error }
|
||||
</div>
|
||||
% 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>
|
||||
% else:
|
||||
</div>
|
||||
@@ -142,7 +142,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
<%def name="sejour_wrapper(Places)">
|
||||
|
||||
<div class="form-inline">
|
||||
Départ :
|
||||
Départ :
|
||||
<select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu">
|
||||
% for place in Places:
|
||||
<option value="${place.place_id}">${place.display_name}</option>
|
||||
@@ -151,7 +151,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
</div>
|
||||
<br />
|
||||
<div class="form-inline">
|
||||
Arrivée :
|
||||
Arrivée :
|
||||
<select style="width:12em;" id="Arrival:Place" name="Arrival:Place" title="Lieu">
|
||||
% for place in Places:
|
||||
<option value="${place.place_id}">${place.display_name}</option>
|
||||
@@ -184,7 +184,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
${itin_form.arrival_place(style='width:17em;')}
|
||||
</div>
|
||||
<div style="padding:5px;">
|
||||
<small style="color:#999">Si je n´ai pas trouvé le lieu dont j´ai besoin dans ces listes...</small>
|
||||
<small style="color:#999">Si je n´ai pas trouvé le lieu dont j´ai besoin dans ces listes...</small>
|
||||
<br />
|
||||
<small style="color:#999">Je peux </small>
|
||||
<a class="btn btn-mini btn-info" role="button" href="javascript:DoGetLieu('/${CurrentYear}/modal/Place/0');">
|
||||
@@ -350,9 +350,9 @@ TabJs = {'select':[], 'desc':[]}
|
||||
<tr>
|
||||
<td style="text-align:center;" colspan="2">
|
||||
% if NotFoundTitle:
|
||||
<i>${NotFoundTitle}</i>
|
||||
<i>${NotFoundTitle | h}</i>
|
||||
% else:
|
||||
<i>Désolé, Il n'y a rien dans l'historique.</i>
|
||||
<i>Désolé;, Il n'y a rien dans l'historique.</i>
|
||||
% endif
|
||||
</td>
|
||||
</tr>
|
||||
@@ -366,7 +366,7 @@ TabJs = {'select':[], 'desc':[]}
|
||||
vid = event.video.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}
|
||||
</td>
|
||||
<td style="position: relative;">${event.event_type}:
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<div class="tabbable" id="main_tab">
|
||||
<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><a href="#Sejour" id="Map_Sejour" data-toggle="tab">Mon Séjour</a></li>
|
||||
<li><a href="#Sejour" id="Map_Sejour" data-toggle="tab">Mon Séjour</a></li>
|
||||
<li><a href="#Logistique" id="Map_Logistique" data-toggle="tab">Logistique</a></li>
|
||||
<li><a href="#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>
|
||||
@@ -79,8 +79,8 @@
|
||||
<div class="tabbable tabs-left" id="Interventions_tab">
|
||||
|
||||
<ul class="nav nav-tabs navbar" style="margin-bottom:0;">
|
||||
<li class="active"> <a href="#ResumePart" data-toggle="tab">Resumé</a> </li>
|
||||
<li> <a href="#Conference" data-toggle="tab">Conférence</a> </li>
|
||||
<li class="active"> <a href="#ResumePart" data-toggle="tab">Resumé</a> </li>
|
||||
<li> <a href="#Conference" data-toggle="tab">Conférence</a> </li>
|
||||
<li> <a href="#Stand" data-toggle="tab">Stand</a> </li>
|
||||
<li> <a href="#Atelier" data-toggle="tab">Atelier</a> </li>
|
||||
<li> <a href="#TableRonde" data-toggle="tab">Table Ronde</a> </li>
|
||||
@@ -118,12 +118,12 @@
|
||||
<div class="tab-pane fade" id="Frais">
|
||||
<fieldset>
|
||||
<legend class="lowshadow">Une participation à mes frais ?</legend>
|
||||
L'équipe des JM2L participe aux <u>frais de transport</u> des intervenants !<br /><br />
|
||||
L'équipe des JM2L participe aux <u>frais de transport</u> des intervenants !<br /><br />
|
||||
Et bien oui, mais cette participation ne sera effective que si vous remplissez <u>toutes les conditions</u> suivantes:
|
||||
<ul style="list-style:circle;">
|
||||
<li>Vous animez <strong>un atelier, une conférence ou une table ronde</strong> aux JM2L ${CurrentYear}.</li>
|
||||
<li>Votre fiche est renseignée avec <strong>votre RIB</strong>.</li>
|
||||
<li>Votre fiche est renseignée avec <strong>les preuves</strong> de vos achats.</li>
|
||||
<li>Vous animez <strong>un atelier, une conférence ou une table ronde</strong> aux JM2L ${CurrentYear}.</li>
|
||||
<li>Votre fiche est renseignée avec <strong>votre RIB</strong>.</li>
|
||||
<li>Votre fiche est renseignée avec <strong>les preuves</strong> de vos achats.</li>
|
||||
<li>Vous <strong>présentez l'original de vos tickets</strong> à l'accueil pendant l'évènement.</li>
|
||||
<li>Tous vos documents sont conformes.</li>
|
||||
</ul>
|
||||
|
||||
+16
-16
@@ -3,7 +3,7 @@
|
||||
<%namespace name="helpers" file="jm2l:templates/helpers.mako"/>
|
||||
<%
|
||||
context._kwargs['postpone_js']=[]
|
||||
DisplayYear = request.session.get('year', 2018)
|
||||
DisplayYear = request.session.get('year', 2020)
|
||||
%>
|
||||
<head>
|
||||
<title>JM2L ${DisplayYear}</title>
|
||||
@@ -68,12 +68,12 @@ ${helpers.uploader_js()}
|
||||
% if request.user and request.user.vote_logo not in [1,2,3]:
|
||||
<div class="item active">
|
||||
<div class="align-center">
|
||||
<H1>JM2L 2017</H1>
|
||||
<h3>Choisissez ici votre logo préféré !</h3>
|
||||
<H1>JM2L 2020</H1>
|
||||
<h3>Choisissez ici votre logo préféré !</h3>
|
||||
<p>Utilisez les flèches pour choisir et voter !<br>
|
||||
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>
|
||||
N'hésitez pas à envoyer vos propositions par mail à l'équipe !</p>
|
||||
N'hésitez pas à envoyer vos propositions par mail à l'équipe !</p>
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
||||
@@ -105,10 +105,10 @@ ${helpers.uploader_js()}
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
Édition <span class="caret"></span></a>
|
||||
<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:
|
||||
<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>
|
||||
% endif
|
||||
% endfor
|
||||
@@ -128,17 +128,17 @@ ${helpers.uploader_js()}
|
||||
% if request.user:
|
||||
% if request.user.Staff:
|
||||
<li><a href="/${DisplayYear}/Staff">Partie Staff</a></li>
|
||||
<li><a href="/${DisplayYear}/ListParticipant">Gérer les intervenants</a></li>
|
||||
<li><a href="/ListSalles">Gérer les salles</a></li>
|
||||
<li><a href="/entities">Gérer les entités</a></li>
|
||||
<li><a href="/${DisplayYear}/ListParticipant">Gérer les intervenants</a></li>
|
||||
<li><a href="/ListSalles">Gérer les salles</a></li>
|
||||
<li><a href="/entities">Gérer les entités</a></li>
|
||||
<li><a href="/${DisplayYear}/ListOrga">Participations à l'orga</a></li>
|
||||
<li><a href="/${DisplayYear}/Staff/compta">Comptabilité</a></li>
|
||||
<li><a href="/${DisplayYear}/Staff/compta">Comptabilité</a></li>
|
||||
<li><a href="/ListSallesPhy">Les salles à Poly'tech</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
% endif
|
||||
<li><a href="/MesJM2L">Mon profil</a></li>
|
||||
<li><a href="/user/${request.user.slug}">Mon profil public</a></li>
|
||||
<li><a href="/sign/out">Me déconnecter</a></li>
|
||||
<li><a href="/sign/out">Me déconnecter</a></li>
|
||||
% else:
|
||||
<li><a href="/participer-l-evenement#inscription">Je m'inscris</a></li>
|
||||
<li><a href="/sign/login">Je m'identifie</a></li>
|
||||
@@ -186,9 +186,9 @@ ${helpers.uploader_js()}
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<h4>JM2L 2005-2018</h4>
|
||||
<h4>JM2L 2005-2020</h4>
|
||||
<p>
|
||||
Concocté par <a href="http://www.linux-azur.org/">Linux Azur</a> ~
|
||||
Concocté par <a href="http://www.linux-azur.org/">Linux Azur</a> ~
|
||||
<a href="http://creativecommons.org/licenses/by-sa/4.0/">CopyFriendly</a>
|
||||
</p>
|
||||
<p>
|
||||
@@ -196,10 +196,10 @@ ${helpers.uploader_js()}
|
||||
</p>
|
||||
<p>
|
||||
Conception et construction en <a href="http://git.linux-azur.org/JM2L/jm2l/src/master">DIY</a> ~
|
||||
Hébergé par <a href="http://www.heberg-24.com/"> Heberg24 </a>
|
||||
Hébergé par <a href="http://www.heberg-24.com/"> Heberg24 </a>
|
||||
</p>
|
||||
<p>
|
||||
Vous avez trouvé un bug ? <a href="http://git.linux-azur.org/JM2L/jm2l/issues">Reportez-le ici</a>
|
||||
Vous avez trouvé un bug ? <a href="http://git.linux-azur.org/JM2L/jm2l/issues">Reportez-le ici</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -245,7 +245,7 @@ function handlevote() {
|
||||
$('.carousel-vote a').attr('href', "/vote_logo/" + currentIndex )
|
||||
if (currentIndex==${request.user.vote_logo or 0}) {
|
||||
$('.carousel-vote a').removeClass('btn-primary').addClass('btn-success')
|
||||
$('.carousel-vote a').html("<i class='icon-ok icon-white'></i> Mon préféré ! ");
|
||||
$('.carousel-vote a').html("<i class='icon-ok icon-white'></i> Mon préféré ! ");
|
||||
} else {
|
||||
$('.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 ! ");
|
||||
|
||||
@@ -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):
|
||||
% if not t.closed:
|
||||
<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>
|
||||
% endif
|
||||
% 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):
|
||||
% if not t.closed:
|
||||
<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>
|
||||
% endif
|
||||
% 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>
|
||||
<br/><br/>
|
||||
% 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
|
||||
<p>
|
||||
Bon courage !
|
||||
|
||||
@@ -65,7 +65,7 @@ Voici ce qu'il y'a dans la liste des tâches qui te sont assignées:
|
||||
|
||||
% for t in sorted(User.task_assoc, key=lambda k:k.due_date):
|
||||
% 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}
|
||||
|
||||
% 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):
|
||||
% 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}
|
||||
|
||||
% 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)}.
|
||||
|
||||
% 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
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
<br/>
|
||||
<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>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
<strong>${event.event_type}</strong>:
|
||||
<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')}
|
||||
</div>
|
||||
% if event.for_year==CurrentYear and request.user and (request.user.Staff or request.user in event.intervenants):
|
||||
@@ -116,7 +116,7 @@
|
||||
</p>
|
||||
% endfor
|
||||
<div class="clearfix"> </div>
|
||||
<p style="float:right;">Créé le ${event.created.strftime('%d %b %Y').decode('utf-8')}</p>
|
||||
<p style="float:right;">Créé le ${event.created.strftime('%d %b %Y')}</p>
|
||||
<br/>
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,7 @@ ${The_entity_type.entity_subtype}
|
||||
</p>
|
||||
% endfor
|
||||
<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/>
|
||||
<hr/>
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<h4>Ses interventions :</h4>
|
||||
${helpers.show_Interventions(DispUser.events)}
|
||||
% 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>
|
||||
+74
-74
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf8 -*-
|
||||
import io
|
||||
from pyramid.response import Response
|
||||
import cStringIO as StringIO
|
||||
from pyramid.view import view_config
|
||||
from .models import DBSession, Event, Salles
|
||||
from reportlab.pdfgen import canvas
|
||||
@@ -17,49 +17,50 @@ HEIGHT = 297 * mm
|
||||
ICONSIZE = 10 * mm
|
||||
|
||||
|
||||
def JM2L_large_Logo(canvas, Offset=(0,0)):
|
||||
def JM2L_large_Logo(canvas, Offset=(0, 0)):
|
||||
OffX, OffY = Offset
|
||||
|
||||
canvas.setFont('Logo', 110)
|
||||
canvas.setFillColorRGB(.83,0,.33)
|
||||
canvas.drawCentredString(WIDTH/2-OffY, HEIGHT-100-OffX, "JM2L")
|
||||
canvas.setFillColorRGB(.83, 0, .33)
|
||||
canvas.drawCentredString(WIDTH / 2 - OffY, HEIGHT - 100 - OffX, "JM2L")
|
||||
|
||||
canvas.setFont("Helvetica-Bold", 30)
|
||||
yearobject = canvas.beginText()
|
||||
yearobject.setFillColorRGB(1,1,1)
|
||||
yearobject.setTextRenderMode(0)
|
||||
yearobject.setTextOrigin(WIDTH/2-OffY-120, HEIGHT-36-OffX)
|
||||
yearobject.setWordSpace(48)
|
||||
yearobject.textLines("2 0 1 5")
|
||||
yearobject.setWordSpace(1)
|
||||
canvas.drawText(yearobject)
|
||||
year_object = canvas.beginText()
|
||||
year_object.setFillColorRGB(1, 1, 1)
|
||||
year_object.setTextRenderMode(0)
|
||||
year_object.setTextOrigin(WIDTH / 2 - OffY - 120, HEIGHT - 36 - OffX)
|
||||
year_object.setWordSpace(48)
|
||||
year_object.textLines("2 0 1 5")
|
||||
year_object.setWordSpace(1)
|
||||
canvas.drawText(year_object)
|
||||
|
||||
|
||||
def one_time_step(canvas, str, hour, max_size, offset):
|
||||
max_x, max_y = max_size
|
||||
off_x, off_y = offset
|
||||
step_y = max_y/9
|
||||
half_step = step_y/2
|
||||
canvas.drawCentredString(off_x-30, max_y-step_y*hour+off_y-3, str)
|
||||
hour_place = step_y*hour+off_y
|
||||
canvas.line(off_x-5, hour_place, off_x, hour_place)
|
||||
if hour<9:
|
||||
canvas.line(off_x-2, hour_place+half_step, off_x, hour_place+half_step)
|
||||
step_y = max_y / 9
|
||||
half_step = step_y / 2
|
||||
canvas.drawCentredString(off_x - 30, max_y - step_y * hour + off_y - 3, str)
|
||||
hour_place = step_y * hour + off_y
|
||||
canvas.line(off_x - 5, hour_place, off_x, hour_place)
|
||||
if hour < 9:
|
||||
canvas.line(off_x - 2, hour_place + half_step, off_x, hour_place + half_step)
|
||||
|
||||
|
||||
@view_config(route_name='stand_print', http_cache = (EXPIRATION_TIME, {'public':True}))
|
||||
@view_config(route_name='stand_print', http_cache=(EXPIRATION_TIME, {'public': True}))
|
||||
def stand_print(request):
|
||||
# Ok let's generate a print for place schedule
|
||||
|
||||
# Register LiberationMono font
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
# Import font
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file))
|
||||
# Import font
|
||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo))
|
||||
|
||||
pdf = StringIO.StringIO()
|
||||
pdf = io.BytesIO()
|
||||
|
||||
c = canvas.Canvas( pdf, pagesize=(HEIGHT, WIDTH) )
|
||||
c = canvas.Canvas(pdf, pagesize=(HEIGHT, WIDTH))
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
@@ -70,43 +71,42 @@ def stand_print(request):
|
||||
|
||||
year = int(request.matchdict.get('year', CurrentYear))
|
||||
|
||||
Events = DBSession.query(Event)\
|
||||
.filter(Event.for_year == year)\
|
||||
Events = DBSession.query(Event) \
|
||||
.filter(Event.for_year == year) \
|
||||
.filter(Event.event_type == "Stand")
|
||||
|
||||
for ev in Events:
|
||||
c.setFont('Logo', 50)
|
||||
c.setFillColorRGB(.5,.5,.5)
|
||||
c.drawString(HEIGHT-150, 30, "JM2L")
|
||||
c.setFillColorRGB(.5, .5, .5)
|
||||
c.drawString(HEIGHT - 150, 30, "JM2L")
|
||||
c.setFont('Logo', 100)
|
||||
c.setFillColorRGB(0.5,0.5,0.5)
|
||||
c.drawCentredString(HEIGHT/2, WIDTH-90, "STAND", 0)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
c.setFillColorRGB(0.5, 0.5, 0.5)
|
||||
c.drawCentredString(HEIGHT / 2, WIDTH - 90, "STAND", 0)
|
||||
c.setFillColorRGB(0, 0, 0)
|
||||
c.setFont('Helvetica', 42)
|
||||
c.drawCentredString(HEIGHT/2, WIDTH/2, ev.name, 0)
|
||||
c.drawCentredString(HEIGHT / 2, WIDTH / 2, ev.name, 0)
|
||||
c.showPage()
|
||||
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
return Response(app_iter=pdf, content_type='application/pdf')
|
||||
|
||||
|
||||
|
||||
@view_config(route_name='place_print', http_cache = (EXPIRATION_TIME, {'public':True}))
|
||||
@view_config(route_name='place_print', http_cache=(EXPIRATION_TIME, {'public': True}))
|
||||
def place_print(request):
|
||||
# Ok let's generate a print for place schedule
|
||||
|
||||
# Register LiberationMono font
|
||||
ttfFile = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttfFile))
|
||||
# Import font
|
||||
ttfFile_Logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttfFile_Logo))
|
||||
ttf_file = "jm2l/static/fonts/LiberationMono-Regular.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Liberation", ttf_file))
|
||||
# Import font
|
||||
ttf_file_logo = "jm2l/static/fonts/PWTinselLetters.ttf"
|
||||
pdfmetrics.registerFont(TTFont("Logo", ttf_file_logo))
|
||||
|
||||
pdf = StringIO.StringIO()
|
||||
pdf = io.BytesIO()
|
||||
|
||||
c = canvas.Canvas( pdf, pagesize=(WIDTH, HEIGHT) )
|
||||
c = canvas.Canvas(pdf, pagesize=(WIDTH, HEIGHT))
|
||||
c.translate(mm, mm)
|
||||
|
||||
# Feed some metadata
|
||||
@@ -118,9 +118,9 @@ def place_print(request):
|
||||
year = int(request.matchdict.get('year', CurrentYear))
|
||||
# Initialization
|
||||
# Compute days used by all events matching the specified input year
|
||||
place_used = DBSession.query(Event.salle_uid)\
|
||||
.filter(Event.for_year == year)\
|
||||
.filter(Event.event_type != 'Stand')\
|
||||
place_used = DBSession.query(Event.salle_uid) \
|
||||
.filter(Event.for_year == year) \
|
||||
.filter(Event.event_type != 'Stand') \
|
||||
.group_by(Event.salle_uid)
|
||||
|
||||
for place in place_used:
|
||||
@@ -128,57 +128,57 @@ def place_print(request):
|
||||
place_obj = Salles.by_id(place_uid)
|
||||
# Logo on Top
|
||||
JM2L_large_Logo(c)
|
||||
max_size = (WIDTH-110, HEIGHT-300)
|
||||
max_size = (WIDTH - 110, HEIGHT - 300)
|
||||
offset = (70, 90)
|
||||
c.setFillColorRGB(.5,.5,.5)
|
||||
c.setFillColorRGB(.5, .5, .5)
|
||||
c.setFont('Liberation', 40)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT-190, place_obj.name, 1)
|
||||
c.drawCentredString(WIDTH / 2, HEIGHT - 190, place_obj.name, 1)
|
||||
c.setFont('Liberation', 35)
|
||||
c.drawCentredString(WIDTH/2, HEIGHT-145, place_obj.place_type, 0 )
|
||||
c.drawCentredString(WIDTH / 2, HEIGHT - 145, place_obj.place_type, 0)
|
||||
c.setFont('Helvetica', 20)
|
||||
c.drawCentredString(WIDTH/2, 55, place_obj.phy.name, 0)
|
||||
c.drawCentredString(WIDTH / 2, 55, place_obj.phy.name, 0)
|
||||
|
||||
# Timetable container
|
||||
c.setLineWidth(.1)
|
||||
c.setLineCap(2)
|
||||
#c.setFillColorRGB(0,0,1)
|
||||
# c.setFillColorRGB(0,0,1)
|
||||
c.rect(offset[0], offset[1], max_size[0], max_size[1], fill=0, stroke=1)
|
||||
c.setLineWidth(.5)
|
||||
# create time mark
|
||||
c.setFillColorRGB(0,0,0)
|
||||
c.setFillColorRGB(0, 0, 0)
|
||||
c.setFont('Helvetica', 10)
|
||||
for i in range(0,10):
|
||||
one_time_step(c, "%.2dh00" % (i+10), i, max_size, offset)
|
||||
for i in range(0, 10):
|
||||
one_time_step(c, "%.2dh00" % (i + 10), i, max_size, offset)
|
||||
|
||||
#c.setFont('Helvetica', 12)
|
||||
Events = DBSession.query(Event)\
|
||||
.filter(Event.for_year == year)\
|
||||
.filter(Event.salle_uid == place_uid)\
|
||||
# c.setFont('Helvetica', 12)
|
||||
Events = DBSession.query(Event) \
|
||||
.filter(Event.for_year == year) \
|
||||
.filter(Event.salle_uid == place_uid) \
|
||||
.order_by(Event.start_time)
|
||||
for ev in Events:
|
||||
place_time(c, ev, max_size, offset)
|
||||
#c.rect(70, 50, WIDTH-100, HEIGHT-250, fill=0, stroke=1)
|
||||
# c.rect(70, 50, WIDTH-100, HEIGHT-250, fill=0, stroke=1)
|
||||
c.showPage()
|
||||
|
||||
c.save()
|
||||
pdf.seek(0)
|
||||
|
||||
return Response(app_iter=pdf, content_type = 'application/pdf' )
|
||||
return Response(app_iter=pdf, content_type='application/pdf')
|
||||
|
||||
|
||||
def place_time(c, ev, max_size, offset):
|
||||
max_x, max_y = max_size
|
||||
off_x, off_y = offset
|
||||
minute = max_y/(9*60)
|
||||
start_pos_y = ((int( ev.start_time.strftime('%H') )-10)*60 + int( ev.start_time.strftime('%M') )) * minute
|
||||
stop_pos_y = ((int( ev.end_time.strftime('%H') )-10)*60 + int( ev.end_time.strftime('%M') )) * minute
|
||||
minute = max_y / (9 * 60)
|
||||
start_pos_y = ((int(ev.start_time.strftime('%H')) - 10) * 60 + int(ev.start_time.strftime('%M'))) * minute
|
||||
stop_pos_y = ((int(ev.end_time.strftime('%H')) - 10) * 60 + int(ev.end_time.strftime('%M'))) * minute
|
||||
|
||||
c.setFillColorRGB(0.98,0.98,0.98)
|
||||
c.rect(offset[0], max_y + off_y - start_pos_y, max_size[0], start_pos_y-stop_pos_y, fill=1, stroke=1)
|
||||
c.setFillColorRGB(0,0,0)
|
||||
#c.drawString(off_x+5, max_y + off_y - 15 - start_pos_y, ev.start_time.strftime('%H:%M'), 0)
|
||||
c.setFillColorRGB(0.98, 0.98, 0.98)
|
||||
c.rect(offset[0], max_y + off_y - start_pos_y, max_size[0], start_pos_y - stop_pos_y, fill=1, stroke=1)
|
||||
c.setFillColorRGB(0, 0, 0)
|
||||
# c.drawString(off_x+5, max_y + off_y - 15 - start_pos_y, ev.start_time.strftime('%H:%M'), 0)
|
||||
c.setFont('Helvetica', 12)
|
||||
c.drawCentredString(WIDTH/2, max_y + off_y - 35 - start_pos_y, ev.name, 0)
|
||||
intervs = ', '.join( [x.slug for x in ev.intervenants] )
|
||||
c.drawCentredString(WIDTH / 2, max_y + off_y - 35 - start_pos_y, ev.name, 0)
|
||||
intervs = ', '.join([x.slug for x in ev.intervenants])
|
||||
c.setFont('Helvetica', 10)
|
||||
c.drawCentredString(WIDTH/2, max_y + off_y - 55 - start_pos_y, intervs, 0)
|
||||
|
||||
c.drawCentredString(WIDTH / 2, max_y + off_y - 55 - start_pos_y, intervs, 0)
|
||||
|
||||
+113
-109
@@ -9,7 +9,10 @@ from os import path
|
||||
import mimetypes
|
||||
import magic
|
||||
import subprocess
|
||||
import cStringIO as StringIO
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
# Database access imports
|
||||
from .models import User, Place, Tiers, Event, SallePhy
|
||||
from .blenderthumbnailer import blend_extract_thumb, write_png
|
||||
@@ -30,90 +33,88 @@ ACCEPTED_MIMES = ['application/pdf',
|
||||
'application/vnd.oasis.opendocument.spreadsheet-template',
|
||||
'image/svg+xml',
|
||||
'application/x-blender'
|
||||
]
|
||||
|
||||
|
||||
]
|
||||
|
||||
ACCEPT_FILE_TYPES = IMAGE_TYPES
|
||||
THUMBNAIL_SIZE = 80
|
||||
EXPIRATION_TIME = 300 # seconds
|
||||
IMAGEPATH = [ 'images' ]
|
||||
DOCPATH = [ 'document' ]
|
||||
THUMBNAILPATH = [ 'images', 'thumbnails' ]
|
||||
IMAGEPATH = ['images']
|
||||
DOCPATH = ['document']
|
||||
THUMBNAILPATH = ['images', 'thumbnails']
|
||||
# change the following to POST if DELETE isn't supported by the webserver
|
||||
DELETEMETHOD="DELETE"
|
||||
DELETEMETHOD = "DELETE"
|
||||
|
||||
mimetypes.init()
|
||||
|
||||
|
||||
class MediaPath():
|
||||
|
||||
def get_all(self, media_table, linked_id, MediaType=None):
|
||||
filelist = list()
|
||||
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):
|
||||
return list()
|
||||
for f in os.listdir(curpath):
|
||||
filename, ext = os.path.splitext( f )
|
||||
if os.path.isdir(os.path.join(curpath,f)):
|
||||
filename, ext = os.path.splitext(f)
|
||||
if os.path.isdir(os.path.join(curpath, f)):
|
||||
continue
|
||||
if f.endswith('.type'):
|
||||
continue
|
||||
if f:
|
||||
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 os.path.exists(os.path.join(thumbpath, f +".jpg")):
|
||||
filelist.append((ress_url, thumb_url +".jpg"))
|
||||
if os.path.exists(os.path.join(thumbpath, f + ".jpg")):
|
||||
filelist.append((ress_url, thumb_url + ".jpg"))
|
||||
else:
|
||||
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))
|
||||
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))
|
||||
return filelist
|
||||
|
||||
|
||||
def get_list(self, media_table, linked_id, MediaType=None):
|
||||
filelist = list()
|
||||
curpath = self.get_mediapath(media_table, linked_id, None)
|
||||
if not os.path.isdir(curpath):
|
||||
return list()
|
||||
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
|
||||
if f.endswith('.type'):
|
||||
continue
|
||||
if f:
|
||||
filename, ext = os.path.splitext( f )
|
||||
tmpurl = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ","%20"))
|
||||
filename, ext = os.path.splitext(f)
|
||||
tmpurl = '/image/%s/%d/%s' % (media_table, linked_id, f.replace(" ", "%20"))
|
||||
if MediaType is None:
|
||||
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)
|
||||
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)
|
||||
return filelist
|
||||
|
||||
def get_thumb(self, media_table, linked_id, MediaType=None):
|
||||
filelist = list()
|
||||
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):
|
||||
return list()
|
||||
for f in os.listdir(curpath):
|
||||
filename, ext = os.path.splitext( f )
|
||||
if os.path.isdir(os.path.join(curpath,f)):
|
||||
filename, ext = os.path.splitext(f)
|
||||
if os.path.isdir(os.path.join(curpath, f)):
|
||||
continue
|
||||
if f.endswith('.type'):
|
||||
continue
|
||||
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:
|
||||
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)
|
||||
elif MediaType=='Other' and len( os.path.splitext(filename)[1] ):
|
||||
elif MediaType == 'Other' and len(os.path.splitext(filename)[1]):
|
||||
filelist.append(tmpurl)
|
||||
return filelist
|
||||
|
||||
@@ -126,8 +127,8 @@ class MediaPath():
|
||||
:return: Error if any
|
||||
"""
|
||||
if media_table in ['tiers', 'place', 'salle', 'users']:
|
||||
src = IMAGEPATH + [ media_table, from_id ]
|
||||
dst = IMAGEPATH + [ media_table, to_id ]
|
||||
src = IMAGEPATH + [media_table, from_id]
|
||||
dst = IMAGEPATH + [media_table, to_id]
|
||||
else:
|
||||
raise RuntimeError("Sorry, Media '%s' not supported yet for move." % media_table)
|
||||
|
||||
@@ -153,51 +154,51 @@ class MediaPath():
|
||||
linked_id = str(linked_id)
|
||||
if media_table in ['tiers', 'place', 'salle']:
|
||||
# Retrieve Slug
|
||||
if media_table=='tiers':
|
||||
if media_table == 'tiers':
|
||||
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)
|
||||
if media_table=='salle':
|
||||
if media_table == 'salle':
|
||||
slug = SallePhy.by_id(linked_id).slug
|
||||
p = IMAGEPATH + [ media_table, slug ]
|
||||
elif media_table=='presse':
|
||||
p = IMAGEPATH + [media_table, slug]
|
||||
elif media_table == 'presse':
|
||||
# Use Year in linked_id
|
||||
p = IMAGEPATH + [ media_table, linked_id ]
|
||||
elif media_table=='tasks':
|
||||
p = IMAGEPATH + [media_table, linked_id]
|
||||
elif media_table == 'tasks':
|
||||
# Use Current Year
|
||||
p = IMAGEPATH + [ str(CurrentYear), media_table, linked_id ]
|
||||
elif media_table=='poles':
|
||||
p = IMAGEPATH + [str(CurrentYear), media_table, linked_id]
|
||||
elif media_table == 'poles':
|
||||
# Use Current Year
|
||||
p = IMAGEPATH + [ str(CurrentYear), media_table, linked_id ]
|
||||
p = IMAGEPATH + [str(CurrentYear), media_table, linked_id]
|
||||
elif media_table in ['RIB', 'Justif']:
|
||||
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']:
|
||||
user = User.by_id(linked_id)
|
||||
if not user:
|
||||
raise HTTPNotFound()
|
||||
else:
|
||||
slug = user.slug
|
||||
p = IMAGEPATH + [media_table, slug ]
|
||||
elif media_table=='event':
|
||||
p = IMAGEPATH + [media_table, slug]
|
||||
elif media_table == 'event':
|
||||
ev = Event.by_id(linked_id)
|
||||
slug = ev.slug
|
||||
year = ev.for_year
|
||||
p = IMAGEPATH + ['event', str(year), slug ]
|
||||
p = IMAGEPATH + ['event', str(year), slug]
|
||||
|
||||
if name:
|
||||
p += [ name ]
|
||||
p += [name]
|
||||
TargetPath = os.path.join('jm2l/upload', *p)
|
||||
if not os.path.isdir(os.path.dirname(TargetPath)):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(TargetPath))
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
if e.errno != 17:
|
||||
raise e
|
||||
return os.path.join('jm2l/upload', *p)
|
||||
|
||||
def ExtMimeIcon(self, mime):
|
||||
if mime=='application/pdf':
|
||||
if mime == 'application/pdf':
|
||||
return "/img/PDF.png"
|
||||
|
||||
def check_blend_file(self, fileobj):
|
||||
@@ -217,12 +218,12 @@ class MediaPath():
|
||||
fileobj.seek(0)
|
||||
|
||||
# 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
|
||||
else:
|
||||
return mimetype, False
|
||||
|
||||
|
||||
def get_mimetype(self, name):
|
||||
""" This function return the mime-type based on .type file """
|
||||
try:
|
||||
@@ -232,6 +233,7 @@ class MediaPath():
|
||||
except IOError:
|
||||
return None
|
||||
|
||||
|
||||
@view_defaults(route_name='media_upload')
|
||||
class MediaUpload(MediaPath):
|
||||
|
||||
@@ -266,7 +268,7 @@ class MediaUpload(MediaPath):
|
||||
result['type'] = found_mime
|
||||
|
||||
# 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'] += "( %s vs %s )" % (found_mime, result['type'])
|
||||
return False
|
||||
@@ -281,7 +283,7 @@ class MediaUpload(MediaPath):
|
||||
result['error'] = 'le fichier est trop petit'
|
||||
elif result['size'] > MAX_FILE_SIZE:
|
||||
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'
|
||||
else:
|
||||
return True
|
||||
@@ -294,36 +296,36 @@ class MediaUpload(MediaPath):
|
||||
fileobj.seek(0) # Reset the file position to the beginning
|
||||
return size
|
||||
|
||||
def thumbnailurl(self,name):
|
||||
return self.request.route_url('media_view',name='thumbnails',
|
||||
def thumbnailurl(self, name):
|
||||
return self.request.route_url('media_view', name='thumbnails',
|
||||
media_table=self.media_table,
|
||||
uid=self.linked_id) + '/' + name
|
||||
|
||||
def thumbnailpath(self,name):
|
||||
def thumbnailpath(self, name):
|
||||
origin = self.mediapath(name)
|
||||
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)):
|
||||
os.makedirs(os.path.dirname(TargetPath))
|
||||
return TargetPath
|
||||
|
||||
def createthumbnail(self, filename):
|
||||
image = Image.open( self.mediapath(filename) )
|
||||
image = Image.open(self.mediapath(filename))
|
||||
image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS)
|
||||
timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0))
|
||||
timage.paste(
|
||||
image,
|
||||
((THUMBNAIL_SIZE - image.size[0]) / 2, (THUMBNAIL_SIZE - image.size[1]) / 2))
|
||||
TargetFileName = self.thumbnailpath(filename)
|
||||
timage.save( TargetFileName )
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName) )
|
||||
timage.save(TargetFileName)
|
||||
return self.thumbnailurl(os.path.basename(TargetFileName))
|
||||
|
||||
def pdfthumbnail(self, filename):
|
||||
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)
|
||||
if Result==0:
|
||||
image = Image.open( TargetFileName+"_.jpg" )
|
||||
pdf_indicator = Image.open( "jm2l/static/img/PDF_Thumb_Stamp.png" )
|
||||
if Result == 0:
|
||||
image = Image.open(TargetFileName + "_.jpg")
|
||||
pdf_indicator = Image.open("jm2l/static/img/PDF_Thumb_Stamp.png")
|
||||
image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS)
|
||||
timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0))
|
||||
# Add thumbnail
|
||||
@@ -333,21 +335,21 @@ class MediaUpload(MediaPath):
|
||||
# Stamp with PDF file type
|
||||
timage.paste(
|
||||
pdf_indicator,
|
||||
(timage.size[0]-30, timage.size[1]-30),
|
||||
(timage.size[0] - 30, timage.size[1] - 30),
|
||||
pdf_indicator,
|
||||
)
|
||||
timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG')
|
||||
os.unlink(TargetFileName+"_.jpg")
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") )
|
||||
timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG')
|
||||
os.unlink(TargetFileName + "_.jpg")
|
||||
return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg"))
|
||||
return self.ExtMimeIcon('application/pdf')
|
||||
|
||||
def svgthumbnail(self, 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)
|
||||
if Result==0:
|
||||
image = Image.open( TargetFileName+"_.jpg" )
|
||||
pdf_indicator = Image.open( "jm2l/static/img/svg-icon.png" )
|
||||
if Result == 0:
|
||||
image = Image.open(TargetFileName + "_.jpg")
|
||||
pdf_indicator = Image.open("jm2l/static/img/svg-icon.png")
|
||||
image.thumbnail((THUMBNAIL_SIZE, THUMBNAIL_SIZE), Image.ANTIALIAS)
|
||||
timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0))
|
||||
# Add thumbnail
|
||||
@@ -357,12 +359,12 @@ class MediaUpload(MediaPath):
|
||||
# Stamp with PDF file type
|
||||
timage.paste(
|
||||
pdf_indicator,
|
||||
(timage.size[0]-30, timage.size[1]-30),
|
||||
(timage.size[0] - 30, timage.size[1] - 30),
|
||||
pdf_indicator,
|
||||
)
|
||||
timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG')
|
||||
os.unlink(TargetFileName+"_.jpg")
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") )
|
||||
timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG')
|
||||
os.unlink(TargetFileName + "_.jpg")
|
||||
return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg"))
|
||||
return self.ExtMimeIcon('image/svg+xml')
|
||||
|
||||
def docthumbnail(self, filename):
|
||||
@@ -370,16 +372,17 @@ class MediaUpload(MediaPath):
|
||||
# let's take the thumbnail generated inside the document
|
||||
Command = ["unzip", "-p", self.mediapath(filename), "Thumbnails/thumbnail.png"]
|
||||
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)
|
||||
# Use the correct stamp
|
||||
f, ext = os.path.splitext( filename )
|
||||
istamp = [ ('Writer','odt'),
|
||||
('Impress','odp'),
|
||||
('Calc','ods'),
|
||||
('Draw','odg')]
|
||||
stampfilename = filter(lambda (x,y): ext.endswith(y), istamp)
|
||||
stamp = Image.open( "jm2l/static/img/%s-icon.png" % stampfilename[0][0])
|
||||
f, ext = os.path.splitext(filename)
|
||||
istamp = [('Writer', 'odt'),
|
||||
('Impress', 'odp'),
|
||||
('Calc', 'ods'),
|
||||
('Draw', 'odg')]
|
||||
stampfilename = filter(lambda x, y: ext.endswith(y), istamp)
|
||||
stamp = Image.open("jm2l/static/img/%s-icon.png" % stampfilename[0][0])
|
||||
|
||||
timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0))
|
||||
# Add thumbnail
|
||||
timage.paste(
|
||||
@@ -388,11 +391,11 @@ class MediaUpload(MediaPath):
|
||||
# Stamp with PDF file type
|
||||
timage.paste(
|
||||
stamp,
|
||||
(timage.size[0]-30, timage.size[1]-30),
|
||||
(timage.size[0] - 30, timage.size[1] - 30),
|
||||
stamp,
|
||||
)
|
||||
timage.convert('RGB').save( TargetFileName+".jpg", 'JPEG')
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName+".jpg") )
|
||||
timage.convert('RGB').save(TargetFileName + ".jpg", 'JPEG')
|
||||
return self.thumbnailurl(os.path.basename(TargetFileName + ".jpg"))
|
||||
|
||||
def blendthumbnail(self, filename):
|
||||
blendfile = self.mediapath(filename)
|
||||
@@ -411,7 +414,7 @@ class MediaUpload(MediaPath):
|
||||
png = write_png(buf, width, height)
|
||||
TargetFileName = self.thumbnailpath(filename)
|
||||
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)
|
||||
timage = Image.new('RGBA', (THUMBNAIL_SIZE, THUMBNAIL_SIZE), (255, 255, 255, 0))
|
||||
# Add thumbnail
|
||||
@@ -421,17 +424,17 @@ class MediaUpload(MediaPath):
|
||||
# Stamp with Blender file type
|
||||
timage.paste(
|
||||
blender_indicator,
|
||||
(timage.size[0]-30, timage.size[1]-30),
|
||||
(timage.size[0] - 30, timage.size[1] - 30),
|
||||
blender_indicator,
|
||||
)
|
||||
timage.save( TargetFileName+".png")
|
||||
return self.thumbnailurl( os.path.basename(TargetFileName+".png") )
|
||||
timage.save(TargetFileName + ".png")
|
||||
return self.thumbnailurl(os.path.basename(TargetFileName + ".png"))
|
||||
return self.ExtMimeIcon('application/x-blender')
|
||||
|
||||
def fileinfo(self,name):
|
||||
def fileinfo(self, name):
|
||||
filename = self.mediapath(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['name'] = name
|
||||
info['size'] = os.path.getsize(filename)
|
||||
@@ -448,8 +451,8 @@ class MediaUpload(MediaPath):
|
||||
thumbext = ".jpg"
|
||||
if mime == "application/x-blender":
|
||||
thumbext = ".png"
|
||||
if os.path.exists( thumb + thumbext ):
|
||||
info['thumbnailUrl'] = self.thumbnailurl(name)+thumbext
|
||||
if os.path.exists(thumb + thumbext):
|
||||
info['thumbnailUrl'] = self.thumbnailurl(name) + thumbext
|
||||
else:
|
||||
info['thumbnailUrl'] = self.ExtMimeIcon(mime)
|
||||
else:
|
||||
@@ -488,7 +491,7 @@ class MediaUpload(MediaPath):
|
||||
n = self.fileinfo(f)
|
||||
if n:
|
||||
filelist.append(n)
|
||||
return { "files":filelist }
|
||||
return {"files": filelist}
|
||||
|
||||
@view_config(request_method='DELETE', xhr=True, accept="application/json", renderer='json')
|
||||
def delete(self):
|
||||
@@ -506,7 +509,7 @@ class MediaUpload(MediaPath):
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
os.remove(self.thumbnailpath(filename+".jpg"))
|
||||
os.remove(self.thumbnailpath(filename + ".jpg"))
|
||||
except IOError:
|
||||
pass
|
||||
except OSError:
|
||||
@@ -523,7 +526,7 @@ class MediaUpload(MediaPath):
|
||||
return self.delete()
|
||||
results = []
|
||||
for name, fieldStorage in self.request.POST.items():
|
||||
if isinstance(fieldStorage,unicode):
|
||||
if isinstance(fieldStorage, unicode):
|
||||
continue
|
||||
result = {}
|
||||
result['name'] = os.path.basename(fieldStorage.filename)
|
||||
@@ -531,26 +534,26 @@ class MediaUpload(MediaPath):
|
||||
result['size'] = self.get_file_size(fieldStorage.file)
|
||||
|
||||
if self.validate(result, fieldStorage.file):
|
||||
filename, file_extension = os.path.splitext( result['name'] )
|
||||
local_filename = slugify( filename ) + file_extension
|
||||
filename, file_extension = os.path.splitext(result['name'])
|
||||
local_filename = slugify(filename) + file_extension
|
||||
# Keep mime-type in .type file
|
||||
with open( self.mediapath( local_filename ) + '.type', 'w') as f:
|
||||
with open(self.mediapath(local_filename) + '.type', 'w') as f:
|
||||
f.write(result['type'])
|
||||
|
||||
# Store uploaded file
|
||||
fieldStorage.file.seek(0)
|
||||
with open( self.mediapath( local_filename ), 'wb') as f:
|
||||
shutil.copyfileobj( fieldStorage.file , f)
|
||||
with open(self.mediapath(local_filename), 'wb') as f:
|
||||
shutil.copyfileobj(fieldStorage.file, f)
|
||||
|
||||
if re.match(IMAGE_TYPES, result['type']):
|
||||
result['thumbnailUrl'] = self.createthumbnail(local_filename)
|
||||
elif result['type']=='application/pdf':
|
||||
elif result['type'] == 'application/pdf':
|
||||
result['thumbnailUrl'] = self.pdfthumbnail(local_filename)
|
||||
elif result['type']=='image/svg+xml':
|
||||
elif result['type'] == 'image/svg+xml':
|
||||
result['thumbnailUrl'] = self.svgthumbnail(local_filename)
|
||||
elif result['type'].startswith('application/vnd'):
|
||||
result['thumbnailUrl'] = self.docthumbnail(local_filename)
|
||||
elif result['type']=='application/x-blender':
|
||||
elif result['type'] == 'application/x-blender':
|
||||
result['thumbnailUrl'] = self.blendthumbnail(local_filename)
|
||||
else:
|
||||
result['thumbnailUrl'] = self.ExtMimeIcon(result['type'])
|
||||
@@ -568,26 +571,27 @@ class MediaUpload(MediaPath):
|
||||
if DELETEMETHOD != 'DELETE':
|
||||
result['deleteUrl'] += '&_method=DELETE'
|
||||
results.append(result)
|
||||
return {"files":results}
|
||||
return {"files": results}
|
||||
|
||||
|
||||
@view_defaults(route_name='media_view')
|
||||
class MediaView(MediaPath):
|
||||
|
||||
def __init__(self,request):
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
self.media_table = self.request.matchdict.get('media_table')
|
||||
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)
|
||||
|
||||
@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):
|
||||
name = self.request.matchdict.get('name')
|
||||
self.request.response.content_type = self.get_mimetype(name)
|
||||
|
||||
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:
|
||||
raise NotFound
|
||||
return self.request.response
|
||||
|
||||
+633
-562
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
|
||||
## Do not forget to run for lxml dependencies
|
||||
## apt-get install libxml2-dev libxslt1-dev
|
||||
|
||||
|
||||
requires = [
|
||||
'pyramid',
|
||||
'pyramid_chameleon',
|
||||
@@ -28,15 +29,19 @@ requires = [
|
||||
'python-magic',
|
||||
'Pillow',
|
||||
'pyramid_exclog',
|
||||
'repoze.sendmail==4.1',
|
||||
'repoze.sendmail',
|
||||
'pyramid_mailer',
|
||||
'apscheduler',
|
||||
'qrcode',
|
||||
'reportlab',
|
||||
'passlib',
|
||||
'argon2_cffi'
|
||||
'argon2_cffi',
|
||||
'paginate',
|
||||
'markupsafe',
|
||||
'webhelpers2',
|
||||
'email_validator',
|
||||
'pyramid-scheduler'
|
||||
]
|
||||
|
||||
setup(name='JM2L',
|
||||
version='0.1',
|
||||
description='JM2L',
|
||||
|
||||
Reference in New Issue
Block a user