Fix user_self calling editGet with a wrong parameter
[Melange.git] / app / soc / views / models / organization.py
blobda6def30562216c85c2df256f84d1b47d4d34ec9
1 #!/usr/bin/python2.5
3 # Copyright 2008 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Views for Organizations.
18 """
20 __authors__ = [
21 '"Augie Fackler" <durin42@gmail.com>',
22 '"Sverre Rabbelier" <sverre@rabbelier.nl>',
23 '"Lennard de Rijk" <ljvderijk@gmail.com>',
27 import itertools
29 from django import forms
30 from django.utils.translation import ugettext
32 from soc.logic import cleaning
33 from soc.logic import dicts
34 from soc.logic import accounts
35 from soc.logic.helper import timeline as timeline_helper
36 from soc.logic.models import mentor as mentor_logic
37 from soc.logic.models import organization as org_logic
38 from soc.logic.models import org_admin as org_admin_logic
39 from soc.logic.models import org_app as org_app_logic
40 from soc.logic.models import user as user_logic
41 from soc.views import helper
42 from soc.views import out_of_band
43 from soc.views.helper import access
44 from soc.views.helper import decorators
45 from soc.views.helper import dynaform
46 from soc.views.helper import lists
47 from soc.views.helper import redirects
48 from soc.views.helper import widgets
49 from soc.views.models import group
51 import soc.models.organization
52 import soc.logic.models.organization
54 class View(group.View):
55 """View methods for the Organization model.
56 """
58 DEF_ACCEPTED_PROJECTS_MSG_FMT = ugettext("These projects have"
59 " been accepted into %s. You can learn more about"
60 " each project by visiting the links below.")
62 def __init__(self, params=None):
63 """Defines the fields and methods required for the base View class
64 to provide the user with list, public, create, edit and delete views.
66 Params:
67 original_params: a dict with params for this View
68 """
70 from soc.views.models import program as program_view
72 rights = access.Checker(params)
73 rights['any_access'] = ['allow']
74 rights['show'] = ['allow']
75 rights['create'] = ['checkIsDeveloper']
76 rights['edit'] = [('checkHasActiveRoleForKeyFieldsAsScope',
77 org_admin_logic.logic,),
78 ('checkGroupIsActiveForLinkId', org_logic.logic)]
79 rights['delete'] = ['checkIsDeveloper']
80 rights['home'] = ['allow']
81 rights['public_list'] = ['allow']
82 rights['apply_mentor'] = ['checkIsUser']
83 rights['list_requests'] = [('checkHasActiveRoleForKeyFieldsAsScope',
84 org_admin_logic.logic)]
85 rights['list_roles'] = [('checkHasActiveRoleForKeyFieldsAsScope',
86 org_admin_logic.logic)]
87 rights['applicant'] = [('checkIsApplicationAccepted',
88 org_app_logic.logic)]
89 rights['list_proposals'] = [('checkHasAny', [
90 [('checkHasActiveRoleForKeyFieldsAsScope', [org_admin_logic.logic]),
91 ('checkHasActiveRoleForKeyFieldsAsScope', [mentor_logic.logic])]
92 ])]
94 new_params = {}
95 new_params['logic'] = soc.logic.models.organization.logic
96 new_params['rights'] = rights
98 new_params['scope_view'] = program_view
99 new_params['scope_redirect'] = redirects.getCreateRedirect
101 new_params['name'] = "Organization"
102 new_params['url_name'] = "org"
103 new_params['document_prefix'] = "org"
104 new_params['sidebar_grouping'] = 'Organizations'
106 new_params['public_template'] = 'soc/organization/public.html'
107 new_params['list_row'] = 'soc/organization/list/row.html'
108 new_params['list_heading'] = 'soc/organization/list/heading.html'
109 new_params['home_template'] = 'soc/organization/home.html'
111 new_params['application_logic'] = org_app_logic
112 new_params['group_applicant_url'] = True
113 new_params['sans_link_id_public_list'] = True
115 new_params['extra_dynaexclude'] = ['slots', 'slots_calculated',
116 'nr_applications', 'nr_mentors']
118 patterns = []
120 patterns += [
121 (r'^%(url_name)s/(?P<access_type>apply_mentor)/%(scope)s$',
122 'soc.views.models.%(module_name)s.apply_mentor',
123 "List of all %(name_plural)s you can apply to"),
124 (r'^%(url_name)s/(?P<access_type>list_proposals)/%(key_fields)s$',
125 'soc.views.models.%(module_name)s.list_proposals',
126 "List of all Student Proposals for this %(name)s"),
129 new_params['extra_django_patterns'] = patterns
131 new_params['create_dynafields'] = [
132 {'name': 'link_id',
133 'base': forms.fields.CharField,
134 'label': 'Organization Link ID',
138 new_params['create_extra_dynaproperties'] = {
139 'scope_path': forms.CharField(widget=forms.HiddenInput,
140 required=True),
141 'description': forms.fields.CharField(
142 widget=helper.widgets.FullTinyMCE(
143 attrs={'rows': 25, 'cols': 100})),
144 'contrib_template': forms.fields.CharField(
145 widget=helper.widgets.FullTinyMCE(
146 attrs={'rows': 25, 'cols': 100})),
147 'clean_description': cleaning.clean_html_content('description'),
148 'clean_contrib_template': cleaning.clean_html_content(
149 'contrib_template'),
150 'clean_ideas': cleaning.clean_url('ideas'),
151 'clean': cleaning.validate_new_group('link_id', 'scope_path',
152 soc.logic.models.organization, org_app_logic)
155 new_params['edit_extra_dynaproperties'] = {
156 'clean': cleaning.clean_refs(new_params, ['home_link_id'])
159 params = dicts.merge(params, new_params)
161 super(View, self).__init__(params=params)
163 # create and store the special form for applicants
164 updated_fields = {
165 'link_id': forms.CharField(widget=widgets.ReadOnlyInput(),
166 required=False),
167 'clean_link_id': cleaning.clean_link_id('link_id')
170 applicant_create_form = dynaform.extendDynaForm(
171 dynaform = self._params['create_form'],
172 dynaproperties = updated_fields)
174 self._params['applicant_create_form'] = applicant_create_form
176 @decorators.merge_params
177 @decorators.check_access
178 def applyMentor(self, request, access_type,
179 page_name=None, params=None, **kwargs):
180 """Shows a list of all organizations and you can choose one to
181 apply to become a mentor.
183 Args:
184 request: the standard Django HTTP request object
185 access_type : the name of the access type which should be checked
186 page_name: the page name displayed in templates as page and header title
187 params: a dict with params for this View
188 kwargs: the Key Fields for the specified entity
191 list_params = params.copy()
192 list_params['list_action'] = (redirects.getRequestRedirectForRole, 'mentor')
193 list_params['list_description'] = ugettext('Choose an Organization which '
194 'you want to become a Mentor for.')
196 filter = {'scope_path': kwargs['scope_path'],
197 'status' : 'active'}
199 return self.list(request, access_type,
200 page_name, params=list_params, filter=filter)
202 @decorators.merge_params
203 @decorators.check_access
204 def listProposals(self, request, access_type,
205 page_name=None, params=None, **kwargs):
206 """Lists all proposals for the organization given in kwargs.
208 For params see base.View.public().
211 from soc.logic.models.ranker_root import logic as ranker_root_logic
212 from soc.logic.models import student_proposal as sp_logic
213 from soc.models import student_proposal
214 from soc.views.helper import list_info as list_info_helper
215 from soc.views.models import student_proposal as student_proposal_view
217 try:
218 org_entity = self._logic.getFromKeyFieldsOr404(kwargs)
219 except out_of_band.Error, error:
220 return helper.responses.errorResponse(
221 error, request, template=params['error_public'])
223 context = {}
224 context['entity'] = org_entity
226 list_params = student_proposal_view.view.getParams().copy()
227 list_params['list_template'] = 'soc/student_proposal/list_for_org.html'
228 list_params['list_key_order'] = [
229 'title', 'abstract', 'content', 'additional_info', 'mentor',
230 'possible_mentors', 'score', 'status', 'created_on',
231 'last_modified_on']
233 ranked_params = list_params.copy()# ranked proposals
234 ranked_params['list_row'] = ('soc/%(module_name)s/list/'
235 'detailed_row.html' % list_params)
236 ranked_params['list_heading'] = ('soc/%(module_name)s/list/'
237 'detailed_heading.html' % list_params)
238 ranked_params['list_description'] = '%s already under review sent to %s' % (
239 ranked_params['name_plural'], org_entity.name)
240 ranked_params['list_action'] = (redirects.getReviewRedirect, ranked_params)
242 # TODO(ljvderijk) once sorting with IN operator is fixed,
243 # make this list show more
244 filter = {'org': org_entity,
245 'status': 'pending'}
247 # order by descending score
248 order = ['-score']
250 prop_list = lists.getListContent(
251 request, ranked_params, filter, order=order, idx=0)
253 proposals = prop_list['data']
255 # get a list of scores
256 scores = [[proposal.score] for proposal in proposals]
258 # retrieve the ranker
259 fields = {'link_id': student_proposal.DEF_RANKER_NAME,
260 'scope': org_entity}
262 ranker_root = ranker_root_logic.getForFields(fields, unique=True)
263 ranker = ranker_root_logic.getRootFromEntity(ranker_root)
265 # retrieve the ranks for these scores
266 ranks = [rank+1 for rank in ranker.FindRanks(scores)]
268 # link the proposals to the rank
269 ranking = dict([i for i in itertools.izip(proposals, ranks)])
271 assigned_proposals = []
273 # only when the program allows allocations
274 # to be seen we should color the list
275 if org_entity.scope.allocations_visible:
276 assigned_proposals = sp_logic.getProposalsToBeAcceptedForOrg(org_entity)
278 # show the amount of slots assigned on the webpage
279 context['slots_visible'] = True
281 ranking_keys = dict([(k.key(),v) for k,v in ranking.iteritems()])
282 proposal_keys = [i.key() for i in assigned_proposals]
284 # update the prop_list with the ranking and coloring information
285 prop_list['info'] = (list_info_helper.getStudentProposalInfo(ranking_keys,
286 proposal_keys), None)
288 # check if the current user is a mentor
289 user_entity = user_logic.logic.getForCurrentAccount()
291 fields = {'user': user_entity,
292 'scope': org_entity,}
293 mentor_entity = mentor_logic.logic.getForFields(fields, unique=True)
295 if mentor_entity:
296 mp_params = list_params.copy() # proposals mentored by current user
298 description = ugettext('List of %s sent to %s you are mentoring') % (
299 mp_params['name_plural'], org_entity.name)
300 mp_params['list_description'] = description
301 mp_params['list_action'] = (redirects.getReviewRedirect, mp_params)
303 filter = {'org': org_entity,
304 'mentor': mentor_entity,
305 'status': 'pending'}
307 mp_list = lists.getListContent(
308 request, mp_params, filter, idx=1, need_content=True)
310 new_params = list_params.copy() # new proposals
311 new_params['list_description'] = 'List of new %s sent to %s ' % (
312 new_params['name_plural'], org_entity.name)
313 new_params['list_action'] = (redirects.getReviewRedirect, new_params)
315 filter = {'org': org_entity,
316 'status': 'new'}
318 contents = []
319 new_list = lists.getListContent(
320 request, new_params, filter, idx=2, need_content=True)
322 ip_params = list_params.copy() # ineligible proposals
324 description = ugettext('List of ineligible %s sent to %s ') % (
325 ip_params['name_plural'], org_entity.name)
327 ip_params['list_description'] = description
328 ip_params['list_action'] = (redirects.getReviewRedirect, ip_params)
330 filter = {'org': org_entity,
331 'status': 'invalid'}
333 ip_list = lists.getListContent(
334 request, ip_params, filter, idx=3, need_content=True)
336 # fill contents with all the needed lists
337 if new_list != None:
338 contents.append(new_list)
340 contents.append(prop_list)
342 if mentor_entity and mp_list != None:
343 contents.append(mp_list)
345 if ip_list != None:
346 contents.append(ip_list)
348 # call the _list method from base to display the list
349 return self._list(request, list_params, contents, page_name, context)
351 @decorators.merge_params
352 @decorators.check_access
353 def listPublic(self, request, access_type, page_name=None,
354 params=None, filter=None, **kwargs):
355 """See base.View.list.
358 account = accounts.getCurrentAccount()
359 user = user_logic.logic.getForAccount(account) if account else None
361 try:
362 rights = self._params['rights']
363 rights.setCurrentUser(account, user)
364 rights.checkIsHost()
365 is_host = True
366 except out_of_band.Error:
367 is_host = False
369 params = params.copy()
371 if is_host:
372 params['list_action'] = (redirects.getAdminRedirect, params)
373 else:
374 params['list_action'] = (redirects.getPublicRedirect, params)
376 new_filter = {}
378 new_filter['scope_path'] = kwargs['scope_path']
379 new_filter['status'] = 'active'
380 filter = dicts.merge(filter, new_filter)
382 content = lists.getListContent(request, params, filter)
383 contents = [content]
385 return self._list(request, params, contents, page_name)
387 def _public(self, request, entity, context):
388 """See base.View._public().
391 from soc.views.models import student_project as student_project_view
393 ap_params = student_project_view.view.getParams().copy() # accepted projects
395 # define the list redirect action to show the notification
396 ap_params['list_action'] = (redirects.getPublicRedirect, ap_params)
397 ap_params['list_description'] = self.DEF_ACCEPTED_PROJECTS_MSG_FMT % (
398 entity.name)
399 ap_params['list_heading'] = 'soc/student_project/list/heading.html'
400 ap_params['list_row'] = 'soc/student_project/list/row.html'
402 # only show projects that have not failed
403 filter = {'scope': entity,
404 'status': ['accepted', 'mid_term_passed', 'passed']}
406 ap_list = lists.getListContent(request, ap_params, filter, idx=0,
407 need_content=True)
409 contents = []
411 if ap_list:
412 contents.append(ap_list)
414 # construct the list and put it into the context
415 context['list'] = soc.logic.lists.Lists(contents)
417 return super(View, self)._public(request=request,
418 entity=entity, context=context)
420 def _getExtraMenuItems(self, role_description, params=None):
421 """Used to create the specific Organization menu entries.
423 For args see group.View._getExtraMenuItems().
425 submenus = []
427 group_entity = role_description['group']
428 program_entity = group_entity.scope
429 roles = role_description['roles']
431 if roles.get('org_admin') or roles.get('mentor'):
432 # add a link to view all the student proposals
433 submenu = (redirects.getListProposalsRedirect(group_entity, params),
434 "View all Student Proposals", 'any_access')
435 submenus.append(submenu)
438 if roles.get('org_admin'):
439 # add a link to manage student projects after they have been announced
440 if timeline_helper.isAfterEvent(program_entity.timeline,
441 'accepted_students_announced_deadline'):
442 submenu = (redirects.getManageOverviewRedirect(group_entity,
443 {'url_name': 'student_project'}),
444 "Manage Student Projects", 'any_access')
445 submenus.append(submenu)
447 # add a link to the management page
448 submenu = (redirects.getListRolesRedirect(group_entity, params),
449 "Manage Admins and Mentors", 'any_access')
450 submenus.append(submenu)
452 # add a link to invite an org admin
453 submenu = (redirects.getInviteRedirectForRole(group_entity, 'org_admin'),
454 "Invite an Admin", 'any_access')
455 submenus.append(submenu)
457 # add a link to invite a member
458 submenu = (redirects.getInviteRedirectForRole(group_entity, 'mentor'),
459 "Invite a Mentor", 'any_access')
460 submenus.append(submenu)
462 # add a link to the request page
463 submenu = (redirects.getListRequestsRedirect(group_entity, params),
464 "List Requests and Invites", 'any_access')
465 submenus.append(submenu)
467 # add a link to the edit page
468 submenu = (redirects.getEditRedirect(group_entity, params),
469 "Edit Organization Profile", 'any_access')
470 submenus.append(submenu)
472 if roles.get('org_admin') or roles.get('mentor'):
473 submenu = (redirects.getCreateDocumentRedirect(group_entity, 'org'),
474 "Create a New Document", 'any_access')
475 submenus.append(submenu)
477 submenu = (redirects.getListDocumentsRedirect(group_entity, 'org'),
478 "List Documents", 'any_access')
479 submenus.append(submenu)
482 if roles.get('org_admin'):
483 # add a link to the resign page
484 submenu = (redirects.getManageRedirect(roles['org_admin'],
485 {'url_name': 'org_admin'}),
486 "Resign as Admin", 'any_access')
487 submenus.append(submenu)
489 # add a link to the edit page
490 submenu = (redirects.getEditRedirect(roles['org_admin'],
491 {'url_name': 'org_admin'}),
492 "Edit My Admin Profile", 'any_access')
493 submenus.append(submenu)
496 if roles.get('mentor'):
497 # add a link to the resign page
498 submenu = (redirects.getManageRedirect(roles['mentor'],
499 {'url_name' : 'mentor'}),
500 "Resign as Mentor", 'any_access')
501 submenus.append(submenu)
503 # add a link to the edit page
504 submenu = (redirects.getEditRedirect(roles['mentor'],
505 {'url_name': 'mentor'}),
506 "Edit My Mentor Profile", 'any_access')
507 submenus.append(submenu)
509 return submenus
512 view = View()
514 admin = decorators.view(view.admin)
515 applicant = decorators.view(view.applicant)
516 apply_mentor = decorators.view(view.applyMentor)
517 create = decorators.view(view.create)
518 delete = decorators.view(view.delete)
519 edit = decorators.view(view.edit)
520 home = decorators.view(view.home)
521 list = decorators.view(view.list)
522 list_proposals = decorators.view(view.listProposals)
523 list_public = decorators.view(view.listPublic)
524 list_requests = decorators.view(view.listRequests)
525 list_roles = decorators.view(view.listRoles)
526 public = decorators.view(view.public)
527 export = decorators.view(view.export)
528 pick = decorators.view(view.pick)