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.
 
 
 
 
 

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