Le repo des sources pour le site web des JM2L
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

1050 linhas
45 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.response import Response
  6. from pyramid.view import notfound_view_config, forbidden_view_config
  7. from pyramid.view import view_config
  8. # Import Web Forms
  9. from .forms import *
  10. # Database access imports
  11. from .models import *
  12. from sqlalchemy.exc import DBAPIError
  13. from sqlalchemy import func, or_
  14. # Usefull tools
  15. from slugify import slugify
  16. from icalendar import Calendar
  17. from pytz import timezone
  18. from icalendar import Event as Evt
  19. # Then, standard libs
  20. import webhelpers.paginate as paginate
  21. import unicodedata
  22. import time
  23. import datetime
  24. import re
  25. CurrentYear = 2015
  26. ## =-=- Here, We keep some usefull function -=-=
  27. def remove_accents(input_str):
  28. """ This function is intended to remove all accent from input unicode string """
  29. nkfd_form = unicodedata.normalize('NFKD', input_str)
  30. only_ascii = nkfd_form.encode('ASCII', 'ignore')
  31. return only_ascii
  32. @view_config(route_name='tester', renderer="jm2l:templates/tester.mako")
  33. def Tester(request):
  34. JTiers = DBSession.query(Tiers).all()
  35. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  36. 'Tiers':JTiers, "logged_in":request.authenticated_userid }
  37. return MainTab
  38. ## =-=- Here, We handle ICal requests -=-=
  39. @view_config(route_name='progr_iCal', renderer="string")
  40. def ICal_Progamme_Request(request):
  41. year = int(request.matchdict.get('year', CurrentYear))
  42. # Initialization
  43. DicResult = dict()
  44. # Query database
  45. # Compute days used by all events matching the specified input year
  46. Events = DBSession.query(Event)\
  47. .filter(Event.for_year == year)\
  48. .filter(Event.event_type != 'Stand')\
  49. .order_by(Event.start_time)
  50. cal = Calendar()
  51. cal.add('prodid', '-//Programme %d//jm2l.linux-azur.org//' % year)
  52. cal.add('version', '2.0')
  53. tz = timezone('Europe/Paris')
  54. for ev in Events:
  55. if ev.event_type:
  56. event = Evt()
  57. event['uid'] = "%d/%d" % ( year, ev.uid )
  58. event.add('summary', ev.name )
  59. event.add('dtstart', ev.start_time.replace(tzinfo=tz) )
  60. event.add('dtend', ev.end_time.replace(tzinfo=tz) )
  61. event.add('created', ev.last_change.replace(tzinfo=tz) )
  62. event.add('description', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  63. event.add('url', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  64. event.add('priority', 5)
  65. cal.add_component(event)
  66. return cal.to_ical()
  67. ## =-=- Here, We handle Json requests -=-=
  68. @view_config(route_name='users_json', renderer="json")
  69. def JSON_User_Request(request):
  70. """ Build a JSON answer with active users and pagination handling """
  71. # Check arguments consitency
  72. pageSize = request.params.get('pageSize',"8")
  73. current_page = request.params.get('pageNum',"1")
  74. UserQuery = request.params.get('searchTerm', u"")
  75. # Don't answer to users that aren't logged
  76. if not request.user:
  77. return HTTPUnauthorized('You have to be logged to hope an answer.')
  78. # Check consistancy of parameters
  79. if pageSize.isdigit() and current_page.isdigit():
  80. current_page = int(current_page)
  81. pageSize = int(pageSize)
  82. else:
  83. return HTTPBadRequest('pageSize and pageNum accept only digits.')
  84. # Query database
  85. Users = DBSession.query(User.uid, User.nom, User.prenom)\
  86. .filter(User.slug.contains( remove_accents(UserQuery) ))
  87. page_url = paginate.PageURL_WebOb(request)
  88. records = paginate.Page(Users, current_page, url=page_url, items_per_page=pageSize)
  89. ListMatchUser = map( lambda u:{"id": u.uid, "text":"%s %s" % ( u.prenom, u.nom )}, records )
  90. return { "Results": ListMatchUser, "Total":records.item_count,
  91. "logged_in":request.authenticated_userid }
  92. @view_config(route_name='tiers_json', renderer="json")
  93. def JSON_Tiers_Request(request):
  94. """ Build a JSON answer with active users and pagination handling """
  95. # Check arguments consitency
  96. pageSize = request.params.get('pageSize',"8")
  97. current_page = request.params.get('pageNum',"1")
  98. TiersQuery = request.params.get('searchTerm', u"")
  99. # Don't answer to users that aren't logged
  100. if not request.user:
  101. return HTTPUnauthorized('You have to be logged to hope an answer.')
  102. # Check consistancy of parameters
  103. if pageSize.isdigit() and current_page.isdigit():
  104. current_page = int(current_page)
  105. pageSize = int(pageSize)
  106. else:
  107. return HTTPBadRequest('pageSize and pageNum accept only digits.')
  108. # Query database
  109. JTiers = DBSession.query(Tiers.uid, Tiers.name)\
  110. .filter(Tiers.slug.contains( remove_accents(TiersQuery) ))
  111. page_url = paginate.PageURL_WebOb(request)
  112. records = paginate.Page(JTiers, current_page, url=page_url, items_per_page=pageSize)
  113. ListMatchTiers = map( lambda t:{"id": t.uid, "text": t.name }, records )
  114. return { "Results": ListMatchTiers, "Total":records.item_count,
  115. "logged_in":request.authenticated_userid }
  116. @view_config(route_name='progr_json', renderer="json")
  117. def JSON_Progamme_Request(request):
  118. year = int(request.matchdict.get('year', CurrentYear))
  119. # Initialization
  120. DicResult = dict()
  121. # Query database
  122. # Compute days used by all events matching the specified input year
  123. Days = DBSession.query( func.strftime('%d', Event.start_time).label('day') )\
  124. .filter(Event.for_year == year)\
  125. .filter(Event.event_type != None)\
  126. .group_by(func.strftime('%d', Event.start_time)).all()
  127. for Day in Days:
  128. Events = DBSession.query(Event)\
  129. .filter(Event.for_year == year)\
  130. .filter(Event.event_type != 'Stand')\
  131. .filter("strftime('%d', start_time) = :dow").params(dow=Day.day)\
  132. .order_by(Event.start_time)
  133. ListEv = []
  134. for ev in Events:
  135. if ev.event_type:
  136. ListEv.append( {
  137. "uid":"%d/%d" % ( year, ev.uid ),
  138. "desc":ev.name,
  139. "startDate":ev.start_time.strftime('%Y-%m-%dT%H:%M:%S'),
  140. "endDate":ev.end_time.strftime('%Y-%m-%dT%H:%M:%S'),
  141. "placeName":ev.Salle and (ev.Salle.name or "unk") ,
  142. "status":ev.event_type
  143. } )
  144. DicResult[Day.day] = ListEv
  145. return { 'all':DicResult }
  146. @view_config(route_name='timeline_json', renderer="json")
  147. def JSON_TimeLine_Request(request):
  148. year = int(request.matchdict.get('year', CurrentYear))
  149. # Initialization
  150. DicResult = dict()
  151. # Query database
  152. # Compute days used by all events matching the specified input year
  153. Days = DBSession.query( func.strftime('%d', Event.start_time).label('day') )\
  154. .filter(Event.for_year == year)\
  155. .filter(Event.event_type != None)\
  156. .group_by(func.strftime('%d', Event.start_time)).all()
  157. ListEv = []
  158. for Day in Days:
  159. Events = DBSession.query(Event)\
  160. .filter(Event.for_year == year)\
  161. .filter(Event.event_type != 'Stand')\
  162. .filter("strftime('%d', start_time) = :dow").params(dow=Day.day)\
  163. .order_by(Event.start_time)
  164. ListEv = []
  165. for ev in Events:
  166. if ev.event_type:
  167. ListEv.append( {
  168. #"uid":"%d/%d" % ( year, ev.uid ),
  169. "headline":ev.name,
  170. "startDate":ev.start_time.strftime('%Y,%m,%d,%H,%M'),
  171. "endDate":ev.end_time.strftime('%Y,%m,%d,%H,%M'),
  172. "text":ev.Salle and (ev.Salle.name or "unk"),
  173. "tags":ev.Salle and (ev.Salle.name or "unk") ,
  174. #"status":ev.event_type,
  175. "asset": {
  176. "media":"", #http://jm2l.linux-azur.org/sites/jm2l.linux-azur.org/files/videos/2012/2012_Introduction_aux_logiciels_libres__Frederic_Couchet.ogv",
  177. "credit":"",
  178. "caption":"" }
  179. } )
  180. break
  181. DicResult = {
  182. "lang":"fr",
  183. "headline":"JM2L 2015",
  184. "type":"default",
  185. "startDate":"2015,11,28,10",
  186. "text":"<i><span class='c1'>9ème Édition</span></i>",
  187. "asset":
  188. {
  189. "media":"",
  190. "credit":"JM2L",
  191. "caption":""
  192. }
  193. }
  194. DicResult["date"] = ListEv
  195. return { 'timeline':DicResult }
  196. ## =-=- Here, We handle HTTP requests - Public Part -=-=
  197. @view_config(route_name='home', renderer="jm2l:templates/NewIndex.mako")
  198. def index_page(request):
  199. page = int(request.params.get('page', 1))
  200. paginator = Entry.get_paginator(request, page)
  201. profil = User.by_id(4)
  202. profil_form = ProfilForm(request.POST, profil, meta={'csrf_context': request.session})
  203. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'', 'paginator':paginator,
  204. "logged_in":request.authenticated_userid }
  205. return MainTab
  206. @view_config(route_name='programme', renderer="jm2l:templates/Public/Programme.mako")
  207. def programme(request):
  208. year = int(request.matchdict.get('year'))
  209. if 2006 > year:
  210. return HTTPBadRequest('The first JM2L event was in 2006.')
  211. # Query database about selected Year.
  212. Events = DBSession.query(Event)\
  213. .filter(Event.for_year == year)\
  214. .order_by(Event.start_time)
  215. Days = DBSession.query(func.strftime('%d-%m-%Y', Event.start_time))\
  216. .filter(Event.for_year == year)\
  217. .filter(Event.event_type != None)\
  218. .group_by(func.strftime('%d', Event.start_time)).all()
  219. ListDay = []
  220. for day in Days:
  221. RefDay = datetime.datetime.strptime(day[0],'%d-%m-%Y')
  222. ListDay.append( ( RefDay.strftime('%A %d %b %Y'),
  223. RefDay.strftime('%d') ) )
  224. MainTab = {'programme':'active','presse':'', 'plan':'', 'participer':'', 'DisplayYear':year, \
  225. 'Events':Events, 'Event':Event, 'Days':ListDay, "logged_in":request.authenticated_userid }
  226. return MainTab
  227. @view_config(route_name='presse', renderer="jm2l:templates/Public/Presse.mako")
  228. def static_presse(request):
  229. year = int(request.matchdict.get('year', None))
  230. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  231. MainTab = {'programme':'','presse':'active', 'plan':'', 'participer':'',
  232. "logged_in":request.authenticated_userid, 'content':content, 'DisplayYear':year}
  233. return MainTab
  234. @view_config(route_name='edit_presse', renderer="jm2l:templates/Staff/EditPresse.mako")
  235. def edit_presse(request):
  236. year = int(request.matchdict.get('year', None))
  237. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  238. form = DossPresse(request.POST, content, meta={'csrf_context': request.session})
  239. if request.method == 'POST' and form.validate():
  240. form.populate_obj(content)
  241. MainTab = {'programme':'','presse':'active', 'plan':'', 'participer':'',
  242. "logged_in":request.authenticated_userid, 'form':form, 'DisplayYear':year}
  243. return MainTab
  244. @view_config(route_name='plan', renderer="jm2l:templates/Public/Plan.mako")
  245. def static_plan(request):
  246. MainTab = {'programme':'','presse':'', 'plan':'active', 'participer':'',
  247. "logged_in":request.authenticated_userid }
  248. return MainTab
  249. ## =-=- Here, We handle HTTP requests - Staff Logged Part -=-=
  250. @view_config(route_name='list_task', renderer='jm2l:templates/Staff/list.mako')
  251. def list_view(request):
  252. DicTask = {}
  253. taskgroup = DBSession.query( TasksArea ).all()
  254. for grp in taskgroup:
  255. tasks = DBSession.query( Tasks )\
  256. .filter( Tasks.area_uid==grp.uid )\
  257. .order_by(Tasks.closed, Tasks.due_date).all()
  258. DicTask[grp] = tasks
  259. return {'tasks': DicTask }
  260. @view_config(route_name='handle_task', renderer='jm2l:templates/Staff/tasks.mako')
  261. def tasks(request):
  262. task_id = request.matchdict.get('task_id')
  263. if task_id:
  264. Task = Tasks.by_id(int(task_id))
  265. if not Task:
  266. raise HTTPNotFound()
  267. form = EditStaffTasks(request.POST, Task, meta={'csrf_context': request.session})
  268. else:
  269. Task = Tasks()
  270. form = StaffTasks(request.POST, Task, meta={'csrf_context': request.session})
  271. # Put some areas on form
  272. Areas = DBSession.query(TasksArea.uid, TasksArea.name)\
  273. .order_by('name').all()
  274. form.area_uid.choices = Areas
  275. # Put some users on form
  276. Users = DBSession.query(User)\
  277. .filter(User.Staff==1)\
  278. .order_by('nom').all()
  279. form.closed_by.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  280. for u in Users]
  281. if request.method == 'POST' and form.validate():
  282. form.populate_obj(Task)
  283. Task.closed = False
  284. if 'uid' in form._fields.keys():
  285. DBSession.merge(Task)
  286. else:
  287. DBSession.add(Task)
  288. return HTTPFound(location=request.route_url('list_task'))
  289. return {'form':form }
  290. @view_config(route_name='handle_pole', renderer='jm2l:templates/Staff/pole.mako')
  291. def tasks_area(request):
  292. pole_id = request.matchdict.get('pole_id')
  293. if pole_id:
  294. Pole = TasksArea.by_id(int(pole_id))
  295. if not Pole:
  296. raise HTTPNotFound()
  297. form = EditStaffArea(request.POST, Pole, meta={'csrf_context': request.session})
  298. else:
  299. Pole = TasksArea()
  300. form = StaffArea(request.POST, Pole, meta={'csrf_context': request.session})
  301. if request.method == 'POST' and form.validate():
  302. form.populate_obj(Pole)
  303. if 'uid' in form._fields.keys():
  304. DBSession.merge(Pole)
  305. else:
  306. DBSession.add(Pole)
  307. return HTTPFound(location=request.route_url('list_task'))
  308. return {'form':form }
  309. @view_config(route_name='action_task')
  310. def action_task(request):
  311. action = request.matchdict.get('action')
  312. task_id = request.matchdict.get('task_id')
  313. Task = Tasks.by_id(int(task_id))
  314. if action=='close':
  315. Task.closed = True
  316. if action=='open':
  317. Task.closed = False
  318. DBSession.merge(Task)
  319. request.session.flash('Task was successfully closed!')
  320. return HTTPFound(location=request.route_url('list_task'))
  321. ## =-=- Here, We handle HTTP requests - User Logged Part -=-=
  322. @view_config(route_name='exchange', renderer="jm2l:templates/Logistique/Logistique.mako")
  323. def exchange(request):
  324. modtype = request.matchdict.get('modtype', None)
  325. action = request.matchdict.get('action', None)
  326. uid = int(request.matchdict.get('id', -1))
  327. Exch = Exchange.by_id(uid)
  328. if not Exch:
  329. MainTab = {
  330. 'Exchanges':Exchange,
  331. 'Type':modtype[-1:],
  332. 'reload':True,
  333. 'logged_in':request.authenticated_userid
  334. }
  335. return MainTab
  336. if action in ['delete', 'accept', 'refuse', 'deal']:
  337. if action=='delete': # delete exchange
  338. DBSession.delete(Exch)
  339. elif action=='accept': # accept exchange
  340. Exch.exch_done=True
  341. DBSession.merge(Exch)
  342. elif action=='refuse': # refuse exchange
  343. Exch.exch_done=False
  344. if Exch.exch_state=="Ask":
  345. Exch.provider_id = None
  346. elif Exch.exch_state=="Proposal":
  347. Exch.asker_id = None
  348. DBSession.merge(Exch)
  349. elif action=='deal':
  350. # ask to deal the exchange
  351. if Exch.exch_state=="Ask":
  352. Exch.provider_id = request.user.uid
  353. elif Exch.exch_state=="Proposal":
  354. Exch.asker_id = request.user.uid
  355. # Return javascript to parent page
  356. response = render_to_response('jm2l:templates/modals_js.mako',
  357. {'modtype':modtype, 'action':action},
  358. request=request)
  359. response.content_type = 'text/javascript'
  360. return response
  361. else:
  362. MainTab = {
  363. 'Exchanges':Exchange,
  364. 'Type':modtype[-1:],
  365. 'reload':True,
  366. 'logged_in':request.authenticated_userid
  367. }
  368. return MainTab
  369. @view_config(route_name='jm2l', renderer="jm2l:templates/jm2l.mako")
  370. def jm2l_page(request):
  371. if request.user is None:
  372. # Don't answer to users that aren't logged
  373. return HTTPUnauthorized('You have to be logged to hope an answer.')
  374. page = int(request.params.get('page', 1))
  375. UserNum = request.params.get('user')
  376. if UserNum:
  377. profil = User.by_id(int(UserNum))
  378. if not profil:
  379. raise HTTPNotFound()
  380. else:
  381. profil = request.user
  382. # Build Form
  383. profil_form = ProfilForm(request.POST, profil, meta={'csrf_context': request.session})
  384. if request.method == 'POST' and profil_form.validate():
  385. ToDelete = list()
  386. # First, we remove entries no more present
  387. for obj in profil_form.tiersship.object_data:
  388. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  389. profil_form.tiersship.entries )
  390. if not MatchEntry:
  391. ToDelete.append(obj)
  392. # Then, it's time to consider new entries
  393. for entry in profil_form.tiersship.entries:
  394. if entry.object_data is None:
  395. TmpUser = User_Tiers()
  396. entry.object_data = TmpUser
  397. profil.tiersship.append(TmpUser)
  398. profil_form.tiersship.object_data = profil.tiersship
  399. profil_form.populate_obj(profil)
  400. # We should remove it as it's not in original data
  401. for obj in ToDelete:
  402. #profil.tiersship.remove(obj)
  403. DBSession.delete(obj)
  404. profil.last_change = datetime.datetime.utcnow()
  405. profil.slug = slugify(remove_accents('%s %s' % (profil.prenom, profil.nom)).lower().strip())
  406. DBSession.merge(profil)
  407. MainTab = {'participer':'active',
  408. 'Places':Place.get_list(False),
  409. 'DBTiers':Tiers,
  410. 'DBTiersOpt':TiersOpt,
  411. 'Exchanges':Exchange,
  412. 'profil_form':profil_form,
  413. 'uprofil':profil,
  414. 'logged_in':request.authenticated_userid
  415. }
  416. return MainTab
  417. @view_config(route_name='modal', renderer="jm2l:templates/modals.mako")
  418. def Modal(request):
  419. year = int(request.matchdict.get('year', None))
  420. modtype = request.matchdict.get('modtype', None)
  421. uid = int(request.matchdict.get('id', -1))
  422. session = request.session
  423. if modtype=='Password':
  424. form = UserPasswordForm(request.POST, request.user, meta={'csrf_context': request.session})
  425. if request.method == 'POST' and form.validate():
  426. response = render_to_response('jm2l:templates/modals_js.mako',
  427. {'modtype':modtype},
  428. request=request)
  429. response.content_type = 'text/javascript'
  430. return response
  431. if modtype=='UserPicture':
  432. form = None
  433. if request.method == 'POST':
  434. response = render_to_response('jm2l:templates/modals_js.mako',
  435. {'modtype':modtype},
  436. request=request)
  437. response.content_type = 'text/javascript'
  438. return response
  439. if modtype=='Place':
  440. if uid>0:
  441. place = Place.by_id(uid)
  442. if not place:
  443. raise HTTPNotFound()
  444. form = PlaceUpdateForm(request.POST, place, meta={'csrf_context': request.session})
  445. else:
  446. place = Place()
  447. form = PlaceCreateForm(request.POST, meta={'csrf_context': request.session})
  448. if request.method == 'POST' and form.validate():
  449. form.populate_obj(place)
  450. place.created_by=request.user.uid
  451. if uid>0:
  452. DBSession.merge(place)
  453. else:
  454. DBSession.add(place)
  455. response = render_to_response('jm2l:templates/modals_js.mako',
  456. {'modtype':modtype},
  457. request=request)
  458. response.content_type = 'text/javascript'
  459. return response
  460. if modtype in ['AskC', 'AskH', 'AskM', 'PropC', 'PropH', 'PropM']:
  461. if uid>0:
  462. Exch = Exchange.by_id(uid)
  463. if not Exch:
  464. raise HTTPNotFound()
  465. if modtype in ['AskC','PropC']:
  466. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  467. start_place = Exch.Itin.start_place,
  468. arrival_place = Exch.Itin.arrival_place,
  469. Hour_start = Exch.start_time.strftime("%H:%M"),
  470. Day_start = Exch.start_time.strftime("%w"),
  471. exch_id = uid, meta={'csrf_context': request.session}
  472. )
  473. elif modtype in ['AskM','PropM']:
  474. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  475. description = Exch.description,
  476. exch_categ = Exch.exch_categ,
  477. Hour_start = Exch.start_time.strftime("%H:%M"),
  478. Day_start = Exch.start_time.strftime("%w"),
  479. Hour_end = Exch.end_time.strftime("%H:%M"),
  480. Day_end = Exch.end_time.strftime("%w"),
  481. exch_id = uid, meta={'csrf_context': request.session}
  482. )
  483. elif modtype in ['AskH','PropH']:
  484. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  485. description = Exch.description,
  486. exch_categ = Exch.exch_categ,
  487. Day_start = Exch.start_time.strftime("%w"),
  488. exch_id = uid, meta={'csrf_context': request.session}
  489. )
  490. # Itinerary, first get itinerary
  491. if 0:
  492. form.itin.form.start_place.data = Exch.Itin.start_place
  493. form.itin.form.arrival_place.data = Exch.Itin.arrival_place
  494. form.dateform.form.Hour.data = Exch.start_time.strftime("%H:%M")
  495. form.dateform.form.Day.data = Exch.start_time.strftime("%w")
  496. form.exch_id.data = uid
  497. else:
  498. Exch = Exchange()
  499. form = globals()["%sForm" % modtype](request.POST, meta={'csrf_context': request.session})
  500. if modtype in ['AskC', 'PropC']:
  501. # Put some place on form
  502. Places = DBSession.query(Place.place_id, Place.display_name)\
  503. .order_by('name').all()
  504. form.start_place.choices = Places
  505. form.arrival_place.choices = Places
  506. if modtype in ['PropH']:
  507. form.exch_categ.choices = DBSession.query( Exchange_Cat.cat_id, Exchange_Cat.exch_subtype)\
  508. .filter( Exchange_Cat.exch_type=='H' ).all()
  509. form.place_id.choices = DBSession.query( Place.place_id, Place.display_name)\
  510. .filter( Place.created_by==request.user.uid ).all()
  511. if modtype in ['AskM', 'PropM']:
  512. form.exch_categ.choices = DBSession.query( Exchange_Cat.cat_id, Exchange_Cat.exch_subtype)\
  513. .filter( Exchange_Cat.exch_type=='M' ).all()
  514. if request.method == 'POST' and form.validate():
  515. # Form has been validated, it's time to create our Exchange
  516. Exch.for_year = year
  517. Exch.exch_state = {'Ask':'Ask', 'Prop':'Proposal'}[modtype[:-1]]
  518. Exch.exch_type = modtype[-1:]
  519. if modtype in ['AskC', 'PropC']:
  520. # Itinerary, first Let's see if itinerary exist
  521. Itinerary = DBSession.query(Itineraire)\
  522. .filter(Itineraire.start_place==form.start_place.data) \
  523. .filter(Itineraire.arrival_place==form.arrival_place.data) \
  524. .filter(Itineraire.tr_voiture==True) \
  525. .first()
  526. if not Itinerary: # Not exist yet !
  527. Itinerary = Itineraire(start_place=form.start_place.data, \
  528. arrival_place=form.arrival_place.data, \
  529. tr_voiture=True, \
  530. created_by=1
  531. )
  532. DBSession.add(Itinerary)
  533. DBSession.flush()
  534. Exch.itin_id = Itinerary.itin_id
  535. # Start Time
  536. StartEvent = DBSession.query(JM2L_Year.start_time).filter(JM2L_Year.year_uid==year).first()
  537. Week = StartEvent[0].strftime("%W")
  538. # populate
  539. form.populate_obj(Exch)
  540. if modtype in ['AskC', 'PropC']:
  541. Exch.itin_id = Itinerary.itin_id
  542. if form._fields.has_key("Hour_start"):
  543. TargetTime = datetime.datetime.strptime('%d %d %d %s' % (year, int(Week), \
  544. int(form.Day_start.data), form.Hour_start.data), "%Y %W %w %H:%M")
  545. Exch.start_time = TargetTime
  546. elif form._fields.has_key("Day_start"):
  547. TargetTime = datetime.datetime.strptime('%d %d %d' % (year, int(Week), \
  548. int(form.Day_start.data)), "%Y %W %w")
  549. Exch.start_time = TargetTime
  550. if form._fields.has_key("Hour_end"):
  551. TargetTime = datetime.datetime.strptime('%d %d %d %s' % (year, int(Week), \
  552. int(form.Day_end.data), form.Hour_end.data), "%Y %W %w %H:%M")
  553. Exch.end_time = TargetTime
  554. elif form._fields.has_key("Day_end"):
  555. TargetTime = datetime.datetime.strptime('%d %d %d' % (year, int(Week), \
  556. int(form.Day_end.data)), "%Y %W %w")
  557. Exch.end_time = TargetTime
  558. Exch.last_change = datetime.datetime.utcnow()
  559. if Exch.exch_state=='Ask':
  560. Exch.asker_id = request.user.uid
  561. elif Exch.exch_state=='Proposal':
  562. Exch.provider_id = request.user.uid
  563. #print vars(form.itin.form)
  564. if uid>0:
  565. DBSession.merge(Exch)
  566. else:
  567. DBSession.add(Exch)
  568. response = render_to_response('jm2l:templates/modals_js.mako',
  569. {'modtype':modtype},
  570. request=request)
  571. response.content_type = 'text/javascript'
  572. return response
  573. # Fallback to HTML Display with errors
  574. return {'modtype':modtype, 'form':form, 'update':uid>0,
  575. 'logged_in':request.authenticated_userid }
  576. if modtype in ['ShowC', 'ShowH', 'ShowM']:
  577. if uid>0:
  578. Exch = Exchange.by_id(uid)
  579. if not Exch:
  580. raise HTTPNotFound()
  581. else:
  582. raise HTTPNotFound()
  583. # Show Details around the Current Exchange
  584. return {'modtype':modtype, 'Exch':Exch, 'logged_in':request.authenticated_userid }
  585. MainTab = {'modtype':modtype, 'form':form, 'update':uid>0, 'uid':uid,
  586. 'DisplayYear':year, 'session':session,
  587. 'logged_in':request.authenticated_userid }
  588. return MainTab
  589. @view_config(route_name='participer', renderer="jm2l:templates/Participer.mako")
  590. def participer(request):
  591. session = request.session
  592. session['year'] = 2015
  593. TmpUsr = User()
  594. form = UserRegisterForm(request.POST, TmpUsr, meta={'csrf_context': request.session})
  595. MyLink=None
  596. if request.method == 'POST' and form.validate():
  597. form.populate_obj(TmpUsr)
  598. TmpUsr.nom = TmpUsr.nom.capitalize()
  599. TmpUsr.prenom = TmpUsr.prenom.capitalize()
  600. TmpUsr.slug = slugify(remove_accents('%s %s' % (form.prenom.data, form.nom.data)).lower().strip())
  601. TmpUsr.password = TmpUsr.my_hash
  602. if len(TmpUsr.slug):
  603. CheckExist = DBSession.query(User)\
  604. .filter(User.slug==TmpUsr.slug)\
  605. .first()
  606. else:
  607. CheckExist=None
  608. if CheckExist:
  609. MyLink = CheckExist.my_hash
  610. else:
  611. DBSession.add(TmpUsr)
  612. DBSession.flush()
  613. MyLink = TmpUsr.my_hash
  614. MainTab = {'programme':'','presse':'', 'plan':'',
  615. 'participer':'active', 'form':form, "link": MyLink,
  616. 'logged_in':request.authenticated_userid }
  617. return MainTab
  618. @view_config(route_name='year')
  619. def change_year(request):
  620. year = int(request.matchdict.get('year', -1))
  621. session = request.session
  622. if year>-1:
  623. session['year'] = year
  624. return HTTPFound(location='/%s/le-programme' % year)
  625. return HTTPFound(location=request.route_url('home'))
  626. @view_config(route_name='pict_user', renderer="jm2l:templates/Profil/pict_user.mako")
  627. def pict_user(request):
  628. return {"uprofil":request.user}
  629. @view_config(route_name='event', renderer="jm2l:templates/view_event.mako")
  630. def show_event(request):
  631. year = int(request.matchdict.get('year', -1))
  632. event_id = request.matchdict.get('event_id')
  633. if event_id.isdigit():
  634. TheEvent = Event.by_id(event_id)
  635. if TheEvent is None:
  636. raise HTTPNotFound()
  637. else:
  638. TheEvent = Event.by_slug(event_id, year)
  639. if TheEvent is None:
  640. raise HTTPNotFound()
  641. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  642. 'event':TheEvent, 'logged_in':request.authenticated_userid }
  643. return MainTab
  644. @view_config(route_name='link_event')
  645. def link_event(request):
  646. """ Create user if not exist, add it to current event """
  647. year = int(request.matchdict.get('year', -1))
  648. form = AddIntervenant(request.POST, meta={'csrf_context': request.session})
  649. intervention = request.matchdict.get('intervention', None)
  650. TargetEvent = Event.by_id(form.event_uid.data)
  651. Exist = DBSession.query(User)\
  652. .filter(User.nom==form.nom.data)\
  653. .filter(User.prenom==form.prenom.data)\
  654. .first()
  655. if Exist:
  656. TargetUser = Exist
  657. else:
  658. # Add it to user base
  659. TargetUser = User(nom=form.nom.data,
  660. prenom=form.prenom.data, password=form.nom.data)
  661. DBSession.add(TargetUser)
  662. DBSession.flush()
  663. uev = User_Event(year_uid=year, role="Animateur", user_uid=TargetUser.uid)
  664. TargetEvent.interventions.append( uev )
  665. return HTTPFound(location=request.route_url('edit_event', sep='/',
  666. year=str(year), intervention=intervention, uid=str(TargetEvent.uid)))
  667. @view_config(route_name='edit_event', renderer="jm2l:templates/edit_event.mako")
  668. def edit_event(request):
  669. year = int(request.matchdict.get('year', -1))
  670. event_id = request.matchdict.get('event_id')
  671. intervention = request.matchdict.get('intervention', None)
  672. IntervLabel = intervention.replace('_',' ').lower()
  673. if intervention=='Conference':
  674. IntervLabel = u'conférence'
  675. # Check intervention
  676. if not intervention in ['Stand', 'Table ronde', 'Atelier', 'Conference']:
  677. raise HTTPNotFound(u"Ce type d'évenement n'est pas reconnu")
  678. TheYear = DBSession.query(JM2L_Year)\
  679. .filter(JM2L_Year.year_uid==year)\
  680. .all()
  681. # Check year avaibility
  682. if not TheYear:
  683. raise HTTPNotFound(u"Cette année n'est pas pris en charge")
  684. # Generate Timeslots for current year
  685. TimeSlots = list(enumerate( [ x.strftime('%a %d %b %H:%M') for x in
  686. TheYear[0].AvailableTimeSlots ] ))
  687. if event_id:
  688. # We try to update an existing record
  689. if event_id.isdigit():
  690. TheEvent = Event.by_id(event_id)
  691. if TheEvent is None:
  692. raise HTTPNotFound(u"Cette réference n'existe pas")
  693. else:
  694. TheEvent = Event.by_slug(event_id, year)
  695. if TheEvent is None:
  696. raise HTTPNotFound(u"Cette réference n'existe pas")
  697. if not (request.user.uid==1 or request.user in TheEvent.intervenants):
  698. return HTTPForbidden(u"Vous n'êtes pas identifié comme étant un participant à cette intervention.")
  699. # Compute some field value from selected event
  700. if TheEvent.start_time in TheYear[0].AvailableTimeSlots:
  701. start_sel = TheYear[0].AvailableTimeSlots.index(TheEvent.start_time)
  702. else:
  703. start_sel = len(TimeSlots)
  704. TimeSlots.append( (len(TimeSlots), TheEvent.start_time.strftime('%a %d %b %H:%M')))
  705. duration = (TheEvent.end_time - TheEvent.start_time).total_seconds()/60
  706. end = TheEvent.start_time + datetime.timedelta(minutes=duration)
  707. # prepare the form with update
  708. form = ConfUpdateForm(request.POST, TheEvent, start_sel=start_sel, duration=duration, end_time=end,
  709. meta={'csrf_context': request.session} )
  710. # Customize labels
  711. form.name.label.text += IntervLabel
  712. form.description.label.text += IntervLabel
  713. # Each event can get severals members
  714. formAdd = AddIntervenant(event_uid=TheEvent.uid)
  715. else:
  716. TheEvent = Event()
  717. # prepare the form for creation
  718. form = ConfCreateForm(request.POST,
  719. event_type=intervention,
  720. for_year=str(year), meta={'csrf_context': request.session}
  721. )
  722. # Customize labels
  723. form.name.label.text += IntervLabel
  724. form.description.label.text += IntervLabel
  725. duration=60
  726. # No intervenant
  727. formAdd = None
  728. if intervention=="Conference":
  729. form.duration.choices =[
  730. (15,u'Lighting talk ( 5 min)'),
  731. (30,u'Conférence (20 min)'),
  732. (60,u'Conférence (50 min)'),
  733. (90,u'Conférence (75 min)'),
  734. ]
  735. if not duration in [15, 30, 60, 90]:
  736. form.duration.choices.append( (duration,u'Conférence (%d min)' % duration) )
  737. if not form._fields.has_key("uid"):
  738. form.duration.data=60
  739. elif intervention=="Stand":
  740. form.duration.choices =[
  741. (8*60, u'Toute la journée'),
  742. (4*60, u'une demi-journée')
  743. ]
  744. elif intervention=="Atelier":
  745. form.duration.choices = map( lambda d:(d, u'Atelier (%dh%.2d)' % (d/60, d%60) ), \
  746. [60, 90, 120, 150, 180, 210, 240] )
  747. if not duration in map(lambda (d,y): d, form.duration.choices):
  748. form.duration.choices.append( (duration,u'Atelier (%dh%.2d)' % (duration/60, duration%60) ) )
  749. elif intervention=="Table_Ronde":
  750. form.duration.choices = map( lambda d:(d, u'Table ronde (%dh%.2d)' % (d/60, d%60) ), \
  751. [60, 90, 120, 150] )
  752. if not duration in map(lambda (d,y): d, form.duration.choices):
  753. form.duration.choices.append( (duration,u'Table ronde (%dh%.2d)' % (duration/60, duration%60) ) )
  754. else:
  755. return HTTPForbidden(u"Pas encore disponible.")
  756. SalleDispo = DBSession.query(Salles)\
  757. .filter(Salles.year_uid==year)\
  758. .order_by('name')
  759. form.salle_uid.choices = [(s.salle_id, s.name) for s in SalleDispo]
  760. form.start_sel.choices = TimeSlots
  761. if request.method == 'POST' and form.validate():
  762. form.populate_obj(TheEvent)
  763. TheEvent.start_time = TheYear[0].AvailableTimeSlots[form.start_sel.data]
  764. TheEvent.end_time = TheEvent.start_time + datetime.timedelta(minutes=form.duration.data)
  765. # Ok, time to put in database
  766. if not form._fields.has_key("uid"):
  767. TheEvent.slug = slugify(TheEvent.name)
  768. DBSession.add(TheEvent)
  769. # Append creator by default
  770. if request.user.uid!=1:
  771. uev = User_Event(year_uid=TheYear.year_uid, role="Animateur")
  772. uev.user_uid = request.user.uid
  773. TheEvent.interventions.append( uev )
  774. DBSession.flush()
  775. return HTTPFound(location=request.route_url('edit_event', sep='/',
  776. year=str(year), intervention=intervention, event_id=str(TheEvent.slug)))
  777. else:
  778. DBSession.merge(TheEvent)
  779. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  780. 'event':TheEvent, 'form':form, 'formAdd':formAdd,
  781. 'logged_in':request.authenticated_userid }
  782. return MainTab
  783. @view_config(route_name='entities', renderer="jm2l:templates/list_tiers.mako")
  784. def list_tiers(request):
  785. Entities = dict()
  786. EntityType = DBSession.query(TiersOpt.entity_type)\
  787. .group_by(TiersOpt.entity_type).all()
  788. for EType in EntityType:
  789. Entities[EType.entity_type] = DBSession.query(Tiers).join(TiersOpt)\
  790. .filter(TiersOpt.entity_type==EType.entity_type)\
  791. .order_by(TiersOpt.entity_subtype, Tiers.name)
  792. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  793. 'entities':Entities, 'logged_in':request.authenticated_userid }
  794. return MainTab
  795. @view_config(route_name='show_entity', renderer="jm2l:templates/view_tiers.mako")
  796. def show_tiers(request):
  797. tiers_type = request.matchdict.get('tiers_type')
  798. entity_id = request.matchdict.get('entity_id')
  799. if entity_id.isdigit():
  800. TheTiers = Tiers.by_id(entity_id)
  801. if TheTiers is None:
  802. raise HTTPNotFound()
  803. else:
  804. TheTiers = Tiers.by_slug(entity_id)
  805. if TheTiers is None:
  806. raise HTTPNotFound()
  807. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  808. 'entity':TheTiers, 'logged_in':request.authenticated_userid }
  809. return MainTab
  810. @view_config(route_name='add_entity', renderer="jm2l:templates/edit_tiers.mako")
  811. @view_config(route_name='edit_entity', renderer="jm2l:templates/edit_tiers.mako",
  812. permission='edit')
  813. def edit_tiers(request):
  814. entity_id = request.matchdict.get('entity_id', None)
  815. TargetList = list()
  816. entity_types = DBSession.query(TiersOpt.entity_type).group_by(TiersOpt.entity_type).all()
  817. for entity_type in entity_types:
  818. entity_subtypes = DBSession.query(TiersOpt)\
  819. .filter(TiersOpt.entity_type==entity_type.entity_type)\
  820. .group_by(TiersOpt.entity_subtype).all()
  821. ListType = [(i.uid, i.entity_subtype) for i in entity_subtypes]
  822. TargetList.append( (entity_type.entity_type, ListType) )
  823. if entity_id:
  824. if entity_id.isdigit():
  825. TheTiers = Tiers.by_id(entity_id)
  826. if TheTiers is None:
  827. raise HTTPNotFound()
  828. else:
  829. TheTiers = Tiers.by_slug(entity_id)
  830. if TheTiers is None:
  831. raise HTTPNotFound()
  832. form = UpdateTiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  833. UserOptions = DBSession.query(TiersOpt)\
  834. .filter(TiersOpt.entity_type==TheTiers.tiers_type)\
  835. .all()
  836. form.tiers_type.choices = TargetList
  837. else:
  838. TheTiers = Tiers()
  839. # prepare the form for creation
  840. form = TiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  841. form.tiers_type.choices = TargetList
  842. UserOptions = list()
  843. #test_form = TiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  844. if request.method == 'POST' and form.validate():
  845. ToDelete = list()
  846. # First, we remove entries no more present
  847. for obj in form.membership.object_data:
  848. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  849. form.membership.entries )
  850. if not MatchEntry:
  851. ToDelete.append(obj)
  852. # We should remove it as it's not in original data
  853. for obj in ToDelete:
  854. TheTiers.membership.remove(obj)
  855. DBSession.delete(obj)
  856. # Then, it's time to consider new entries
  857. for entry in form.membership.entries:
  858. if entry.object_data is None:
  859. TmpUser = User_Tiers()
  860. entry.object_data = TmpUser
  861. TheTiers.membership.append(TmpUser)
  862. form.membership.object_data = TheTiers.membership
  863. form.populate_obj(TheTiers)
  864. # Handle Remove of accents
  865. TheTiers.slug = slugify(form.name.data)
  866. if not form._fields.has_key('uid'):
  867. TheTiers.creator_id = request.user.uid
  868. DBSession.add(TheTiers)
  869. DBSession.flush()
  870. return HTTPFound(location=request.route_url('edit_entity', sep='/',
  871. entity_id=str(TheTiers.slug), tiers_type=TheTiers.get_entity_type.entity_type))
  872. DBSession.merge(TheTiers)
  873. return HTTPFound(location=request.route_url('entities'))
  874. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  875. 'form':form, 'DBUser':User, 'UserOptions':UserOptions,
  876. 'logged_in':request.authenticated_userid }
  877. return MainTab
  878. @view_config(route_name='edit_entity_cat', renderer="jm2l:templates/edit_tiers_categ.mako")
  879. def edit_tiers_category(request):
  880. DicResult = dict()
  881. ListChanges = list()
  882. if request.method == 'POST':
  883. # Reformat data
  884. RegExist = re.compile('collection\[(?P<slug>[\w-]+)\]\[(?P<num>\d+)\]\[(?P<id>\d+)\]')
  885. RegTitle = re.compile('collection\[(?P<slug>[\w-]+)\]\[title]')
  886. RegNew = re.compile('collection\[(?P<slug>[\w-]+)\]\[(?P<num>\d+)\]\[id\]')
  887. for key, value in request.POST.iteritems():
  888. regN= RegNew.match(key)
  889. regT= RegTitle.match(key)
  890. reg = RegExist.match(key)
  891. if reg:
  892. if not DicResult.has_key(reg.group('slug')):
  893. DicResult[reg.group('slug')] = dict()
  894. if DicResult[reg.group('slug')].has_key('items'):
  895. DicResult[reg.group('slug')]['items'].append( ( int(reg.group('id')), value ) )
  896. else:
  897. DicResult[reg.group('slug')]['items'] = [ ( int(reg.group('id')), value ) ]
  898. elif regN:
  899. if not DicResult.has_key(regN.group('slug')):
  900. DicResult[regN.group('slug')] = dict()
  901. if DicResult[regN.group('slug')].has_key('items'):
  902. DicResult[regN.group('slug')]['items'].append( ( 'id', value ) )
  903. else:
  904. DicResult[regN.group('slug')]['items'] = [ ( 'id', value ) ]
  905. ListChanges.append(('add', 0, DicResult[regN.group('slug')]['title'], value))
  906. elif regT:
  907. if not DicResult.has_key(regT.group('slug')):
  908. DicResult[regT.group('slug')] = dict()
  909. DicResult[regT.group('slug')]['title'] = value
  910. else:
  911. raise
  912. for opt in DBSession.query(TiersOpt).all():
  913. if DicResult.has_key(opt.slug_entity_type):
  914. found = filter( lambda (x,y): opt.uid==x,
  915. DicResult[opt.slug_entity_type].get('items', []))
  916. if not found:
  917. ListChanges.append(('remove', opt.uid, opt.entity_type, opt.entity_subtype))
  918. else:
  919. for tst in found:
  920. # Check changes on Cat Name
  921. if DicResult[opt.slug_entity_type]['title']!=opt.entity_type or \
  922. tst[1]!=opt.entity_subtype:
  923. ListChanges.append(('changed', opt.uid,
  924. DicResult[opt.slug_entity_type]['title'],
  925. tst[1]))
  926. else:
  927. ListChanges.append(('remove', opt.uid, opt.entity_type, opt.entity_subtype))
  928. # Do The change
  929. for action, uid, entity, subentity in ListChanges:
  930. if action=="changed":
  931. opt = TiersOpt.by_id(uid)
  932. opt.entity_type = entity
  933. opt.entity_subtype = subentity
  934. elif action=="remove":
  935. opt = TiersOpt.by_id(uid)
  936. DBSession.delete(opt)
  937. elif action=="add":
  938. opt = TiersOpt()
  939. opt.entity_type = entity
  940. opt.entity_subtype = subentity
  941. DBSession.add(opt)
  942. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  943. 'logged_in':request.authenticated_userid, 'TiersOpt':TiersOpt }
  944. return MainTab
  945. @view_config(route_name='show_user', renderer="jm2l:templates/view_user.mako")
  946. def show_user(request):
  947. user_slug = request.matchdict.get('user_slug', None)
  948. # Query database
  949. DispUser = User.by_slug(user_slug)
  950. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  951. 'DispUser':DispUser, 'logged_in':request.authenticated_userid }
  952. return MainTab
  953. #@view_config(route_name='link_user_entity')
  954. def link_user_entity(request):
  955. uid = int(request.matchdict.get('uid', -1))
  956. year = int(request.matchdict.get('year', -1))
  957. user_id = int(request.matchdict.get('uid', -1))
  958. TheTiers = Tiers.by_id(uid)
  959. if TheTiers is None:
  960. raise HTTPNotFound()
  961. return HTTPFound(location=request.route_url('edit_entity', uid=uid) )
  962. #@view_config(route_name='link_role_entity')
  963. def link_role_entity(request):
  964. uid = int(request.matchdict.get('uid', -1))
  965. year = int(request.matchdict.get('year', -1))
  966. role_id = int(request.matchdict.get('role_id', -1))
  967. TheTiers = Tiers.by_id(uid)
  968. if TheTiers is None:
  969. raise HTTPNotFound()
  970. return HTTPFound(location=request.route_url('edit_entity', uid=uid) )
  971. @notfound_view_config()
  972. def notfound(reason, request):
  973. request.response.status = 404
  974. return render_to_response('jm2l:templates/Errors/404.mak', { "reason":reason },
  975. request=request)
  976. @forbidden_view_config()
  977. def forbidden(reason, request):
  978. return Response('forbidden')
  979. request.response.status = 404
  980. return render_to_response('jm2l:templates/Errors/404.mak', { "reason":reason },
  981. request=request)