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.
 
 
 
 
 

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