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.
 
 
 
 
 

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