Le repo des sources pour le site web des JM2L
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 

1855 Zeilen
82 KiB

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