Fix datepicker arrows style on hover
[cds-indico.git] / indico / MaKaC / webinterface / rh / categoryMod.py
blob0869f8d045b7e674a8a78db96f3cbdb36915dc95
1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from flask import request
18 import tempfile
20 import MaKaC.webinterface.locators as locators
21 import MaKaC.webinterface.urlHandlers as urlHandlers
22 import MaKaC.webinterface.pages.category as category
23 from MaKaC.webinterface.user import UserListModificationBase
24 from indico.core.config import Config
25 from MaKaC.common.utils import validMail
26 from MaKaC.webinterface.rh.base import RHModificationBaseProtected
27 from MaKaC.errors import MaKaCError, FormValuesError, NotFoundError
28 import MaKaC.conference as conference
30 from indico.modules.users.legacy import AvatarUserWrapper
31 from indico.modules.groups.legacy import GroupWrapper
32 from indico.util.i18n import _
35 class RHCategModifBase( RHModificationBaseProtected ):
37 def _checkProtection(self):
38 if self._target.canModify( self.getAW() ):
39 RHModificationBaseProtected._checkProtection(self)
40 return
41 else:
42 self._doProcess = False
43 self._redirect(urlHandlers.UHCategoryDisplay.getURL(self._target))
45 def _checkParams(self, params):
46 l = locators.CategoryWebLocator(params)
47 self._target = l.getObject()
48 if self._target is None:
49 raise NotFoundError(_("The category with id '{}' does not exist or has been deleted").format(
50 params["categId"]),
51 title=_("Category not found"))
54 class RHCategoryModification(RHCategModifBase):
55 _uh = urlHandlers.UHCategoryModification
57 def _process(self):
58 p = category.WPCategoryModification(self, self._target)
59 return p.display()
62 class RHCategoryDataModif( RHCategModifBase ):
63 _uh = urlHandlers.UHCategoryDataModif
65 def _process( self ):
66 p = category.WPCategoryDataModification( self, self._target )
67 return p.display()
70 class RHCategoryPerformModification( RHCategModifBase ):
71 _uh = urlHandlers.UHCategoryPerformModification
73 def _checkParams(self, params):
74 RHCategModifBase._checkParams(self, params)
75 if params.get("name", "").strip() =="":
76 raise FormValuesError("Please, provide a name for the new subcategory")
78 def _getNewTempFile( self ):
79 cfg = Config.getInstance()
80 tempPath = cfg.getUploadedFilesTempDir()
81 tempFileName = tempfile.mkstemp( suffix="Indico.tmp", dir = tempPath )[1]
82 return tempFileName
84 def _saveFileToTemp(self, fs):
85 fileName = self._getNewTempFile()
86 fs.save(fileName)
87 return fileName
89 def _process( self):
90 params = self._getRequestParams()
92 if not "cancel" in params:
93 if (params.get("subcats","")):
94 subcat=True
95 else:
96 subcat=False
97 if (params.get("modifyConfTZ","")):
98 modifyConfTZ=True
99 else:
100 modifyConfTZ=False
101 tz = params.get("defaultTimezone", "UTC")
102 self._target.setTimezone( tz )
103 if modifyConfTZ:
104 self._target.changeConfTimezones( tz )
106 if params.get("name", "") != self._target.getName():
107 self._target.setName( params.get("name", "") )
109 self._target.setDescription( params.get("description", "") )
110 self._target.setDefaultStyle("simple_event",params.get("defaultSimpleEventStyle", ""),subcat )
111 self._target.setDefaultStyle("meeting",params.get("defaultMeetingStyle", ""),subcat)
112 if self._target.getVisibility() != int(params.get("visibility",999)):
113 self._target.setVisibility(params.get("visibility",999))
114 if self._getUser().isAdmin():
115 self._target.setSuggestionsDisabled('disableSuggestions' in request.form)
116 if "delete" in params and self._target.getIcon() is not None:
117 self._target.removeIcon()
118 if "icon" in params and type(params["icon"]) != str and \
119 params["icon"].filename.strip() != "":
120 if not hasattr(self, "_filePath"):
121 # do not save the file again if it has already been done (db conflicts)
122 self._filePath = self._saveFileToTemp(params["icon"])
123 self._tempFilesToDelete.append(self._filePath)
124 self._fileName = params["icon"].filename
126 f = conference.LocalFile()
127 f.setName( "Icon" )
128 f.setDescription( "This is the icon for the category" )
129 f.setFileName( self._fileName )
130 f.setFilePath( self._filePath )
131 self._target.setIcon( f )
132 if "tasksAllowed" in params :
133 if params["tasksAllowed"] == "allowed" :
134 self._target.setTasksAllowed()
135 else :
136 self._target.setTasksForbidden()
138 self._redirect( urlHandlers.UHCategoryModification.getURL( self._target ) )
141 class RHCategoryTaskOption( RHCategModifBase ):
142 _uh = urlHandlers.UHCategoryTasksOption
144 def _process( self ):
146 if self._target.tasksAllowed() :
147 self._target.setTasksForbidden()
148 else :
149 self._target.setTasksAllowed()
151 self._redirect( urlHandlers.UHCategoryModification.getURL( self._target ) )
155 class RHCategoryAC( RHCategModifBase ):
156 _uh = urlHandlers.UHCategModifAC
158 def _process( self ):
159 p = category.WPCategModifAC( self, self._target )
160 return p.display()
163 class RHCategoryTools( RHCategModifBase ):
164 _uh = urlHandlers.UHCategModifTools
166 def _process( self ):
167 p = category.WPCategModifTools( self, self._target )
168 return p.display()
171 class RHCategoryTasks( RHCategModifBase ):
172 _uh = urlHandlers.UHCategModifTasks
174 def _process( self ):
175 p = category.WPCategModifTasks( self, self._target )
176 return p.display()
179 class RHCategoryTasksAction( RHCategModifBase ):
180 _uh = urlHandlers.UHCategModifTasksAction
182 def _process( self ):
183 params = self._getRequestParams()
185 if params.get("accessVisibility","") == _("PRIVATE") :
186 self._target.setTasksPrivate()
187 elif params.get("accessVisibility","") == _("PUBLIC") :
188 self._target.setTasksPublic()
189 else :
190 pass
192 if params.get("commentVisibility","") == _("PRIVATE") :
193 self._target.setTasksCommentPrivate()
194 elif params.get("commentVisibility","") == _("PUBLIC") :
195 self._target.setTasksCommentPublic()
196 else :
197 pass
199 if params.get("taskAccessAction","") == "Add":
200 chosen = params.get("accessChosen",None)
201 if chosen is not None and chosen != "" :
202 person = self._findPerson(chosen)
203 if person is not None :
204 self._target.addTasksAccessPerson(person)
205 elif params.get("taskAccessAction","") == "New":
206 pass
207 elif params.get("taskAccessAction","") == "Remove":
208 chosen = self._normaliseListParam(params.get("access", []))
209 for c in chosen :
210 self._target.removeTasksAccessPerson(int(c))
211 else :
212 pass
214 if params.get("taskCommentAction","") == "Add":
215 chosen = params.get("commentChosen",None)
216 if chosen is not None and chosen != "" :
217 person = self._findPerson(chosen)
218 if person is not None :
219 self._target.addTasksCommentator(person)
220 elif params.get("taskCommentAction","") == "New":
221 pass
222 elif params.get("taskCommentAction","") == "Remove":
223 chosen = self._normaliseListParam(params.get("commentator", []))
224 for c in chosen :
225 self._target.removeTasksCommentator(int(c))
226 else :
227 pass
230 if params.get("taskManagerAction","") == "Add":
231 chosen = params.get("managerChosen",None)
232 if chosen is not None and chosen != "" :
233 person = self._findPerson(chosen)
234 if person is not None :
235 self._target.addTasksManager(person)
236 elif params.get("taskManagerAction","") == "New":
237 pass
238 elif params.get("taskManagerAction","") == "Remove":
239 chosen = self._normaliseListParam(params.get("manager", []))
240 for c in chosen :
241 self._target.removeTasksManager(int(c))
242 else :
243 pass
246 p = category.WPCategModifTasks( self, self._target )
247 return p.display()
249 def _findPerson(self, idString):
250 if idString is None or idString == "" :
251 return None
252 if idString[0] == "c" :
253 return self.getTasksCommentator(int(idString[1:]))
254 elif idString[0] == "a" :
255 return self._target.getTasksAccessPerson(int(idString[1:]))
257 index = idString.find("-")
258 eventId = idString[1:index]
259 personId = idString[index+1:]
261 if idString[0] == "h" :
262 return self._target.getConferenceById(eventId).getChairById(personId)
263 elif idString[0] == "m" :
264 return self._target.getConferenceById(eventId).getManagerList()[int(personId)]
265 elif idString[0] == "p" :
266 return self._target.getConferenceById(eventId).getParticipation().getParticipantById(personId)
268 return None
270 class RHCategoryCreation( RHCategModifBase ):
271 _uh = urlHandlers.UHCategoryCreation
273 def _process( self ):
274 p = category.WPCategoryCreation( self, self._target )
275 return p.display()
278 class RHCategoryPerformCreation( RHCategModifBase ):
279 _uh = urlHandlers.UHCategoryPerformCreation
281 def _checkParams(self, params):
282 RHCategModifBase._checkParams(self, params)
283 if params.get("name", "").strip() =="" and not ("cancel" in params):
284 raise FormValuesError("Please, provide a name for the new subcategory")
286 def _process( self ):
287 params = self._getRequestParams()
288 if not ("cancel" in params):
290 categAccessProtection = params.get("categProtection", "inherit")
292 if categAccessProtection == "private" :
293 protection = 1
294 elif categAccessProtection == "public" :
295 protection = -1
296 else:
297 protection = 0
299 nc = self._target.newSubCategory(protection)
301 nc.setTimezone( params.get("defaultTimezone"))
302 nc.setName( params.get("name", "") )
303 nc.setDescription( params.get("description", "") )
304 nc.setDefaultStyle("simple_event",params.get("defaultSimpleEventStyle", "") )
305 nc.setDefaultStyle("meeting",params.get("defaultMeetingStyle", "") )
307 if protection == 1:
308 allowedUsers = self._getAllowedUsers(params)
309 if allowedUsers :
310 for person in allowedUsers :
311 if isinstance(person, (AvatarUserWrapper, GroupWrapper)):
312 nc.grantAccess(person)
314 self._redirect( urlHandlers.UHCategoryModification.getURL( self._target ) )
317 def _getAllowedUsers(self, params):
319 auAvatars = []
320 from MaKaC.services.interface.rpc import json
321 allowedUsersDict = json.decode(params.get("allowedUsers"))
322 if allowedUsersDict :
323 auAvatars, auNewUsers, auEditedAvatars = UserListModificationBase.retrieveUsers({"allowedUserList":allowedUsersDict}, "allowedUserList")
325 return auAvatars
328 class _ActionSubCategDeletion:
330 def __init__( self, rh, target, selCategs ):
331 self._rh = rh
332 self._target = target
333 self._categs = selCategs
335 def askConfirmation( self, params ):
336 p = category.WPSubCategoryDeletion( self._rh, self._target )
337 return p.display( subCategs=self._categs )
339 def perform( self ):
340 for categ in self._categs:
341 for manager in categ.getManagerList():
342 categ.revokeModification(manager)
343 categ.delete()
345 class _ActionSortCategories:
347 def __init__( self, rh ):
348 self._rh = rh
350 def askConfirmation( self, params ):
351 return ""
353 def perform(self):
354 cl = self._rh._target.getSubCategoryList()
355 cl.sort(key=lambda c: c.getTitle().lower())
356 for categ in cl:
357 categ.setOrder(cl.index(categ))
359 class _ActionSubCategMove:
361 def __init__( self, rh, newpos, oldpos ):
362 self._rh = rh
363 self._newpos = int(newpos)
364 self._oldpos = int(oldpos)
366 def askConfirmation( self, params ):
367 return ""
369 def perform(self):
370 cl = self._rh._target.getSubCategoryList()
371 order = 0
372 movedcateg = cl[self._oldpos]
373 del cl[self._oldpos]
374 cl.insert(self._newpos,movedcateg)
375 for categ in cl:
376 categ.setOrder(cl.index(categ))
378 class _ActionSubCategReallocation:
380 def __init__( self, rh, target, selCategs ):
381 self._rh = rh
382 self._target = target
383 self._categs = selCategs
385 def askConfirmation( self, params ):
386 p = category.WPCategoryReallocation( self._rh, self._target )
387 params["subCategs"] = self._categs
388 return p.display( **params )
390 def perform( self ):
391 #check if the current user has modification privileges on the
392 # destination category
393 if not self._target.canModify( self._rh.getAW() ):
394 raise MaKaCError( _("cannot reallocate selected categoried to the selected destination because you are not authorised to modify the destination category"))
395 for categ in self._categs:
396 categ.move( self._target )
399 class RHCategoryActionSubCategs( RHCategModifBase ):
400 _uh = urlHandlers.UHCategoryActionSubCategs
402 def _checkParams( self, params ):
403 RHCategModifBase._checkParams( self, params )
404 categIdList = self._normaliseListParam(params.get("selectedCateg", []))
405 self._categs = []
406 self._confirmation = params.has_key("confirm")
407 if "cancel" in params:
408 return
409 cm = conference.CategoryManager()
410 for categId in categIdList:
411 self._categs.append( cm.getById( categId ) )
412 self._action = _ActionSubCategDeletion( self, self._target, self._categs )
413 if params.has_key("reallocate"):
414 self._action = _ActionSubCategReallocation( self, self._target, self._categs )
415 if params.has_key("oldpos") and params["oldpos"]!='':
416 self._confirmation = 1
417 self._action = _ActionSubCategMove( self, params['newpos'+params['oldpos']], params['oldpos'] )
418 if params.has_key("sort"):
419 self._confirmation = 1
420 self._action = _ActionSortCategories( self )
422 def _process( self ):
423 if not self._categs:
424 if self._confirmation:
425 #Move category
426 self._action.perform()
427 else:
428 if self._confirmation:
429 #remove, reallocate
430 self._action.perform()
431 else:
432 return self._action.askConfirmation(self._getRequestParams())
433 self._redirect(urlHandlers.UHCategoryModification.getURL(self._target))
436 class _ActionConferenceDeletion:
438 def __init__(self, rh, target, selConfs):
439 self._rh = rh
440 self._target = target
441 self._confs = selConfs
443 def perform(self, confs):
444 for event in confs:
445 event.delete()
447 def askConfirmation(self, params):
448 p = category.WPConferenceDeletion(self._rh, self._target)
449 return p.display(events=self._confs)
452 class _ActionConferenceReallocation:
454 def __init__( self, rh, srcCateg, selConfs, target):
455 self._rh = rh
456 self._categ = srcCateg
457 self._confs = selConfs
458 self._target=target
460 def askConfirmation( self, params ):
461 p = category.WPConferenceReallocation( self._rh, self._categ )
462 params["confs"] = self._confs
463 return p.display( **params )
465 def perform(self, confs):
466 # TODO: check if the current user can create conferences on the destination category
467 if not self._confs:
468 self._confs = confs
469 for conf in self._confs:
470 if self._categ == conf.getOwner():
471 self._categ.moveConference(conf, self._target)
474 class RHCategoryActionConferences(RHCategModifBase):
475 _uh = urlHandlers.UHCategoryActionConferences
477 def _checkParams( self, params ):
478 RHCategModifBase._checkParams( self, params )
479 confIdList = self._normaliseListParam(params.get("selectedConf", []))
480 self._confs = []
481 self._confirmation = params.has_key("confirm")
482 if "cancel" in params:
483 return
484 ch = conference.ConferenceHolder()
485 for confId in confIdList:
486 self._confs.append( ch.getById( confId ) )
487 self._action = _ActionConferenceDeletion( self, self._target, self._confs, )
488 if params.has_key("reallocate"):
489 self._srcCateg = self._target
490 if self._confirmation:
491 cm = conference.CategoryManager()
492 self._srcCateg = cm.getById( params["srcCategId"] )
493 self._action = _ActionConferenceReallocation( self, self._srcCateg, self._confs, self._target )
495 def _process( self ):
496 if self._confirmation:
497 self._action.perform(self._confs)
498 self._redirect( urlHandlers.UHCategoryModification.getURL( self._target ) )
499 if not self._confs:
500 self._redirect( urlHandlers.UHCategoryModification.getURL( self._target ) )
501 else:
502 return self._action.askConfirmation( self._getRequestParams() )
505 class RHCategorySetVisibility( RHCategModifBase ):
506 _uh = urlHandlers.UHCategorySetVisibility
508 def _process( self ):
509 params = self._getRequestParams()
510 if params.has_key("changeToPrivate"):
511 self._target.setProtection( 1 )
512 elif params.has_key("changeToInheriting"):
513 self._target.setProtection( 0 )
514 elif params.has_key("changeToPublic"):
515 # The 'Home' category is handled as a special case.
516 # We maintain the illusion for the user of it being either
517 # private or public, but actually it can be either private
518 # or inheriting for legacy reasons.
519 if params["type"] == "Home":
520 self._target.setProtection( 0 )
521 else :
522 self._target.setProtection( -1 )
523 self._redirect( urlHandlers.UHCategModifAC.getURL( self._target ) )
526 class RHCategorySetConfControl( RHCategModifBase ):
527 _uh = urlHandlers.UHCategorySetConfCreationControl
529 def _process( self ):
530 params = self._getRequestParams()
531 if "RESTRICT" in self._getRequestParams():
532 self._target.restrictConferenceCreation()
533 else:
534 self._target.allowConferenceCreation()
535 self._redirect( urlHandlers.UHCategModifAC.getURL( self._target ) )
538 class RHCategorySetNotifyCreation( RHCategModifBase ):
539 _uh = urlHandlers.UHCategorySetNotifyCreation
541 def _checkParams(self, params):
542 RHCategModifBase._checkParams(self, params)
543 self._emailList = params.get("notifyCreationList","")
544 if self._emailList.strip() != "" and not validMail(self._emailList):
545 raise FormValuesError(_("The email list contains invalid e-mail addresses or invalid separator"))
547 def _process( self ):
548 self._target.setNotifyCreationList(self._emailList)
549 self._redirect( urlHandlers.UHCategModifAC.getURL( self._target ) )
552 class RHCategoryDeletion(RHCategModifBase):
553 _uh = urlHandlers.UHCategoryDeletion
555 def _checkParams( self, params ):
556 RHCategModifBase._checkParams( self, params )
557 self._cancel = False
558 if "cancel" in params:
559 self._cancel = True
560 self._confirmation = params.has_key("confirm")
562 def _perform( self ):
563 self._target.delete(1)
565 def _process( self ):
566 if self._cancel:
567 self._redirect( urlHandlers.UHCategModifTools.getURL( self._target ) )
568 elif self._confirmation:
569 owner = self._target.getOwner()
570 self._perform()
571 self._redirect(urlHandlers.UHCategoryModification.getURL(owner))
572 else:
573 p = category.WPCategoryDeletion(self, self._target)
574 return p.display()