Le repo des sources pour le site web des JM2L
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

1885 lignes
84 KiB

  1. # -*- coding: utf8 -*-
  2. from pyramid.httpexceptions import HTTPFound, HTTPNotFound, HTTPForbidden
  3. from pyramid.httpexceptions import HTTPBadRequest, HTTPUnauthorized
  4. from pyramid.renderers import render_to_response
  5. from pyramid.view import notfound_view_config, forbidden_view_config
  6. from pyramid.view import view_config
  7. from mako.template import Template
  8. from .upload import IMAGEPATH
  9. # Import Web Forms
  10. from .forms import *
  11. # Database access imports
  12. from .models import *
  13. from .helpers import Orga_helpers
  14. from sqlalchemy import func, or_, text, and_
  15. from os import path, makedirs, listdir
  16. # Usefull tools
  17. from slugify import slugify
  18. from icalendar import Calendar
  19. from pytz import timezone
  20. from icalendar import Event as Evt
  21. from pyramid_mailer.message import Message
  22. # Then, standard libs
  23. import webhelpers.paginate as paginate
  24. import unicodedata
  25. import datetime
  26. import re
  27. import shutil
  28. CurrentYear = 2015
  29. ## =-=- Here, We keep some usefull function -=-=
  30. def remove_accents(input_str):
  31. """ This function is intended to remove all accent from input unicode string """
  32. nkfd_form = unicodedata.normalize('NFKD', input_str)
  33. only_ascii = nkfd_form.encode('ASCII', 'ignore')
  34. return only_ascii
  35. def embeed_video(mime_type, link):
  36. Container = "<video controls='controls' preload='metadata' style='width:60%'>"
  37. Container += "<source type='%s' " % mime_type
  38. Container += "src='%s' />" % link
  39. Container += "</video>"
  40. return Container
  41. @view_config(route_name='Live', renderer="jm2l:templates/Live.mako")
  42. def Live(request):
  43. year = int(request.matchdict.get('year', CurrentYear))
  44. tz = timezone('Europe/Paris')
  45. curtime = datetime.datetime.now().replace(tzinfo=tz, day=28) #, hour=10, minute=00 )
  46. Events = DBSession.query(Event)\
  47. .filter(Event.for_year == year)\
  48. .filter(Event.event_type != 'Stand')\
  49. .filter(and_(Event.start_time <= curtime, Event.end_time >= curtime) )\
  50. .order_by(Event.start_time)
  51. return {'year': year, "DisplayYear": year, 'events':Events, "logged_in":request.authenticated_userid }
  52. ## =-=- Here, We handle ICal requests -=-=
  53. @view_config(route_name='progr_iCal', renderer="string")
  54. def ICal_Progamme_Request(request):
  55. year = int(request.matchdict.get('year', CurrentYear))
  56. # Initialization
  57. # Compute days used by all events matching the specified input year
  58. Events = DBSession.query(Event)\
  59. .filter(Event.for_year == year)\
  60. .filter(Event.event_type != 'Stand')\
  61. .order_by(Event.start_time)
  62. cal = Calendar()
  63. cal.add('prodid', '-//Programme %d//jm2l.linux-azur.org//' % year)
  64. cal.add('version', '2.0')
  65. tz = timezone('Europe/Paris')
  66. for ev in Events:
  67. if ev.event_type:
  68. event = Evt()
  69. event['uid'] = "%d/%d" % ( year, ev.uid )
  70. event.add('summary', ev.name )
  71. event.add('dtstart', ev.start_time.replace(tzinfo=tz) )
  72. event.add('dtend', ev.end_time.replace(tzinfo=tz) )
  73. event.add('created', ev.last_change.replace(tzinfo=tz) )
  74. event.add('description', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  75. event.add('url', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  76. event.add('priority', 5)
  77. cal.add_component(event)
  78. request.response.content_type = "text/calendar"
  79. return cal.to_ical()
  80. ## =-=- Here, We handle ICal requests -=-=
  81. @view_config(route_name='progr_dyn_iCal', renderer="string")
  82. def ICal_Progamme_Dyn_Request(request):
  83. year = int(request.matchdict.get('year', CurrentYear))
  84. # Initialization
  85. # Compute days used by all events matching the specified input year
  86. Events = DBSession.query(Event)\
  87. .filter(Event.for_year == year)\
  88. .filter(Event.event_type != 'Stand')\
  89. .order_by(Event.start_time)
  90. cal = Calendar()
  91. cal.add('prodid', '-//Programme %d//jm2l.linux-azur.org//' % year)
  92. cal.add('version', '2.0')
  93. today = datetime.datetime.now()
  94. tz = timezone('Europe/Paris')
  95. event = Evt()
  96. event['uid'] = "%d/%d" % ( year, 100 )
  97. event.add('summary', "Les stands JM2L 2015" )
  98. event.add('dtstart', datetime.datetime.now().replace(tzinfo=tz, hour=10, minute=00 ) )
  99. event.add('dtend', datetime.datetime.now().replace(tzinfo=tz, hour=18, minute=00 ) )
  100. event.add('created', datetime.datetime.now().replace(tzinfo=tz, hour=10, minute=00 ) )
  101. event.add('description', "https://www.youtube.com/watch?v=91X65eEKxvU&t=6s" )
  102. event.add('location', "http://jm2l.linux-azur.org/img/325.gif" )
  103. event.add('url', "http://jm2l.linux-azur.org/2015/le-programme" )
  104. event.add('priority', 5)
  105. cal.add_component(event)
  106. TabCorr = {
  107. 135:"Koneko",
  108. 131:"cam-jm2l-a",
  109. 132:"cam-jm2l-b",
  110. 115:"cam-jm2l-e",
  111. 114:"cam-jm2l-f"
  112. }
  113. for i, ev in enumerate(Events):
  114. if ev.event_type:
  115. event = Evt()
  116. event['uid'] = "%d/%d" % ( year, ev.uid )
  117. event.add('summary', ev.name )
  118. event.add('dtstart', ev.start_time.replace(tzinfo=tz, day=today.day, month = today.month, hour=(ev.start_time.hour)%24 ) )
  119. event.add('dtend', ev.end_time.replace(tzinfo=tz, day=today.day, month = today.month, hour=(ev.end_time.hour)%24 ) )
  120. event.add('created', ev.last_change.replace(tzinfo=tz) )
  121. event.add('description', "http://jm2l.linux-azur.org:8081/%s.webm" % TabCorr.get(ev.Salle.phy_salle_id, ev.Salle.phy_salle_id) )
  122. event.add('location', "http://jm2l.linux-azur.org/img/%d.gif" % ev.Salle.phy_salle_id )
  123. event.add('url', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  124. event.add('priority', 5)
  125. cal.add_component(event)
  126. request.response.content_type = "text/calendar"
  127. return cal.to_ical()
  128. ## =-=- Here, We handle Json requests -=-=
  129. @view_config(route_name='users_json', renderer="json")
  130. def JSON_User_Request(request):
  131. """ Build a JSON answer with active users and pagination handling """
  132. # Check arguments consitency
  133. pageSize = request.params.get('pageSize',"8")
  134. current_page = request.params.get('pageNum',"1")
  135. UserQuery = request.params.get('searchTerm', u"")
  136. # Don't answer to users that aren't logged
  137. if not request.user:
  138. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  139. # Check consistancy of parameters
  140. if pageSize.isdigit() and current_page.isdigit():
  141. current_page = int(current_page)
  142. pageSize = int(pageSize)
  143. else:
  144. return HTTPBadRequest('pageSize and pageNum accept only digits.')
  145. # Query database
  146. Users = DBSession.query(User.uid, User.nom, User.prenom)\
  147. .filter(User.slug.contains( remove_accents(UserQuery) ))
  148. page_url = paginate.PageURL_WebOb(request)
  149. records = paginate.Page(Users, current_page, url=page_url, items_per_page=pageSize)
  150. ListMatchUser = map( lambda u:{"id": u.uid, "text":"%s %s" % ( u.prenom, u.nom )}, records )
  151. return { "Results": ListMatchUser, "Total":records.item_count,
  152. "logged_in":request.authenticated_userid }
  153. @view_config(route_name='tiers_json', renderer="json")
  154. def JSON_Tiers_Request(request):
  155. """ Build a JSON answer with active users and pagination handling """
  156. # Check arguments consitency
  157. pageSize = request.params.get('pageSize',"8")
  158. current_page = request.params.get('pageNum',"1")
  159. TiersQuery = request.params.get('searchTerm', u"")
  160. # Don't answer to users that aren't logged
  161. if not request.user:
  162. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  163. # Check consistancy of parameters
  164. if pageSize.isdigit() and current_page.isdigit():
  165. current_page = int(current_page)
  166. pageSize = int(pageSize)
  167. else:
  168. return HTTPBadRequest('pageSize and pageNum accept only digits.')
  169. # Query database
  170. JTiers = DBSession.query(Tiers.uid, Tiers.name)\
  171. .filter(Tiers.slug.contains( remove_accents(TiersQuery) ))
  172. page_url = paginate.PageURL_WebOb(request)
  173. records = paginate.Page(JTiers, current_page, url=page_url, items_per_page=pageSize)
  174. ListMatchTiers = map( lambda t:{"id": t.uid, "text": t.name }, records )
  175. return { "Results": ListMatchTiers, "Total":records.item_count,
  176. "logged_in":request.authenticated_userid }
  177. @view_config(route_name='progr_json', renderer="json")
  178. def JSON_Progamme_Request(request):
  179. year = int(request.matchdict.get('year', CurrentYear))
  180. # Initialization
  181. DicResult = dict()
  182. # Query database
  183. # Compute days used by all events matching the specified input year
  184. Days = DBSession.query( func.strftime('%d', Event.start_time).label('day') )\
  185. .filter(Event.for_year == year)\
  186. .filter(Event.event_type != None)\
  187. .group_by(func.strftime('%d', Event.start_time)).all()
  188. for Day in Days:
  189. Events = DBSession.query(Event)\
  190. .filter(Event.for_year == year)\
  191. .filter(Event.event_type != 'Stand')\
  192. .filter(text("strftime('%d', start_time) = :dow")).params(dow=Day.day)\
  193. .order_by(Event.start_time)
  194. ListEv = []
  195. for ev in Events:
  196. if ev.event_type:
  197. ListEv.append( {
  198. "uid":"%d/%d" % ( year, ev.uid ),
  199. "desc":ev.name,
  200. "startDate":ev.start_time.strftime('%Y-%m-%dT%H:%M:%S+01:00'),
  201. "endDate":ev.end_time.strftime('%Y-%m-%dT%H:%M:%S+01:00'),
  202. "placeName":ev.Salle and (ev.Salle.name or "unk") ,
  203. "status":ev.event_type
  204. } )
  205. DicResult[Day.day] = ListEv
  206. return { 'all':DicResult }
  207. @view_config(route_name='timeline_json', renderer="json")
  208. def JSON_TimeLine_Request(request):
  209. year = int(request.matchdict.get('year', CurrentYear))
  210. # Initialization
  211. DicResult = dict()
  212. # Query database
  213. # Compute days used by all events matching the specified input year
  214. Days = DBSession.query( func.strftime('%d', Event.start_time).label('day') )\
  215. .filter(Event.for_year == year)\
  216. .filter(Event.event_type != None)\
  217. .group_by(func.strftime('%d', Event.start_time)).all()
  218. ListEv = []
  219. for Day in Days:
  220. Events = DBSession.query(Event)\
  221. .filter(Event.for_year == year)\
  222. .filter(Event.event_type != 'Stand')\
  223. .filter(text("strftime('%d', start_time) = :dow")).params(dow=Day.day)\
  224. .order_by(Event.start_time)
  225. #ListEv = []
  226. for ev in Events:
  227. if ev.event_type:
  228. CurMedia = ev.video.first() or ""
  229. if CurMedia:
  230. Container = "<video controls='controls' preload='metadata' style='width:60%'>"
  231. Container += "<source type='%s' " % CurMedia.mime_type
  232. Container += "src='%s' />" % CurMedia.get_path
  233. Container += "</video>"
  234. else:
  235. Container = ""
  236. ListEv.append( {
  237. #"uid":"%d/%d" % ( year, ev.uid ),
  238. "headline":'<a href="/event/%s/%s">%s</a>' % (ev.for_year, ev.slug, ev.name),
  239. "startDate":ev.start_time.strftime('%Y,%m,%d,%H,%M'),
  240. "endDate":ev.end_time.strftime('%Y,%m,%d,%H,%M'),
  241. "text": ev.Salle and (ev.Salle.name or "unk"),
  242. #"text":ev.description[:100],
  243. "tags":ev.Salle and (ev.Salle.salle_id or "unk") ,
  244. #"status":ev.event_type,
  245. "asset": {
  246. "media": Container,
  247. "credit": ",".join(["%s %s" % (i.prenom, i.nom) for i in ev.intervenants]),
  248. "caption":"" }
  249. } )
  250. if year==2015:
  251. DicResult = {
  252. "lang":"fr",
  253. "headline":"JM2L 2015",
  254. "type":"default",
  255. "startDate":"2015,11,28,10",
  256. "text":"<i><span class='c1'>9ème Édition</span></i>",
  257. "asset":
  258. {
  259. "media":"https://www.youtube.com/watch?v=91X65eEKxvU&t=6s",
  260. "credit":"Polytech nice sophia",
  261. "caption":"JM2L 2015"
  262. }
  263. }
  264. elif year==2011:
  265. DicResult = {
  266. "lang":"fr",
  267. "headline":"JM2L 2011",
  268. "type":"default",
  269. "startDate":"2011,11,25,10",
  270. "text":"<i><span class='c1'>6ème Édition</span></i>",
  271. "asset":
  272. {
  273. "media":"https://www.youtube.com/embed/rcaNeXuAEhs",
  274. "credit":"JM2L",
  275. "caption":"Reportage FR3"
  276. },
  277. }
  278. elif year==2010:
  279. DicResult = {
  280. "lang":"fr",
  281. "headline":"JM2L 2010",
  282. "type":"default",
  283. "text":"<i><span class='c1'>5ème Édition</span></i>",
  284. "asset":
  285. {
  286. "media":embeed_video("video/ogg","http://jm2l.linux-azur.org/resources/2010/Video/reportages/JM2L2010-PleinSudTV.ogv"),
  287. "credit":"<a href='http://pleinsudtv.com/index.php/casa/affichage-en-vignettes/93-casa-culture/582-les-jm-du-logiciel-libre-2010'>Le reportage Plein-sud TV</a>",
  288. "caption":"JM2L",
  289. }
  290. }
  291. elif year==2007:
  292. DicResult = {
  293. "lang":"fr",
  294. "headline":"JM2L 2007",
  295. "type":"default",
  296. "text":"<i><span class='c1'>2ème Édition</span></i>",
  297. "asset":
  298. {
  299. "media":embeed_video("video/ogg","http://jm2l.linux-azur.org/resources/2007/Video/20071110-linux.ogv"),
  300. "credit":"<a href='http://pleinsudtv.com/index.php/casa/affichage-en-vignettes/93-casa-culture/245-logiciel-libre-linux-jm2l'>Le reportage Plein-sud TV</a>",
  301. "caption":"JM2L 2007",
  302. }
  303. }
  304. else:
  305. DicResult = {
  306. "lang":"fr",
  307. "headline":"JM2L %d" % year,
  308. "type":"default",
  309. "asset":
  310. {
  311. "media":"",
  312. "credit":"JM2L",
  313. "caption":""
  314. }
  315. }
  316. DicResult["date"] = ListEv
  317. return { 'timeline':DicResult }
  318. ## =-=- Here, We handle HTTP requests - Public Part -=-=
  319. @view_config(route_name='home', renderer="jm2l:templates/NewIndex.mako")
  320. def index_page(request):
  321. year = request.matchdict.get('year')
  322. if year:
  323. year=int(year[:-1])
  324. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  325. if content:
  326. content = content.description
  327. else:
  328. content = ""
  329. if 2004<year<=CurrentYear:
  330. if year==2006:
  331. return {'year': year, 'content':content, 'edition':u"1<sup>ère</sup>" }
  332. elif year==2015:
  333. return {'year': year, 'content':content, 'edition':u"9<sup>ème</sup>" }
  334. else:
  335. edition = year - 2005
  336. return {'year': year, 'content':content, 'edition':u"%d<sup>ème</sup>" % edition }
  337. else:
  338. raise HTTPNotFound()
  339. else:
  340. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==CurrentYear).first().description
  341. TargetDir = "jm2l/static/img/%s/Photos" % (year or 2015)
  342. TargetUrl = "/static/img/%s/Photos/" % (year or 2015)
  343. if path.isdir(TargetDir):
  344. ListPhotos = map(lambda x: TargetUrl + x, listdir(TargetDir))
  345. else:
  346. ListPhotos = []
  347. return {'year': CurrentYear, 'content':content, 'edition':u"9<sup>ème</sup>", 'ListPhotos': ListPhotos}
  348. @view_config(route_name='edit_index', renderer="jm2l:templates/Staff/EditIndex.mako")
  349. def edit_index(request):
  350. year = int(request.matchdict.get('year', None))
  351. if not request.user.Staff:
  352. # Don't answer to users that aren't logged
  353. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  354. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  355. form = IndexForm(request.POST, content, meta={'csrf_context': request.session})
  356. if request.method == 'POST' and form.validate():
  357. form.populate_obj(content)
  358. return HTTPFound(location=request.route_url('home', year="%d/" % year))
  359. MainTab = {'home':'active', "logged_in":request.authenticated_userid,
  360. 'form':form, 'DisplayYear':year}
  361. return MainTab
  362. @view_config(route_name='programme', renderer="jm2l:templates/Public/Programme.mako")
  363. def programme(request):
  364. year = int(request.matchdict.get('year'))
  365. if 2006 > year:
  366. return HTTPBadRequest('The first JM2L event was in 2006.')
  367. # Query database about selected Year.
  368. Events = DBSession.query(Event)\
  369. .filter(Event.for_year == year)\
  370. .order_by(Event.start_time)
  371. Days = DBSession.query(func.strftime('%d-%m-%Y', Event.start_time))\
  372. .filter(Event.for_year == year)\
  373. .filter(Event.event_type != None)\
  374. .group_by(func.strftime('%d', Event.start_time)).all()
  375. ListDay = []
  376. for day in Days:
  377. RefDay = datetime.datetime.strptime(day[0],'%d-%m-%Y')
  378. ListDay.append( ( RefDay.strftime('%A %d %b %Y'),
  379. RefDay.strftime('%d') ) )
  380. MainTab = {'programme':'active','DisplayYear':year, \
  381. 'Events':Events, 'Event':Event, 'Days':ListDay, "logged_in":request.authenticated_userid }
  382. return MainTab
  383. @view_config(route_name='presse', renderer="jm2l:templates/Public/Presse.mako")
  384. def static_presse(request):
  385. year = int(request.matchdict.get('year', None))
  386. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  387. MainTab = {'presse':'active', "logged_in":request.authenticated_userid, 'content':content, 'DisplayYear':year}
  388. return MainTab
  389. @view_config(route_name='edit_presse', renderer="jm2l:templates/Staff/EditPresse.mako")
  390. def edit_presse(request):
  391. year = int(request.matchdict.get('year', None))
  392. if request.user is None:
  393. # Don't answer to users that aren't logged
  394. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  395. if not request.user.Staff:
  396. # Don't answer to users that aren't logged
  397. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  398. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  399. form = DossPresse(request.POST, content, meta={'csrf_context': request.session})
  400. if request.method == 'POST' and form.validate():
  401. form.populate_obj(content)
  402. MainTab = {'presse':'active', "logged_in":request.authenticated_userid, 'form':form, 'DisplayYear':year}
  403. return MainTab
  404. @view_config(route_name='plan', renderer="jm2l:templates/Public/Plan.mako")
  405. def static_plan(request):
  406. session = request.session
  407. session['year'] = 2015
  408. MainTab = {'plan':'active', "logged_in":request.authenticated_userid }
  409. return MainTab
  410. ## =-=- Here, We handle HTTP requests - Staff Logged Part -=-=
  411. @view_config(route_name='list_task', renderer='jm2l:templates/Staff/list.mako')
  412. def list_view(request):
  413. if request.user is None:
  414. # Don't answer to users that aren't logged
  415. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  416. if not request.user.Staff:
  417. # Don't answer to users that aren't logged
  418. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  419. DicTask = {}
  420. taskgroup = DBSession.query( TasksArea ).all()
  421. for grp in taskgroup:
  422. tasks = DBSession.query( Tasks )\
  423. .filter( Tasks.area_uid==grp.uid )\
  424. .order_by(Tasks.closed, Tasks.due_date).all()
  425. DicTask[grp] = tasks
  426. return {'tasks': DicTask }
  427. @view_config(route_name='handle_task', renderer='jm2l:templates/Staff/tasks.mako')
  428. def tasks(request):
  429. if request.user is None:
  430. # Don't answer to users that aren't logged
  431. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  432. if not request.user.Staff:
  433. # Don't answer to users that aren't logged
  434. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  435. task_id = request.matchdict.get('task_id')
  436. # Convert the pole_id GET parameter to int or 0
  437. if request.params.get('pole_id') and request.params.get('pole_id').isdigit():
  438. pole_id = int(request.params.get('pole_id'))
  439. else:
  440. pole_id = None
  441. # Get areas from db
  442. Areas = DBSession.query(TasksArea.uid, TasksArea.name)\
  443. .order_by('name').all()
  444. # Get users from db
  445. Users = DBSession.query(User)\
  446. .filter(User.Staff==1)\
  447. .order_by('nom').all()
  448. if task_id:
  449. TmpTask = Tasks.by_id(int(task_id))
  450. if not TmpTask:
  451. raise HTTPNotFound()
  452. form = EditStaffTasks(request.POST, TmpTask, meta={'csrf_context': request.session})
  453. else:
  454. TmpTask = Tasks()
  455. # Check if the supplied pole_id is in the Areas' range
  456. form = StaffTasks(request.POST, TmpTask, meta={'csrf_context': request.session})
  457. Area = TasksArea.by_id(pole_id)
  458. if Area:
  459. form.area_uid.data = Area.uid
  460. # Put some areas on form
  461. form.area_uid.choices = Areas
  462. # Put some users on form
  463. form.closed_by.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  464. for u in Users]
  465. form.due_date.type = "date"
  466. if request.method=='POST' and form.validate():
  467. form.populate_obj(TmpTask)
  468. TmpTask.closed = False
  469. if 'uid' in form._fields.keys():
  470. DBSession.merge(TmpTask)
  471. else:
  472. DBSession.add(TmpTask)
  473. DBSession.flush()
  474. return HTTPFound(location=request.route_url('list_task')+"#"+slugify(TmpTask.area.name))
  475. return {'form':form, 'area':TmpTask.area and slugify(TmpTask.area.name) or ''}
  476. @view_config(route_name='handle_pole', renderer='jm2l:templates/Staff/pole.mako')
  477. def tasks_area(request):
  478. if request.user is None:
  479. # Don't answer to users that aren't logged
  480. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  481. if not request.user.Staff:
  482. # Don't answer to users that aren't logged
  483. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  484. pole_id = request.matchdict.get('pole_id')
  485. if pole_id:
  486. Pole = TasksArea.by_id(int(pole_id))
  487. if not Pole:
  488. raise HTTPNotFound()
  489. form = EditStaffArea(request.POST, Pole, meta={'csrf_context': request.session})
  490. else:
  491. Pole = TasksArea()
  492. form = StaffArea(request.POST, Pole, meta={'csrf_context': request.session})
  493. if request.method == 'POST' and form.validate():
  494. form.populate_obj(Pole)
  495. if 'uid' in form._fields.keys():
  496. DBSession.merge(Pole)
  497. else:
  498. DBSession.add(Pole)
  499. return HTTPFound(location=request.route_url('list_task')+"#"+slugify(Pole.name))
  500. return {'form':form }
  501. @view_config(route_name='action_task')
  502. def action_task(request):
  503. if request.user is None:
  504. # Don't answer to users that aren't logged
  505. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  506. if not request.user.Staff:
  507. # Don't answer to users that aren't logged
  508. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  509. action = request.matchdict.get('action')
  510. task_id = request.matchdict.get('task_id')
  511. Task = Tasks.by_id(int(task_id))
  512. if action=='close':
  513. Task.closed = True
  514. request.session.flash(('info', u'La tâche a été fermé, Félicitations !'))
  515. DBSession.merge(Task)
  516. if action=='open':
  517. Task.closed = False
  518. request.session.flash(('info', u'La tâche a été ré-ouverte !'))
  519. DBSession.merge(Task)
  520. if action=='delete':
  521. request.session.flash(('info', u'La tâche a été supprimée !'))
  522. DBSession.delete(Task)
  523. return HTTPFound(location=request.route_url('list_task')+"#"+slugify(Task.area.name))
  524. @view_config(route_name='action_task_area')
  525. def action_task_area(request):
  526. if request.user is None:
  527. # Don't answer to users that aren't logged
  528. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  529. if not request.user.Staff:
  530. # Don't answer to users that aren't logged
  531. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  532. action = request.matchdict.get('action')
  533. pole_id = request.matchdict.get('pole_id')
  534. Pole = TasksArea.by_id(int(pole_id))
  535. if not Pole:
  536. raise HTTPNotFound()
  537. if action=='delete':
  538. request.session.flash(('info', u'Le pôle a été supprimé !'))
  539. DBSession.delete(Pole)
  540. return HTTPFound(location=request.route_url('list_task'))
  541. @view_config(route_name='list_salles', renderer='jm2l:templates/Salles/list.mako')
  542. def list_salles(request):
  543. if request.user is None:
  544. # Don't answer to users that aren't logged
  545. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  546. if not request.user.Staff:
  547. # Don't answer to users that aren't logged
  548. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  549. DicSalle = {}
  550. years = DBSession.query( JM2L_Year ).all()
  551. for year in years:
  552. salles = DBSession.query( Salles )\
  553. .filter( Salles.year_uid==year.year_uid )\
  554. .order_by(Salles.name).all()
  555. DicSalle[year] = salles
  556. return {'DicSalle': DicSalle }
  557. @view_config(route_name='handle_salle', renderer='jm2l:templates/Salles/salle.mako')
  558. def handle_salle(request):
  559. if request.user is None:
  560. # Don't answer to users that aren't logged
  561. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  562. if not request.user.Staff:
  563. # Don't answer to users that aren't logged
  564. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  565. salle_id = request.matchdict.get('salle_id')
  566. if salle_id:
  567. Salle = Salles.by_id(int(salle_id))
  568. if not Salle:
  569. raise HTTPNotFound()
  570. form = EditSalleForm(request.POST, Salle, meta={'csrf_context': request.session})
  571. else:
  572. Salle = Salles()
  573. form = SalleForm(request.POST, Salle, meta={'csrf_context': request.session})
  574. form.year_uid.choices = map(tuple, DBSession.query(JM2L_Year.year_uid, JM2L_Year.year_uid).all())
  575. form.phy_salle_id.choices = map(tuple, DBSession.query(SallePhy.uid, SallePhy.name).all())
  576. if request.method == 'POST' and form.validate():
  577. form.populate_obj(Salle)
  578. if 'uid' in form._fields.keys():
  579. DBSession.merge(Salle)
  580. else:
  581. DBSession.add(Salle)
  582. return HTTPFound(location=request.route_url('list_salles'))
  583. return {'form':form }
  584. @view_config(route_name='handle_salle_phy', renderer='jm2l:templates/Salles/salle_phy.mako')
  585. def handle_salle_phy(request):
  586. if request.user is None:
  587. # Don't answer to users that aren't logged
  588. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  589. if not request.user.Staff:
  590. # Don't answer to users that aren't logged
  591. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  592. salle_id = request.matchdict.get('salle_id')
  593. if salle_id:
  594. Salle = SallePhy.by_id(int(salle_id))
  595. if not Salle:
  596. raise HTTPNotFound()
  597. form = EditSallePhyForm(request.POST, Salle, meta={'csrf_context': request.session})
  598. else:
  599. Salle = SallePhy()
  600. form = SallePhyForm(request.POST, Salle, meta={'csrf_context': request.session})
  601. if request.method == 'POST' and form.validate():
  602. form.populate_obj(Salle)
  603. Salle.slug = slugify(Salle.name)
  604. if 'uid' in form._fields.keys():
  605. DBSession.merge(Salle)
  606. else:
  607. DBSession.add(Salle)
  608. return HTTPFound(location=request.route_url('list_salles'))
  609. return {'form':form }
  610. @view_config(route_name='action_salle')
  611. def action_salle(request):
  612. if request.user is None:
  613. # Don't answer to users that aren't logged
  614. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  615. if not request.user.Staff:
  616. # Don't answer to users that aren't logged
  617. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  618. action = request.matchdict.get('action')
  619. salle_id = request.matchdict.get('salle_id')
  620. Salle = Salles.by_id(int(salle_id))
  621. if not Salle:
  622. raise HTTPNotFound()
  623. if action=='delete':
  624. request.session.flash(('info', u'La Salle a été supprimée !'))
  625. DBSession.delete(Salle)
  626. return HTTPFound(location=request.route_url('list_salles'))
  627. ## =-=- Here, We handle HTTP requests - User Logged Part -=-=
  628. @view_config(route_name='exchange', renderer="jm2l:templates/Logistique/Logistique.mako")
  629. def exchange(request):
  630. modtype = request.matchdict.get('modtype', None)
  631. action = request.matchdict.get('action', None)
  632. uid = int(request.matchdict.get('id', -1))
  633. Exch = Exchange.by_id(uid)
  634. if not Exch:
  635. MainTab = {
  636. 'Exchanges':Exchange,
  637. 'Type':modtype[-1:],
  638. 'reload':True,
  639. 'logged_in':request.authenticated_userid
  640. }
  641. return MainTab
  642. if action in ['delete', 'accept', 'refuse', 'deal']:
  643. if action=='delete': # delete exchange
  644. DBSession.delete(Exch)
  645. elif action=='accept': # accept exchange
  646. Exch.exch_done=True
  647. DBSession.merge(Exch)
  648. elif action=='refuse': # refuse exchange
  649. Exch.exch_done=False
  650. if Exch.exch_state=="Ask":
  651. Exch.provider_id = None
  652. elif Exch.exch_state=="Proposal":
  653. Exch.asker_id = None
  654. DBSession.merge(Exch)
  655. elif action=='deal':
  656. # ask to deal the exchange
  657. if Exch.exch_state=="Ask":
  658. Exch.provider_id = request.user.uid
  659. elif Exch.exch_state=="Proposal":
  660. Exch.asker_id = request.user.uid
  661. # Return javascript to parent page
  662. response = render_to_response('jm2l:templates/modals_js.mako',
  663. {'modtype':modtype, 'action':action},
  664. request=request)
  665. response.content_type = 'text/javascript'
  666. return response
  667. else:
  668. MainTab = {
  669. 'Exchanges':Exchange,
  670. 'Type':modtype[-1:],
  671. 'reload':True,
  672. 'logged_in':request.authenticated_userid
  673. }
  674. return MainTab
  675. @view_config(route_name='miam')
  676. def miam(request):
  677. if request.user is None:
  678. # Don't answer to users that aren't logged
  679. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  680. miam_form = MiamForm(request.POST, request.user, meta={'csrf_context': request.session})
  681. if request.method == 'POST' and miam_form.validate():
  682. FicheSejour = Sejour.by_user(request.user.uid)
  683. if FicheSejour:
  684. Update=True
  685. else:
  686. FicheSejour = Sejour()
  687. FicheSejour.created = datetime.datetime.now()
  688. Update=False
  689. Repas=0
  690. for num, item in enumerate(['RepasVendredi', 'RepasSamediMidi', 'RepasSamediSoir']):
  691. if request.params.get(item)==u"1":
  692. Repas += 2**num
  693. FicheSejour.repas = Repas
  694. FicheSejour.repas_allerg = request.params.get('Allergies')
  695. FicheSejour.repas_contr = request.params.get('Contraintes')
  696. FicheSejour.user_id = request.user.uid
  697. FicheSejour.for_year = CurrentYear
  698. if Update:
  699. DBSession.merge(FicheSejour)
  700. else:
  701. DBSession.add(FicheSejour)
  702. request.session.flash(('info',u'Votre fiche a été mise à jour avec succès'))
  703. else:
  704. request.session.flash(('error',u'Un problème est survenu'))
  705. return HTTPFound(location='/MesJM2L#Miam')
  706. @view_config(route_name='sejour')
  707. def sejour(request):
  708. if request.user is None:
  709. # Don't answer to users that aren't logged
  710. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  711. if request.method == 'POST':
  712. FicheSejour = Sejour.by_user(request.user.uid)
  713. if FicheSejour:
  714. Update=True
  715. else:
  716. FicheSejour = Sejour()
  717. FicheSejour.created = datetime.datetime.now()
  718. Update=False
  719. FicheSejour.user_id = request.user.uid
  720. FicheSejour.last_change = datetime.datetime.now()
  721. FicheSejour.for_year = CurrentYear
  722. # Arrival
  723. ArrDate = datetime.datetime.strptime(request.params.get('Arrival:Day'),"%d/%m/%y")
  724. ArrTime = datetime.datetime.strptime(request.params.get('Arrival:Hour'),"%H:%M")
  725. FicheSejour.arrival_time = datetime.datetime.combine(ArrDate.date(), ArrTime.time())
  726. ArrivalCheck=0
  727. for num, item in enumerate(['Arrival:PMR', 'Arrival:Cov', 'Arrival:Bras', 'Arrival:Other']):
  728. if request.params.get(item):
  729. ArrivalCheck += 2**num
  730. FicheSejour.arrival_check = ArrivalCheck
  731. FicheSejour.arrival_text = request.params.get('Arrival:Comment')
  732. FicheSejour.arrival_place = request.params.get('Arrival:Place')
  733. # Departure
  734. DepDate = datetime.datetime.strptime(request.params.get('Departure:Day'),"%d/%m/%y")
  735. DepTime = datetime.datetime.strptime(request.params.get('Departure:Hour'),"%H:%M")
  736. FicheSejour.depart_time = datetime.datetime.combine(DepDate.date(), DepTime.time())
  737. DepartCheck=0
  738. for num, item in enumerate(['Departure:PMR', 'Departure:Cov', 'Departure:Bras', 'Departure:Other']):
  739. if request.params.get(item):
  740. DepartCheck += 2**num
  741. FicheSejour.depart_check = DepartCheck
  742. FicheSejour.depart_text = request.params.get('Departure:Comment')
  743. FicheSejour.depart_place = request.params.get('Departure:Place')
  744. if Update:
  745. DBSession.merge(FicheSejour)
  746. request.session.flash(('info',u'Vos modifications de séjour ont été pris en compte.'))
  747. else:
  748. DBSession.add(FicheSejour)
  749. request.session.flash(('info',u'\\o/ Votre séjour est enregistré ! Complétez la partie Logistique.'))
  750. return HTTPFound(location='/MesJM2L#Sejour')
  751. @view_config(route_name='orga')
  752. def orga(request):
  753. if request.user is None:
  754. # Don't answer to users that aren't logged
  755. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  756. if request.method == 'POST':
  757. FicheSejour = Sejour.by_user(request.user.uid)
  758. UpdateOrga=False
  759. if FicheSejour:
  760. Update=True
  761. if FicheSejour.orga_part:
  762. UpdateOrga=True
  763. else:
  764. FicheSejour = Sejour()
  765. FicheSejour.created = datetime.datetime.now()
  766. Update=False
  767. FicheSejour.user_id = request.user.uid
  768. FicheSejour.last_change = datetime.datetime.now()
  769. FicheSejour.for_year = CurrentYear
  770. OrgaPart=0
  771. for item in request.params:
  772. try:
  773. nb = int(item[1:])
  774. except:
  775. continue
  776. OrgaPart += 2**nb
  777. FicheSejour.orga_part = OrgaPart
  778. if UpdateOrga:
  779. request.session.flash(('info',u'Vos modifications de participation à l\'organisation ont été pris en compte.'))
  780. else:
  781. request.session.flash(('info',u'\\o/ Votre participation à l\'organisation est enregistrée !'))
  782. if Update:
  783. DBSession.merge(FicheSejour)
  784. else:
  785. DBSession.add(FicheSejour)
  786. return HTTPFound(location='/MesJM2L#Organisation')
  787. @view_config(route_name='vote_logo')
  788. def vote_logo(request):
  789. if request.user is None:
  790. # Don't answer to users that aren't logged
  791. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  792. else:
  793. vote = int(request.matchdict.get('num', -1))
  794. come = request.params.get('come_from')
  795. if vote:
  796. request.user.vote_logo=vote
  797. DBSession.merge(request.user)
  798. request.session.flash(('info',u'Votre vote à été pris en compte.'))
  799. return HTTPFound('/')
  800. else:
  801. request.session.flash(('warning',u"Votre vote n'a été pris en compte."))
  802. if come:
  803. return HTTPFound(location=come)
  804. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  805. @view_config(route_name='list_users', renderer="jm2l:templates/Participant/list_users.mako")
  806. def list_users(request):
  807. if request.user is None:
  808. # Don't answer to users that aren't logged
  809. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  810. if not request.user.Staff:
  811. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  812. Data = DBSession.query(User, Sejour).outerjoin(Sejour).all()
  813. Repas = DBSession.query(Sejour.repas).all()
  814. DicRepas = {"Ven":0, "Midi":0, "Soir":0}
  815. for r in Repas:
  816. if r[0] is None:
  817. continue
  818. if (r[0] & 1 == 1): DicRepas["Ven"]+=1
  819. if (r[0] & 2 == 2): DicRepas["Midi"]+=1
  820. if (r[0] & 4 == 4): DicRepas["Soir"]+=1
  821. return { 'Users':Data, 'UserEvent' : User_Event, "DicRepas":DicRepas }
  822. @view_config(route_name='list_orga', renderer="jm2l:templates/Participant/list_orga.mako")
  823. def list_orga(request):
  824. if request.user is None:
  825. # Don't answer to users that aren't logged
  826. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  827. if not request.user.Staff:
  828. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  829. Data = DBSession.query(User, Sejour).outerjoin(Sejour).all()
  830. return { 'Users':Data }
  831. @view_config(route_name='jm2l', renderer="jm2l:templates/jm2l.mako")
  832. def jm2l_page(request):
  833. if request.user is None:
  834. # Don't answer to users that aren't logged
  835. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  836. UserNum = request.params.get('user')
  837. if UserNum:
  838. profil = User.by_id(int(UserNum))
  839. if not profil:
  840. raise HTTPNotFound()
  841. if not request.user.Staff:
  842. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  843. else:
  844. profil = request.user
  845. FicheSejour = Sejour()
  846. FicheSejour.created = datetime.datetime.now()
  847. # Build Form
  848. profil_form = ProfilForm(request.POST, profil, meta={'csrf_context': request.session})
  849. miam_form = MiamForm(request.POST, profil, meta={'csrf_context': request.session})
  850. # Feed FicheSejour if any
  851. FicheSejour = Sejour.by_user(profil.uid)
  852. if FicheSejour:
  853. if FicheSejour.repas is not None:
  854. for num, item in enumerate(['RepasVendredi', 'RepasSamediMidi', 'RepasSamediSoir']):
  855. if FicheSejour.repas & 2**num:
  856. miam_form._fields[item].data = "1"
  857. else:
  858. miam_form._fields[item].data = "0"
  859. miam_form._fields['Allergies'].data = FicheSejour.repas_allerg
  860. miam_form._fields['Contraintes'].data = FicheSejour.repas_contr
  861. if request.method == 'POST' and profil_form.validate():
  862. ToDelete = list()
  863. # First, we remove entries no more present
  864. for obj in profil_form.tiersship.object_data:
  865. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  866. profil_form.tiersship.entries )
  867. if not MatchEntry:
  868. ToDelete.append(obj)
  869. # Then, it's time to consider new entries
  870. for entry in profil_form.tiersship.entries:
  871. if entry.object_data is None:
  872. TmpUser = User_Tiers()
  873. entry.object_data = TmpUser
  874. profil.tiersship.append(TmpUser)
  875. profil_form.tiersship.object_data = profil.tiersship
  876. profil_form.populate_obj(profil)
  877. # We should remove it as it's not in original data
  878. for obj in ToDelete:
  879. #profil.tiersship.remove(obj)
  880. DBSession.delete(obj)
  881. profil.last_change = datetime.datetime.utcnow()
  882. profil.slug = slugify(remove_accents('%s %s' % (profil.prenom, profil.nom)).lower().strip())
  883. DBSession.merge(profil)
  884. request.session.flash(('info',u'Votre fiche a été mise à jour avec succès'))
  885. MainTab = {'participer':'active',
  886. 'Places':Place.get_list(False),
  887. 'DBTiers':Tiers,
  888. 'DBTiersOpt':TiersOpt,
  889. 'Exchanges':Exchange,
  890. 'profil_form':profil_form,
  891. 'miam_form':miam_form,
  892. 'uprofil':profil,
  893. 'logged_in':request.authenticated_userid
  894. }
  895. return MainTab
  896. @view_config(route_name='modal', renderer="jm2l:templates/modals.mako")
  897. def Modal(request):
  898. year = int(request.matchdict.get('year', None))
  899. modtype = request.matchdict.get('modtype', None)
  900. uid = int(request.matchdict.get('id', -1))
  901. session = request.session
  902. if modtype=='Password':
  903. form = UserPasswordForm(request.POST, request.user, meta={'csrf_context': request.session})
  904. if request.method == 'POST' and form.validate():
  905. response = render_to_response('jm2l:templates/modals_js.mako',
  906. {'modtype':modtype},
  907. request=request)
  908. request.user.password = form.password.data
  909. DBSession.merge(request.user)
  910. response.content_type = 'text/javascript'
  911. return response
  912. if modtype=='UserPicture':
  913. form = None
  914. if request.method == 'POST':
  915. response = render_to_response('jm2l:templates/modals_js.mako',
  916. {'modtype':modtype},
  917. request=request)
  918. response.content_type = 'text/javascript'
  919. return response
  920. if modtype=='Place':
  921. if uid>0:
  922. place = Place.by_id(uid)
  923. if not place:
  924. raise HTTPNotFound()
  925. form = PlaceUpdateForm(request.POST, place, meta={'csrf_context': request.session})
  926. else:
  927. place = Place()
  928. form = PlaceCreateForm(request.POST, meta={'csrf_context': request.session})
  929. if request.method == 'POST' and form.validate():
  930. form.populate_obj(place)
  931. place.created_by=request.user.uid
  932. if uid>0:
  933. DBSession.merge(place)
  934. else:
  935. DBSession.add(place)
  936. response = render_to_response('jm2l:templates/modals_js.mako',
  937. {'modtype':modtype},
  938. request=request)
  939. response.content_type = 'text/javascript'
  940. return response
  941. if modtype in ['AskC', 'AskH', 'AskM', 'PropC', 'PropH', 'PropM']:
  942. if uid>0:
  943. Exch = Exchange.by_id(uid)
  944. if not Exch:
  945. raise HTTPNotFound()
  946. if modtype in ['AskC','PropC']:
  947. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  948. start_place = Exch.Itin.start_place,
  949. arrival_place = Exch.Itin.arrival_place,
  950. Hour_start = Exch.start_time.strftime("%H:%M"),
  951. Day_start = Exch.start_time.strftime("%w"),
  952. exch_id = uid, meta={'csrf_context': request.session}
  953. )
  954. elif modtype in ['AskM','PropM']:
  955. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  956. description = Exch.description,
  957. exch_categ = Exch.exch_categ,
  958. Hour_start = Exch.start_time.strftime("%H:%M"),
  959. Day_start = Exch.start_time.strftime("%w"),
  960. Hour_end = Exch.end_time.strftime("%H:%M"),
  961. Day_end = Exch.end_time.strftime("%w"),
  962. exch_id = uid, meta={'csrf_context': request.session}
  963. )
  964. elif modtype in ['AskH','PropH']:
  965. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  966. description = Exch.description,
  967. exch_categ = Exch.exch_categ,
  968. Day_start = Exch.start_time.strftime("%w"),
  969. exch_id = uid, meta={'csrf_context': request.session}
  970. )
  971. # Itinerary, first get itinerary
  972. if 0:
  973. form.itin.form.start_place.data = Exch.Itin.start_place
  974. form.itin.form.arrival_place.data = Exch.Itin.arrival_place
  975. form.dateform.form.Hour.data = Exch.start_time.strftime("%H:%M")
  976. form.dateform.form.Day.data = Exch.start_time.strftime("%w")
  977. form.exch_id.data = uid
  978. else:
  979. Exch = Exchange()
  980. form = globals()["%sForm" % modtype](request.POST, meta={'csrf_context': request.session})
  981. if modtype in ['AskC', 'PropC']:
  982. # Put some place on form
  983. Places = DBSession.query(Place.place_id, Place.display_name)\
  984. .order_by('name').all()
  985. form.start_place.choices = Places
  986. form.arrival_place.choices = Places
  987. if modtype in ['PropH']:
  988. form.exch_categ.choices = DBSession.query( Exchange_Cat.cat_id, Exchange_Cat.exch_subtype)\
  989. .filter( Exchange_Cat.exch_type=='H' ).all()
  990. form.place_id.choices = DBSession.query( Place.place_id, Place.display_name)\
  991. .filter( Place.created_by==request.user.uid ).all()
  992. if modtype in ['AskM', 'PropM']:
  993. form.exch_categ.choices = DBSession.query( Exchange_Cat.cat_id, Exchange_Cat.exch_subtype)\
  994. .filter( Exchange_Cat.exch_type=='M' ).all()
  995. if request.method == 'POST' and form.validate():
  996. # Form has been validated, it's time to create our Exchange
  997. Exch.for_year = year
  998. Exch.exch_state = {'Ask':'Ask', 'Prop':'Proposal'}[modtype[:-1]]
  999. Exch.exch_type = modtype[-1:]
  1000. if modtype in ['AskC', 'PropC']:
  1001. # Itinerary, first Let's see if itinerary exist
  1002. Itinerary = DBSession.query(Itineraire)\
  1003. .filter(Itineraire.start_place==form.start_place.data) \
  1004. .filter(Itineraire.arrival_place==form.arrival_place.data) \
  1005. .filter(Itineraire.tr_voiture==True) \
  1006. .first()
  1007. if not Itinerary: # Not exist yet !
  1008. Itinerary = Itineraire(start_place=form.start_place.data, \
  1009. arrival_place=form.arrival_place.data, \
  1010. tr_voiture=True, \
  1011. created_by=1
  1012. )
  1013. DBSession.add(Itinerary)
  1014. DBSession.flush()
  1015. Exch.itin_id = Itinerary.itin_id
  1016. # Start Time
  1017. StartEvent = DBSession.query(JM2L_Year.start_time).filter(JM2L_Year.year_uid==year).first()
  1018. Week = StartEvent[0].strftime("%W")
  1019. # populate
  1020. form.populate_obj(Exch)
  1021. if modtype in ['AskC', 'PropC']:
  1022. Exch.itin_id = Itinerary.itin_id
  1023. if form._fields.has_key("Hour_start"):
  1024. TargetTime = datetime.datetime.strptime('%d %d %d %s' % (year, int(Week), \
  1025. int(form.Day_start.data), form.Hour_start.data), "%Y %W %w %H:%M")
  1026. Exch.start_time = TargetTime
  1027. elif form._fields.has_key("Day_start"):
  1028. TargetTime = datetime.datetime.strptime('%d %d %d' % (year, int(Week), \
  1029. int(form.Day_start.data)), "%Y %W %w")
  1030. Exch.start_time = TargetTime
  1031. if form._fields.has_key("Hour_end"):
  1032. TargetTime = datetime.datetime.strptime('%d %d %d %s' % (year, int(Week), \
  1033. int(form.Day_end.data), form.Hour_end.data), "%Y %W %w %H:%M")
  1034. Exch.end_time = TargetTime
  1035. elif form._fields.has_key("Day_end"):
  1036. TargetTime = datetime.datetime.strptime('%d %d %d' % (year, int(Week), \
  1037. int(form.Day_end.data)), "%Y %W %w")
  1038. Exch.end_time = TargetTime
  1039. Exch.last_change = datetime.datetime.utcnow()
  1040. if Exch.exch_state=='Ask':
  1041. Exch.asker_id = request.user.uid
  1042. elif Exch.exch_state=='Proposal':
  1043. Exch.provider_id = request.user.uid
  1044. #print vars(form.itin.form)
  1045. if uid>0:
  1046. DBSession.merge(Exch)
  1047. else:
  1048. DBSession.add(Exch)
  1049. response = render_to_response('jm2l:templates/modals_js.mako',
  1050. {'modtype':modtype},
  1051. request=request)
  1052. response.content_type = 'text/javascript'
  1053. return response
  1054. # Fallback to HTML Display with errors
  1055. return {'modtype':modtype, 'form':form, 'update':uid>0,
  1056. 'logged_in':request.authenticated_userid }
  1057. if modtype in ['ShowC', 'ShowH', 'ShowM']:
  1058. if uid>0:
  1059. Exch = Exchange.by_id(uid)
  1060. if not Exch:
  1061. raise HTTPNotFound()
  1062. else:
  1063. raise HTTPNotFound()
  1064. # Show Details around the Current Exchange
  1065. return {'modtype':modtype, 'Exch':Exch, 'logged_in':request.authenticated_userid }
  1066. MainTab = {'modtype':modtype, 'form':form, 'update':uid>0, 'uid':uid,
  1067. 'DisplayYear':year, 'session':session,
  1068. 'logged_in':request.authenticated_userid }
  1069. return MainTab
  1070. @view_config(route_name='participer', renderer="jm2l:templates/Participer.mako")
  1071. def participer(request):
  1072. session = request.session
  1073. session['year'] = 2015
  1074. TmpUsr = User()
  1075. form = UserRegisterForm(request.POST, TmpUsr, meta={'csrf_context': request.session})
  1076. MyLink=None
  1077. if request.method == 'POST' and form.validate():
  1078. # Prepare mailer
  1079. form.populate_obj(TmpUsr)
  1080. TmpUsr.nom = TmpUsr.nom.capitalize()
  1081. TmpUsr.prenom = TmpUsr.prenom.capitalize()
  1082. TmpUsr.slug = slugify(remove_accents('%s %s' % (form.prenom.data, form.nom.data)).lower().strip())
  1083. TmpUsr.password = TmpUsr.my_hash
  1084. if len(TmpUsr.slug):
  1085. CheckExist = DBSession.query(User)\
  1086. .filter(User.slug==TmpUsr.slug)\
  1087. .first()
  1088. else:
  1089. CheckExist=None
  1090. if CheckExist:
  1091. MyLink = CheckExist.my_hash
  1092. NewUser = CheckExist
  1093. else:
  1094. DBSession.add(TmpUsr)
  1095. DBSession.flush()
  1096. MyLink = TmpUsr.my_hash
  1097. NewUser = TmpUsr
  1098. # Send the Welcome Mail
  1099. mailer = request.registry['mailer']
  1100. # Prepare Plain Text Message :
  1101. Mail_template = Template(filename='jm2l/templates/mail_plain.mako')
  1102. mail_plain = Mail_template.render(request=request, User=NewUser, action="Welcome")
  1103. # Prepare HTML Message :
  1104. Mail_template = Template(filename='jm2l/templates/mail_html.mako')
  1105. mail_html = Mail_template.render(request=request, User=NewUser, action="Welcome")
  1106. # Prepare Message
  1107. message = Message(subject="[JM2L] Mon inscription au site web JM2L",
  1108. sender="contact@jm2l.linux-azur.org",
  1109. recipients=[NewUser.mail or TmpUsr.mail],
  1110. body=mail_plain, html=mail_html)
  1111. message.add_bcc("spam@style-python.fr")
  1112. mailer.send(message)
  1113. request.session.flash(('info',u"Un mail vous a été envoyé afin de continuer votre quête !"))
  1114. MainTab = {'programme':'','presse':'', 'plan':'',
  1115. 'participer':'active', 'form':form, "link": MyLink,
  1116. 'logged_in':request.authenticated_userid }
  1117. return MainTab
  1118. @view_config(route_name='year')
  1119. def change_year(request):
  1120. year = int(request.matchdict.get('year', -1))
  1121. session = request.session
  1122. if year>-1:
  1123. session['year'] = year
  1124. return HTTPFound(location='/%s/' % year)
  1125. return HTTPFound(location=request.route_url('home', year=''))
  1126. @view_config(route_name='pict_user', renderer="jm2l:templates/Profil/pict_user.mako")
  1127. def pict_user(request):
  1128. return {"uprofil":request.user}
  1129. @view_config(route_name='pict_salle', renderer="jm2l:templates/Salles/pict_salle.mako")
  1130. def pict_salle(request):
  1131. salle_id = int(request.matchdict.get('salle_id', -1))
  1132. return {"Salles":Salles, "IdSalle":salle_id}
  1133. @view_config(route_name='event', renderer="jm2l:templates/view_event.mako")
  1134. def show_event(request):
  1135. year = int(request.matchdict.get('year', -1))
  1136. event_id = request.matchdict.get('event_id')
  1137. if event_id.isdigit():
  1138. TheEvent = Event.by_id(event_id)
  1139. if TheEvent is None:
  1140. raise HTTPNotFound()
  1141. else:
  1142. TheEvent = Event.by_slug(event_id, year)
  1143. if TheEvent is None:
  1144. raise HTTPNotFound()
  1145. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1146. 'event':TheEvent, 'logged_in':request.authenticated_userid, "Salles":Salles }
  1147. return MainTab
  1148. @view_config(route_name='link_event_user')
  1149. def link_event_user(request):
  1150. """ Get user and add it to current event """
  1151. if request.user is None:
  1152. # Don't answer to users that aren't logged
  1153. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1154. year = int(request.matchdict.get('year', -1))
  1155. form = AddIntervenant(request.POST, meta={'csrf_context': request.session})
  1156. intervention = request.matchdict.get('intervention', None)
  1157. TargetEvent = Event.by_id(form.event_uid.data)
  1158. Exist = User.by_id(form.intervenant.data)
  1159. if not Exist:
  1160. request.session.flash(('error',u"Une erreur s'est produite lors de l'ajout de votre intervenant !"))
  1161. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1162. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1163. else:
  1164. TargetUser = Exist
  1165. uev = User_Event(year_uid=year, role=u"Animateur d'un évènement JM2L", user_uid=TargetUser.uid)
  1166. TargetEvent.interventions.append( uev )
  1167. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1168. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1169. @view_config(route_name='link_event_tiers')
  1170. def link_event_tiers(request):
  1171. """ Create user if not exist, add it to current event """
  1172. if request.user is None:
  1173. # Don't answer to users that aren't logged
  1174. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1175. year = int(request.matchdict.get('year', -1))
  1176. form = AddTiers(request.POST, meta={'csrf_context': request.session})
  1177. intervention = request.matchdict.get('intervention', None)
  1178. TargetEvent = Event.by_id(form.event_uid.data)
  1179. Exist = Tiers.by_id(form.tiers.data)
  1180. if not Exist:
  1181. request.session.flash(('error',u"Une erreur s'est produite lors de l'ajout de votre entité !"))
  1182. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1183. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1184. else:
  1185. TargetTiers = Exist
  1186. Matching = DBSession.query(Role_Tiers)\
  1187. .filter(Role_Tiers.year_uid==year)\
  1188. .filter(Role_Tiers.tiers_role=="Exposant")\
  1189. .filter(Role_Tiers.tiers_uid==TargetTiers.uid)\
  1190. .filter(Role_Tiers.event_uid==TargetEvent.uid)\
  1191. .all()
  1192. if len(Matching)==0:
  1193. tev = Role_Tiers(year_uid=year, tiers_role="Exposant", tiers_uid=TargetTiers.uid, event_uid=TargetEvent.uid)
  1194. DBSession.add(tev)
  1195. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1196. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid), _anchor="Tiers"))
  1197. @view_config(route_name='delete_link_u')
  1198. def delete_link_event_user(request):
  1199. """ Create user if not exist, add it to current event """
  1200. if request.user is None:
  1201. # Don't answer to users that aren't logged
  1202. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1203. year = int(request.matchdict.get('year', -1))
  1204. intervention = request.matchdict.get('intervention', None)
  1205. TargetEvent = Event.by_id( request.params.get('eid') )
  1206. Exist = User.by_id( request.params.get('uid') )
  1207. if not Exist:
  1208. request.session.flash(('error',u"Une erreur s'est produite lors de votre suppression !"))
  1209. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1210. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1211. else:
  1212. TargetUser = Exist
  1213. Matching = DBSession.query(User_Event)\
  1214. .filter(User_Event.year_uid==year)\
  1215. .filter(User_Event.user_uid==TargetUser.uid)\
  1216. .filter(User_Event.event_uid==TargetEvent.uid)\
  1217. .all()
  1218. if len(Matching)==0:
  1219. request.session.flash(('error',u"Une erreur s'est produite lors de la suppression !"))
  1220. else:
  1221. for item in Matching:
  1222. DBSession.delete(item)
  1223. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1224. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid), _anchor="Tiers"))
  1225. @view_config(route_name='delete_link_t')
  1226. def delete_link_event_tiers(request):
  1227. """ Create user if not exist, add it to current event """
  1228. if request.user is None:
  1229. # Don't answer to users that aren't logged
  1230. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1231. year = int(request.matchdict.get('year', -1))
  1232. intervention = request.matchdict.get('intervention', None)
  1233. TargetEvent = Event.by_id( request.params.get('uid') )
  1234. Exist = Tiers.by_id( request.params.get('tid') )
  1235. if not Exist:
  1236. request.session.flash(('error',u"Une erreur s'est produite lors de l'ajout de votre entité !"))
  1237. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1238. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1239. else:
  1240. TargetTiers = Exist
  1241. Matching = DBSession.query(Role_Tiers)\
  1242. .filter(Role_Tiers.year_uid==year)\
  1243. .filter(Role_Tiers.tiers_role=="Exposant")\
  1244. .filter(Role_Tiers.tiers_uid==TargetTiers.uid)\
  1245. .filter(Role_Tiers.event_uid==TargetEvent.uid)\
  1246. .all()
  1247. if len(Matching)==0:
  1248. request.session.flash(('error',u"Une erreur s'est produite lors de la suppression de votre entité !"))
  1249. else:
  1250. for item in Matching:
  1251. DBSession.delete(item)
  1252. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1253. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid), _anchor="Tiers"))
  1254. @view_config(route_name='delete_event')
  1255. def delete_event(request):
  1256. if request.user is None:
  1257. # Don't answer to users that aren't logged
  1258. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1259. year = int(request.matchdict.get('year', -1))
  1260. event_id = request.matchdict.get('event_id')
  1261. intervention = request.matchdict.get('intervention', None)
  1262. # Check intervention
  1263. if not intervention in ['Stand', 'Table_ronde', 'Atelier', 'Conference', 'Concert']:
  1264. raise HTTPNotFound(u"Ce type d'évènement n'est pas reconnu")
  1265. # We should remove all links before to remove the event
  1266. if event_id.isdigit():
  1267. TheEvent = Event.by_id(event_id)
  1268. if TheEvent is None:
  1269. raise HTTPNotFound(u"Cette réference n'existe pas")
  1270. else:
  1271. TheEvent = Event.by_slug(event_id, year)
  1272. if TheEvent is None:
  1273. raise HTTPNotFound(u"Cette réference n'existe pas")
  1274. # Remove Roles
  1275. Roles_Link = DBSession.query(Role_Tiers).filter(Role_Tiers.event_uid==TheEvent.uid).all()
  1276. for tmp in Roles_Link:
  1277. DBSession.delete(tmp)
  1278. # Remove Intervenant
  1279. User_Link = DBSession.query(User_Event).filter(User_Event.event_uid==TheEvent.uid).all()
  1280. for tmp in User_Link:
  1281. DBSession.delete(tmp)
  1282. # Remove attachment if any
  1283. SRCPath = path.join('jm2l/upload', *(IMAGEPATH + ['event'] + [ str(year) ] + [ TheEvent.slug ]) )
  1284. shutil.rmtree(SRCPath, ignore_errors=True)
  1285. # Remove Event
  1286. DBSession.delete(TheEvent)
  1287. return HTTPFound(location=request.route_url('jm2l', _anchor="Interventions"))
  1288. @view_config(route_name='edit_event', renderer="jm2l:templates/edit_event.mako")
  1289. def edit_event(request):
  1290. if request.user is None:
  1291. # Don't answer to users that aren't logged
  1292. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1293. year = int(request.matchdict.get('year', -1))
  1294. event_id = request.matchdict.get('event_id')
  1295. intervention = request.matchdict.get('intervention', None)
  1296. IntervLabel = intervention.replace('_',' ').lower()
  1297. if intervention=='Conference':
  1298. IntervLabel = u'conférence'
  1299. elif intervention=='Table_ronde':
  1300. IntervLabel = u'Table ronde'
  1301. # Check intervention
  1302. if not intervention in ['Stand', 'Table_ronde', 'Atelier', 'Conference', 'Concert']:
  1303. raise HTTPNotFound(u"Ce type d'évènement n'est pas reconnu")
  1304. TheYear = DBSession.query(JM2L_Year)\
  1305. .filter(JM2L_Year.year_uid==year)\
  1306. .first()
  1307. # Check year avaibility
  1308. if not TheYear:
  1309. raise HTTPNotFound(u"Cette année n'est pas pris en charge")
  1310. # Generate Timeslots for current year
  1311. TimeSlots = list(enumerate( [ x.strftime('%a %d %b %H:%M') for x in
  1312. TheYear.AvailableTimeSlots ] ))
  1313. if event_id:
  1314. # We try to update an existing record
  1315. if event_id.isdigit():
  1316. TheEvent = Event.by_id(event_id)
  1317. if TheEvent is None:
  1318. raise HTTPNotFound(u"Cette réference n'existe pas")
  1319. else:
  1320. TheEvent = Event.by_slug(event_id, year)
  1321. if TheEvent is None:
  1322. raise HTTPNotFound(u"Cette réference n'existe pas")
  1323. if request.user is None or not (request.user.Staff or request.user in TheEvent.intervenants):
  1324. raise HTTPForbidden(u"Vous n'êtes pas identifié comme étant un participant à cette intervention.")
  1325. # Compute some field value from selected event
  1326. if TheEvent.start_time in TheYear.AvailableTimeSlots:
  1327. start_sel = TheYear.AvailableTimeSlots.index(TheEvent.start_time)
  1328. else:
  1329. start_sel = len(TimeSlots)
  1330. TimeSlots.append( (len(TimeSlots), TheEvent.start_time.strftime('%a %d %b %H:%M')))
  1331. duration = (TheEvent.end_time - TheEvent.start_time).total_seconds()/60
  1332. end = TheEvent.start_time + datetime.timedelta(minutes=duration)
  1333. # prepare the form with update
  1334. form = ConfUpdateForm(request.POST, TheEvent, start_sel=start_sel, duration=duration, end_time=end,
  1335. meta={'csrf_context': request.session} )
  1336. # Customize labels
  1337. form.name.label.text += IntervLabel
  1338. form.description.label.text += IntervLabel
  1339. # Each event can get severals members
  1340. formAdd = AddIntervenant(event_uid=TheEvent.uid)
  1341. # Build list of intervenant
  1342. # Get users from db
  1343. Users = DBSession.query(User)\
  1344. .filter(User.Staff==1)\
  1345. .order_by('nom').all()
  1346. # Put some users on form
  1347. formAdd.intervenant.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  1348. for u in Users]
  1349. # Each event can get severals entities
  1350. formAddT = AddTiers(event_uid=TheEvent.uid)
  1351. # Build list of entities
  1352. # Get entities from db
  1353. TmpTiers = DBSession.query(Tiers)\
  1354. .order_by('name').limit(10)
  1355. # Put some entities on form
  1356. formAddT.tiers.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  1357. for u in Users]
  1358. else:
  1359. TheEvent = Event()
  1360. # prepare the form for creation
  1361. form = ConfCreateForm(request.POST,
  1362. event_type=intervention,
  1363. for_year=str(year), meta={'csrf_context': request.session}
  1364. )
  1365. # Customize labels
  1366. form.name.label.text += IntervLabel
  1367. form.description.label.text += IntervLabel
  1368. duration=60
  1369. # No intervenant
  1370. formAdd = None
  1371. formAddT = None
  1372. SalleDispo = DBSession.query(Salles)\
  1373. .filter(Salles.year_uid==year)\
  1374. .order_by('name')
  1375. if intervention=="Conference":
  1376. form.duration.choices =[
  1377. (15,u'Lighting talk ( 5 min)'),
  1378. (30,u'Conférence (20 min)'),
  1379. (60,u'Conférence (50 min)'),
  1380. (90,u'Conférence (75 min)'),
  1381. ]
  1382. if not duration in [15, 30, 60, 90]:
  1383. form.duration.choices.append( (duration,u'Conférence (%d min)' % duration) )
  1384. if not form._fields.has_key("uid"):
  1385. form.duration.data=60
  1386. SalleDispo = SalleDispo.filter(Salles.place_type.in_(['Conference', 'MAO', 'Atelier']))
  1387. elif intervention=="Stand":
  1388. form.duration.choices =[
  1389. (8*60, u'Toute la journée'),
  1390. (4*60, u'une demi-journée')
  1391. ]
  1392. SalleDispo = SalleDispo.filter(Salles.place_type=='Stand')
  1393. elif intervention=="Atelier":
  1394. form.duration.choices = map( lambda d:(d, u'Atelier (%dh%.2d)' % (d/60, d%60) ), \
  1395. [60, 90, 120, 150, 180, 210, 240] )
  1396. if not duration in map(lambda (d,y): d, form.duration.choices):
  1397. form.duration.choices.append( (duration,u'Atelier (%dh%.2d)' % (duration/60, duration%60) ) )
  1398. SalleDispo = SalleDispo.filter(Salles.place_type.in_(['Atelier', 'MAO']))
  1399. elif intervention=="Table_ronde":
  1400. form.duration.choices = map( lambda d:(d, u'Table ronde (%dh%.2d)' % (d/60, d%60) ), \
  1401. [60, 90, 120, 150] )
  1402. if not duration in map(lambda (d,y): d, form.duration.choices):
  1403. form.duration.choices.append( (duration,u'Table ronde (%dh%.2d)' % (duration/60, duration%60) ) )
  1404. SalleDispo = SalleDispo.filter(Salles.place_type=='Table ronde')
  1405. elif intervention=="Concert":
  1406. form.duration.choices = map( lambda d:(d, u'Concert (%dh%.2d)' % (d/60, d%60) ), \
  1407. [60, 90, 120, 150, 180, 210, 240] )
  1408. if not duration in map(lambda (d,y): d, form.duration.choices):
  1409. form.duration.choices.append( (duration,u'Concert (%dh%.2d)' % (duration/60, duration%60) ) )
  1410. SalleDispo = SalleDispo.filter(Salles.place_type.in_(['Stand', 'MAO']))
  1411. else:
  1412. raise HTTPForbidden(u"Pas encore disponible.")
  1413. form.salle_uid.choices = [(s.salle_id, s.name) for s in SalleDispo]
  1414. form.start_sel.choices = TimeSlots
  1415. if request.method == 'POST' and form.validate():
  1416. form.populate_obj(TheEvent)
  1417. TheEvent.start_time = TheYear.AvailableTimeSlots[form.start_sel.data]
  1418. TheEvent.end_time = TheEvent.start_time + datetime.timedelta(minutes=form.duration.data)
  1419. # Ok, time to put in database
  1420. if not form._fields.has_key("uid"):
  1421. TheEvent.slug = unicode(slugify(TheEvent.name))
  1422. if intervention==u"Table_ronde":
  1423. TheEvent.event_type = "Table ronde"
  1424. DBSession.add(TheEvent)
  1425. # Append creator by default
  1426. if request.user.uid!=1:
  1427. uev = User_Event(year_uid=TheYear.year_uid, role=u"Animateur")
  1428. uev.user_uid = request.user.uid
  1429. TheEvent.interventions.append( uev )
  1430. DBSession.flush()
  1431. request.session.flash(('sucess',u'Votre intervention a été créee ! Vous pouvez la compléter à tout moment.'))
  1432. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1433. year=str(year), intervention=intervention, event_id=str(TheEvent.slug)))
  1434. else:
  1435. if slugify(TheEvent.name)!=TheEvent.slug:
  1436. # We should move some file as slug have been changed
  1437. # First we ensure there is no related event that already exist with that slug
  1438. CheckEvent = Event.by_slug( unicode(slugify(TheEvent.name)), year)
  1439. if CheckEvent:
  1440. request.session.flash(('warning',u'Choisissez un autre titre pour votre évènement, il est en conflit avec un autre.'))
  1441. return {'event':TheEvent, 'form':form, 'formAdd':formAdd, 'formAddT':formAddT, 'Salles':Salles }
  1442. else:
  1443. SRCPath = path.join('jm2l/upload', *(IMAGEPATH + ['event'] + [ str(year) ] + [ TheEvent.slug ]) )
  1444. TheEvent.slug=unicode(slugify(TheEvent.name))
  1445. DSTPath = path.join('jm2l/upload', *(IMAGEPATH + ['event'] + [ str(year) ] + [ TheEvent.slug ]) )
  1446. if not path.isdir(path.dirname(DSTPath)):
  1447. makedirs(path.dirname(DSTPath))
  1448. # Then we should move event attachments to the new slug (if any)
  1449. if path.exists(SRCPath):
  1450. shutil.move(SRCPath, DSTPath)
  1451. DBSession.merge(TheEvent)
  1452. request.session.flash(('sucess',u'Votre intervention a été mis à jour !'))
  1453. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1454. year=str(year), intervention=intervention, event_id=str(TheEvent.slug)))
  1455. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1456. 'event':TheEvent, 'form':form, 'formAdd':formAdd, 'formAddT':formAddT,
  1457. 'Salles':Salles }
  1458. return MainTab
  1459. @view_config(route_name='entities', renderer="jm2l:templates/list_tiers.mako")
  1460. def list_tiers(request):
  1461. Entities = dict()
  1462. EntityType = DBSession.query(TiersOpt.entity_type)\
  1463. .group_by(TiersOpt.entity_type).all()
  1464. for EType in EntityType:
  1465. Entities[EType.entity_type] = DBSession.query(Tiers).join(TiersOpt)\
  1466. .filter(TiersOpt.entity_type==EType.entity_type)\
  1467. .order_by(TiersOpt.entity_subtype, Tiers.name)
  1468. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1469. 'entities':Entities, 'logged_in':request.authenticated_userid }
  1470. return MainTab
  1471. @view_config(route_name='show_entity', renderer="jm2l:templates/view_tiers.mako")
  1472. def show_tiers(request):
  1473. tiers_type = request.matchdict.get('tiers_type')
  1474. entity_id = request.matchdict.get('entity_id')
  1475. if entity_id.isdigit():
  1476. TheTiers = Tiers.by_id(entity_id)
  1477. if TheTiers is None:
  1478. raise HTTPNotFound()
  1479. else:
  1480. TheTiers = Tiers.by_slug(entity_id)
  1481. if TheTiers is None:
  1482. raise HTTPNotFound()
  1483. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1484. 'entity':TheTiers, 'logged_in':request.authenticated_userid }
  1485. return MainTab
  1486. @view_config(route_name='delete_entity')
  1487. def delete_tiers(request):
  1488. if request.user is None:
  1489. # Don't answer to users that aren't logged
  1490. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1491. entity_id = request.matchdict.get('entity_id', None)
  1492. if entity_id:
  1493. if entity_id.isdigit():
  1494. TheTiers = Tiers.by_id(int(entity_id))
  1495. if TheTiers is None:
  1496. raise HTTPNotFound()
  1497. else:
  1498. TheTiers = Tiers.by_slug(entity_id)
  1499. if TheTiers is None:
  1500. raise HTTPNotFound()
  1501. if len(TheTiers.membership)!=0:
  1502. request.session.flash(('error', u"Vous devez supprimer tous les membres liés avant la suppression d'une entité."))
  1503. return HTTPFound(location=request.route_url('show_entity', entity_id=TheTiers.slug, tiers_type=TheTiers.get_entity_type.slug_entity_type))
  1504. if len(TheTiers.membership)!=0:
  1505. request.session.flash(('error', u"Vous devez supprimer tous les roles liés avant la suppression d'une entité."))
  1506. return HTTPFound(location=request.route_url('show_entity', entity_id=TheTiers.slug, tiers_type=TheTiers.get_entity_type.slug_entity_type))
  1507. DBSession.delete(TheTiers)
  1508. request.session.flash(('info', u"L'entité a bien été supprimée"))
  1509. return HTTPFound(location=request.route_url('entities'))
  1510. else:
  1511. raise HTTPNotFound()
  1512. @view_config(route_name='add_entity', renderer="jm2l:templates/edit_tiers.mako")
  1513. @view_config(route_name='edit_entity', renderer="jm2l:templates/edit_tiers.mako")
  1514. def edit_tiers(request):
  1515. entity_id = request.matchdict.get('entity_id', None)
  1516. TargetList = list()
  1517. if request.user is None:
  1518. # Don't answer to users that aren't logged
  1519. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1520. entity_types = DBSession.query(TiersOpt.entity_type).group_by(TiersOpt.entity_type).all()
  1521. for entity_type in entity_types:
  1522. entity_subtypes = DBSession.query(TiersOpt)\
  1523. .filter(TiersOpt.entity_type==entity_type.entity_type)\
  1524. .group_by(TiersOpt.entity_subtype).all()
  1525. ListType = [(i.uid, i.entity_subtype) for i in entity_subtypes]
  1526. TargetList.append( (entity_type.entity_type, ListType) )
  1527. if entity_id:
  1528. if entity_id.isdigit():
  1529. TheTiers = Tiers.by_id(entity_id)
  1530. if TheTiers is None:
  1531. raise HTTPNotFound()
  1532. else:
  1533. TheTiers = Tiers.by_slug(entity_id)
  1534. if TheTiers is None:
  1535. raise HTTPNotFound()
  1536. form = UpdateTiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  1537. UserOptions = DBSession.query(TiersOpt)\
  1538. .filter(TiersOpt.entity_type==TheTiers.tiers_type)\
  1539. .all()
  1540. form.tiers_type.choices = TargetList
  1541. else:
  1542. TheTiers = Tiers()
  1543. # prepare the form for creation
  1544. form = TiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  1545. form.tiers_type.choices = TargetList
  1546. UserOptions = list()
  1547. #test_form = TiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  1548. if request.method == 'POST' and form.validate():
  1549. ToDelete = list()
  1550. ToDeleteR = list()
  1551. # First, we remove entries no more present
  1552. for obj in form.membership.object_data:
  1553. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  1554. form.membership.entries )
  1555. if not MatchEntry:
  1556. ToDelete.append(obj)
  1557. # For roles too
  1558. for obj in form.roles.object_data:
  1559. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  1560. form.roles.entries )
  1561. if not MatchEntry:
  1562. ToDeleteR.append(obj)
  1563. # We should remove it as it's not in original data
  1564. for obj in ToDelete:
  1565. TheTiers.membership.remove(obj)
  1566. DBSession.delete(obj)
  1567. # For roles too
  1568. for obj in ToDeleteR:
  1569. TheTiers.roles.remove(obj)
  1570. DBSession.delete(obj)
  1571. # Then, it's time to consider new entries
  1572. for entry in form.membership.entries:
  1573. if entry.object_data is None:
  1574. TmpUser = User_Tiers()
  1575. entry.object_data = TmpUser
  1576. TheTiers.membership.append(TmpUser)
  1577. form.membership.object_data = TheTiers.membership
  1578. # For roles too
  1579. for entry in form.roles.entries:
  1580. if entry.object_data is None:
  1581. TmpRole = Role_Tiers()
  1582. entry.object_data = TmpRole
  1583. TheTiers.roles.append(TmpRole)
  1584. form.roles.object_data = TheTiers.roles
  1585. form.populate_obj(TheTiers)
  1586. # Handle Remove of accents
  1587. OriginalSlug = TheTiers.slug
  1588. if not form._fields.has_key('uid'):
  1589. TheTiers.slug = slugify(form.name.data)
  1590. TheTiers.creator_id = request.user.uid
  1591. DBSession.add(TheTiers)
  1592. DBSession.flush()
  1593. return HTTPFound(location=request.route_url('edit_entity', sep='/',
  1594. entity_id=str(TheTiers.slug), tiers_type=TheTiers.get_entity_type.entity_type))
  1595. else:
  1596. if OriginalSlug!=slugify(form.name.data):
  1597. # We should move some file as slug have been changed
  1598. # First we ensure there is no related event that already exist with that slug
  1599. CheckTiers = Tiers.by_slug( slugify(form.name.data) )
  1600. if CheckTiers:
  1601. request.session.flash(('warning',u'Attention, Choisissez un autre titre pour votre entitée, elle est en conflit avec une autre.'))
  1602. DBSession.rollback()
  1603. return HTTPFound(location=request.route_url('edit_entity', sep='/',
  1604. entity_id=str(OriginalSlug), tiers_type=TheTiers.get_entity_type.entity_type))
  1605. else:
  1606. TheTiers.slug = slugify(form.name.data)
  1607. SRCPath = path.join('jm2l/upload', *(IMAGEPATH + ['tiers'] + [ OriginalSlug ]) )
  1608. DSTPath = path.join('jm2l/upload', *(IMAGEPATH + ['tiers'] + [ TheTiers.slug ]) )
  1609. if not path.isdir(path.dirname(DSTPath)):
  1610. makedirs(path.dirname(DSTPath))
  1611. # Then we should move event attachments to the new slug (if any)
  1612. if path.exists(SRCPath):
  1613. shutil.move(SRCPath, DSTPath)
  1614. DBSession.merge(TheTiers)
  1615. return HTTPFound(location=request.route_url('show_entity', entity_id=TheTiers.slug,
  1616. tiers_type=TheTiers.get_entity_type.slug_entity_type))
  1617. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1618. 'form':form, 'DBUser':User, 'UserOptions':UserOptions,
  1619. 'logged_in':request.authenticated_userid }
  1620. return MainTab
  1621. @view_config(route_name='edit_entity_cat', renderer="jm2l:templates/edit_tiers_categ.mako")
  1622. def edit_tiers_category(request):
  1623. if request.user is None:
  1624. # Don't answer to users that aren't logged
  1625. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1626. DicResult = dict()
  1627. ListChanges = list()
  1628. if request.method == 'POST':
  1629. # Reformat data
  1630. RegExist = re.compile('collection\[(?P<slug>[\w-]+)\]\[(?P<num>\d+)\]\[(?P<id>\d+)\]')
  1631. RegTitle = re.compile('collection\[(?P<slug>[\w-]+)\]\[title]')
  1632. RegNew = re.compile('collection\[(?P<slug>[\w-]+)\]\[(?P<num>\d+)\]\[id\]')
  1633. for key, value in request.POST.iteritems():
  1634. regN= RegNew.match(key)
  1635. regT= RegTitle.match(key)
  1636. reg = RegExist.match(key)
  1637. if reg:
  1638. if not DicResult.has_key(reg.group('slug')):
  1639. DicResult[reg.group('slug')] = dict()
  1640. if DicResult[reg.group('slug')].has_key('items'):
  1641. DicResult[reg.group('slug')]['items'].append( ( int(reg.group('id')), value ) )
  1642. else:
  1643. DicResult[reg.group('slug')]['items'] = [ ( int(reg.group('id')), value ) ]
  1644. elif regN:
  1645. if not DicResult.has_key(regN.group('slug')):
  1646. DicResult[regN.group('slug')] = dict()
  1647. if DicResult[regN.group('slug')].has_key('items'):
  1648. DicResult[regN.group('slug')]['items'].append( ( 'id', value ) )
  1649. else:
  1650. DicResult[regN.group('slug')]['items'] = [ ( 'id', value ) ]
  1651. ListChanges.append(('add', 0, DicResult[regN.group('slug')]['title'], value))
  1652. elif regT:
  1653. if not DicResult.has_key(regT.group('slug')):
  1654. DicResult[regT.group('slug')] = dict()
  1655. DicResult[regT.group('slug')]['title'] = value
  1656. else:
  1657. raise
  1658. for opt in DBSession.query(TiersOpt).all():
  1659. if DicResult.has_key(opt.slug_entity_type):
  1660. found = filter( lambda (x,y): opt.uid==x,
  1661. DicResult[opt.slug_entity_type].get('items', []))
  1662. if not found:
  1663. ListChanges.append(('remove', opt.uid, opt.entity_type, opt.entity_subtype))
  1664. else:
  1665. for tst in found:
  1666. # Check changes on Cat Name
  1667. if DicResult[opt.slug_entity_type]['title']!=opt.entity_type or \
  1668. tst[1]!=opt.entity_subtype:
  1669. ListChanges.append(('changed', opt.uid,
  1670. DicResult[opt.slug_entity_type]['title'],
  1671. tst[1]))
  1672. else:
  1673. ListChanges.append(('remove', opt.uid, opt.entity_type, opt.entity_subtype))
  1674. # Do The change
  1675. for action, uid, entity, subentity in ListChanges:
  1676. if action=="changed":
  1677. opt = TiersOpt.by_id(uid)
  1678. opt.entity_type = entity
  1679. opt.entity_subtype = subentity
  1680. elif action=="remove":
  1681. opt = TiersOpt.by_id(uid)
  1682. DBSession.delete(opt)
  1683. elif action=="add":
  1684. opt = TiersOpt()
  1685. opt.entity_type = entity
  1686. opt.entity_subtype = subentity
  1687. DBSession.add(opt)
  1688. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1689. 'logged_in':request.authenticated_userid, 'TiersOpt':TiersOpt }
  1690. return MainTab
  1691. @view_config(route_name='show_user', renderer="jm2l:templates/view_user.mako")
  1692. def show_user(request):
  1693. user_slug = request.matchdict.get('user_slug', None)
  1694. if user_slug is None or len(user_slug)==0:
  1695. raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
  1696. # Query database
  1697. DispUser = User.by_slug(user_slug)
  1698. if DispUser is None:
  1699. raise HTTPNotFound()
  1700. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1701. 'DispUser':DispUser, 'logged_in':request.authenticated_userid }
  1702. return MainTab
  1703. #@view_config(route_name='link_user_entity')
  1704. def link_user_entity(request):
  1705. if request.user is None:
  1706. # Don't answer to users that aren't logged
  1707. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1708. uid = int(request.matchdict.get('uid', -1))
  1709. year = int(request.matchdict.get('year', -1))
  1710. user_id = int(request.matchdict.get('uid', -1))
  1711. TheTiers = Tiers.by_id(uid)
  1712. if TheTiers is None:
  1713. raise HTTPNotFound()
  1714. return HTTPFound(location=request.route_url('edit_entity', uid=uid) )
  1715. #@view_config(route_name='link_role_entity')
  1716. def link_role_entity(request):
  1717. if request.user is None:
  1718. # Don't answer to users that aren't logged
  1719. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1720. uid = int(request.matchdict.get('uid', -1))
  1721. year = int(request.matchdict.get('year', -1))
  1722. role_id = int(request.matchdict.get('role_id', -1))
  1723. TheTiers = Tiers.by_id(uid)
  1724. if TheTiers is None:
  1725. raise HTTPNotFound()
  1726. return HTTPFound(location=request.route_url('edit_entity', uid=uid) )
  1727. @forbidden_view_config()
  1728. def forbidden(reason, request):
  1729. if 'ident' in reason.detail:
  1730. request.session.flash(('info', reason.detail))
  1731. return HTTPFound(location='/sign/login?from='+request.environ['PATH_INFO'] )
  1732. else:
  1733. request.response.status = 403
  1734. return render_to_response('jm2l:templates/Errors/403.mako', { "reason":reason },
  1735. request=request)
  1736. @notfound_view_config()
  1737. def notfound(reason, request):
  1738. request.response.status = 404
  1739. return render_to_response('jm2l:templates/Errors/404.mako', { "reason":reason },
  1740. request=request)