Le repo des sources pour le site web des JM2L
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1268 lines
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)