Added simple listing (no score, rank) for Student Proposals you are a mentor for.
[Melange.git] / app / soc / views / models / organization.py
bloba359b1463fbdc9823a439ac4be6e5e82badb9eaf
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.models import mentor as mentor_logic
36 from soc.logic.models import organization as org_logic
37 from soc.logic.models import org_admin as org_admin_logic
38 from soc.logic.models import org_app as org_app_logic
39 from soc.logic.models import user as user_logic
40 from soc.views import helper
41 from soc.views import out_of_band
42 from soc.views.helper import access
43 from soc.views.helper import decorators
44 from soc.views.helper import dynaform
45 from soc.views.helper import lists
46 from soc.views.helper import redirects
47 from soc.views.helper import widgets
48 from soc.views.models import group
50 import soc.models.organization
51 import soc.logic.models.organization
53 class View(group.View):
54 """View methods for the Organization model.
55 """
57 def __init__(self, params=None):
58 """Defines the fields and methods required for the base View class
59 to provide the user with list, public, create, edit and delete views.
61 Params:
62 original_params: a dict with params for this View
63 """
65 from soc.views.models import program as program_view
67 rights = access.Checker(params)
68 rights['any_access'] = ['allow']
69 rights['show'] = ['allow']
70 rights['create'] = ['checkIsDeveloper']
71 rights['edit'] = [('checkHasActiveRoleForKeyFieldsAsScope',
72 org_admin_logic.logic,),
73 ('checkGroupIsActiveForLinkId', org_logic.logic)]
74 rights['delete'] = ['checkIsDeveloper']
75 rights['home'] = ['allow']
76 rights['public_list'] = ['allow']
77 rights['apply_mentor'] = ['checkIsUser']
78 rights['list_requests'] = [('checkHasActiveRoleForKeyFieldsAsScope',
79 org_admin_logic.logic)]
80 rights['list_roles'] = [('checkHasActiveRoleForKeyFieldsAsScope',
81 org_admin_logic.logic)]
82 rights['applicant'] = [('checkIsApplicationAccepted',
83 org_app_logic.logic)]
84 rights['list_proposals'] = [('checkHasAny', [
85 [('checkHasActiveRoleForKeyFieldsAsScope', [org_admin_logic.logic]),
86 ('checkHasActiveRoleForKeyFieldsAsScope', [mentor_logic.logic])]
87 ])]
89 new_params = {}
90 new_params['logic'] = soc.logic.models.organization.logic
91 new_params['rights'] = rights
93 new_params['scope_view'] = program_view
94 new_params['scope_redirect'] = redirects.getCreateRedirect
96 new_params['name'] = "Organization"
97 new_params['url_name'] = "org"
98 new_params['document_prefix'] = "org"
99 new_params['sidebar_grouping'] = 'Organizations'
101 new_params['public_template'] = 'soc/organization/public.html'
102 new_params['list_row'] = 'soc/organization/list/row.html'
103 new_params['list_heading'] = 'soc/organization/list/heading.html'
105 new_params['application_logic'] = org_app_logic
106 new_params['group_applicant_url'] = True
107 new_params['sans_link_id_public_list'] = True
109 new_params['extra_dynaexclude'] = ['slots', 'nr_applications', 'nr_mentors']
111 patterns = []
113 patterns += [
114 (r'^%(url_name)s/(?P<access_type>apply_mentor)/%(scope)s$',
115 'soc.views.models.%(module_name)s.apply_mentor',
116 "List of all %(name_plural)s you can apply to"),
117 (r'^%(url_name)s/(?P<access_type>list_proposals)/%(key_fields)s$',
118 'soc.views.models.%(module_name)s.list_proposals',
119 "List of all Student Proposals for this %(name)s"),
122 new_params['extra_django_patterns'] = patterns
124 new_params['create_dynafields'] = [
125 {'name': 'link_id',
126 'base': forms.fields.CharField,
127 'label': 'Organization Link ID',
131 new_params['create_extra_dynaproperties'] = {
132 'scope_path': forms.CharField(widget=forms.HiddenInput,
133 required=True),
134 'description': forms.fields.CharField(
135 widget=helper.widgets.FullTinyMCE(
136 attrs={'rows': 25, 'cols': 100})),
137 'contrib_template': forms.fields.CharField(
138 widget=helper.widgets.FullTinyMCE(
139 attrs={'rows': 25, 'cols': 100})),
140 'clean_description': cleaning.clean_html_content('description'),
141 'clean_contrib_template': cleaning.clean_html_content(
142 'contrib_template'),
143 'clean_ideas': cleaning.clean_url('ideas'),
144 'clean': cleaning.validate_new_group('link_id', 'scope_path',
145 soc.logic.models.organization, org_app_logic)
148 new_params['edit_extra_dynaproperties'] = {
149 'clean': cleaning.clean_refs(new_params, ['home_link_id'])
152 params = dicts.merge(params, new_params)
154 super(View, self).__init__(params=params)
156 # create and store the special form for applicants
157 updated_fields = {
158 'link_id': forms.CharField(widget=widgets.ReadOnlyInput(),
159 required=False),
160 'clean_link_id': cleaning.clean_link_id('link_id')
163 applicant_create_form = dynaform.extendDynaForm(
164 dynaform = self._params['create_form'],
165 dynaproperties = updated_fields)
167 params['applicant_create_form'] = applicant_create_form
169 @decorators.merge_params
170 @decorators.check_access
171 def applyMentor(self, request, access_type,
172 page_name=None, params=None, **kwargs):
173 """Shows a list of all organizations and you can choose one to
174 apply to become a mentor.
176 Args:
177 request: the standard Django HTTP request object
178 access_type : the name of the access type which should be checked
179 page_name: the page name displayed in templates as page and header title
180 params: a dict with params for this View
181 kwargs: the Key Fields for the specified entity
184 list_params = params.copy()
185 list_params['list_action'] = (redirects.getRequestRedirectForRole, 'mentor')
186 list_params['list_description'] = ugettext('Choose an Organization which '
187 'you want to become a Mentor for.')
189 filter = {'scope_path': kwargs['scope_path'],
190 'status' : 'active'}
192 return self.list(request, access_type,
193 page_name, params=list_params, filter=filter)
195 @decorators.merge_params
196 @decorators.check_access
197 def listProposals(self, request, access_type,
198 page_name=None, params=None, **kwargs):
199 """Lists all proposals for the organization given in kwargs.
201 For params see base.View.public().
204 from soc.logic.models.ranker_root import logic as ranker_root_logic
205 from soc.models import student_proposal
206 from soc.views.helper import list_info as list_info_helper
207 from soc.views.models import student_proposal as student_proposal_view
209 try:
210 org_entity = self._logic.getFromKeyFieldsOr404(kwargs)
211 except out_of_band.Error, error:
212 return helper.responses.errorResponse(
213 error, request, template=params['error_public'])
215 context = {}
216 context['entity'] = org_entity
218 list_params = student_proposal_view.view.getParams().copy()
219 list_params['list_template'] = 'soc/student_proposal/list_for_org.html'
221 ranked_params = list_params.copy()# ranked proposals
222 ranked_params['list_row'] = ('soc/%(module_name)s/list/'
223 'detailed_row.html' % list_params)
224 ranked_params['list_heading'] = ('soc/%(module_name)s/list/'
225 'detailed_heading.html' % list_params)
226 ranked_params['list_description'] = '%s already under review sent to %s' % (
227 ranked_params['name_plural'], org_entity.name)
228 ranked_params['list_action'] = (redirects.getReviewRedirect, ranked_params)
230 # TODO(ljvderijk) once sorting with IN operator is fixed,
231 # make this list show more
232 filter = {'org': org_entity,
233 'status': 'pending'}
235 # order by descending score
236 order = ['-score']
238 prop_list = lists.getListContent(
239 request, ranked_params, filter, order=order, idx=0)
241 proposals = prop_list['data']
243 # get a list of scores
244 scores = [[proposal.score] for proposal in proposals]
246 # retrieve the ranker
247 fields = {'link_id': student_proposal.DEF_RANKER_NAME,
248 'scope': org_entity}
250 ranker_root = ranker_root_logic.getForFields(fields, unique=True)
251 ranker = ranker_root_logic.getRootFromEntity(ranker_root)
253 # retrieve the ranks for these scores
254 ranks = [rank+1 for rank in ranker.FindRanks(scores)]
256 # link the proposals to the rank
257 ranking = dict([i for i in itertools.izip(proposals, ranks)])
259 assigned_proposals = []
261 # only when the program allows allocations
262 # to be seen we should color the list
263 if org_entity.scope.allocations_visible:
264 # get the limit and offset for the list
265 _, offset = lists.getLimitAndOffset(request, 'offset_0', 'limit_0')
267 # determine the amount of proposals to color
268 to_color = max(0, org_entity.slots - offset)
269 assigned_proposals = proposals[0:to_color]
271 # show the amount of slots assigned on the webpage
272 context['slots_visible'] = True
274 # update the prop_list with the ranking and coloring information
275 prop_list['info'] = (list_info_helper.getStudentProposalInfo(ranking,
276 assigned_proposals), None)
278 # check if the current user is a mentor
279 user_entity = user_logic.logic.getForCurrentAccount()
281 fields = {'user': user_entity,
282 'scope': org_entity,}
283 mentor_entity = mentor_logic.logic.getForFields(fields, unique=True)
285 if mentor_entity:
286 mp_params = list_params.copy() # proposals mentored by current user
288 description = ugettext('List of %s sent to %s you are mentoring') % (
289 mp_params['name_plural'], org_entity.name)
290 mp_params['list_description'] = description
291 mp_params['list_action'] = (redirects.getReviewRedirect, mp_params)
293 filter = {'org': org_entity,
294 'mentor': mentor_entity,
295 'status': 'pending'}
297 mp_list = lists.getListContent(
298 request, mp_params, filter, idx=1, need_content=True)
300 new_params = list_params.copy() # new proposals
301 new_params['list_description'] = 'List of new %s sent to %s ' % (
302 new_params['name_plural'], org_entity.name)
303 new_params['list_action'] = (redirects.getReviewRedirect, new_params)
305 filter = {'org': org_entity,
306 'status': 'new'}
308 contents = []
309 new_list = lists.getListContent(
310 request, new_params, filter, idx=2, need_content=True)
312 ip_params = list_params.copy() # ineligible proposals
314 description = ugettext('List of ineligible %s sent to %s ') % (
315 ip_params['name_plural'], org_entity.name)
317 ip_params['list_description'] = description
318 ip_params['list_action'] = (redirects.getReviewRedirect, ip_params)
320 filter = {'org': org_entity,
321 'status': 'invalid'}
323 ip_list = lists.getListContent(
324 request, ip_params, filter, idx=3, need_content=True)
326 # fill contents with all the needed lists
327 if new_list != None:
328 contents.append(new_list)
330 contents.append(prop_list)
332 if mentor_entity and mp_list != None:
333 contents.append(mp_list)
335 if ip_list != None:
336 contents.append(ip_list)
338 # call the _list method from base to display the list
339 return self._list(request, list_params, contents, page_name, context)
341 @decorators.merge_params
342 @decorators.check_access
343 def listPublic(self, request, access_type, page_name=None,
344 params=None, filter=None, **kwargs):
345 """See base.View.list.
348 account = accounts.getCurrentAccount()
349 user = user_logic.logic.getForAccount(account) if account else None
351 try:
352 rights = self._params['rights']
353 rights.setCurrentUser(account, user)
354 rights.checkIsHost()
355 is_host = True
356 except out_of_band.Error:
357 is_host = False
359 new_params = {}
361 if is_host:
362 new_params['list_action'] = (redirects.getAdminRedirect, params)
363 else:
364 new_params['list_action'] = (redirects.getPublicRedirect, params)
365 # safe to merge them the wrong way around because of @merge_params
366 params = dicts.merge(new_params, params)
368 new_filter = {}
370 new_filter['scope_path'] = kwargs['scope_path']
371 new_filter['status'] = 'active'
372 filter = dicts.merge(filter, new_filter)
374 content = lists.getListContent(request, params, filter)
375 contents = [content]
377 return self._list(request, params, contents, page_name)
379 def _getExtraMenuItems(self, role_description, params=None):
380 """Used to create the specific Organization menu entries.
382 For args see group.View._getExtraMenuItems().
384 submenus = []
386 group_entity = role_description['group']
387 roles = role_description['roles']
389 if roles.get('org_admin') or roles.get('mentor'):
390 # add a link to view all the student proposals
391 submenu = (redirects.getListProposalsRedirect(group_entity, params),
392 "View all Student Proposals", 'any_access')
393 submenus.append(submenu)
396 if roles.get('org_admin'):
397 # add a link to the management page
398 submenu = (redirects.getListRolesRedirect(group_entity, params),
399 "Manage Admins and Mentors", 'any_access')
400 submenus.append(submenu)
402 # add a link to invite an org admin
403 submenu = (redirects.getInviteRedirectForRole(group_entity, 'org_admin'),
404 "Invite an Admin", 'any_access')
405 submenus.append(submenu)
407 # add a link to invite a member
408 submenu = (redirects.getInviteRedirectForRole(group_entity, 'mentor'),
409 "Invite a Mentor", 'any_access')
410 submenus.append(submenu)
412 # add a link to the request page
413 submenu = (redirects.getListRequestsRedirect(group_entity, params),
414 "List Requests and Invites", 'any_access')
415 submenus.append(submenu)
417 # add a link to the edit page
418 submenu = (redirects.getEditRedirect(group_entity, params),
419 "Edit Organization Profile", 'any_access')
420 submenus.append(submenu)
422 if roles.get('org_admin') or roles.get('mentor'):
423 submenu = (redirects.getCreateDocumentRedirect(group_entity, 'org'),
424 "Create a New Document", 'any_access')
425 submenus.append(submenu)
427 submenu = (redirects.getListDocumentsRedirect(group_entity, 'org'),
428 "List Documents", 'any_access')
429 submenus.append(submenu)
432 if roles.get('org_admin'):
433 # add a link to the resign page
434 submenu = (redirects.getManageRedirect(roles['org_admin'],
435 {'url_name': 'org_admin'}),
436 "Resign as Admin", 'any_access')
437 submenus.append(submenu)
439 # add a link to the edit page
440 submenu = (redirects.getEditRedirect(roles['org_admin'],
441 {'url_name': 'org_admin'}),
442 "Edit My Admin Profile", 'any_access')
443 submenus.append(submenu)
446 if roles.get('mentor'):
447 # add a link to the resign page
448 submenu = (redirects.getManageRedirect(roles['mentor'],
449 {'url_name' : 'mentor'}),
450 "Resign as Mentor", 'any_access')
451 submenus.append(submenu)
453 # add a link to the edit page
454 submenu = (redirects.getEditRedirect(roles['mentor'],
455 {'url_name': 'mentor'}),
456 "Edit My Mentor Profile", 'any_access')
457 submenus.append(submenu)
459 return submenus
462 view = View()
464 admin = decorators.view(view.admin)
465 applicant = decorators.view(view.applicant)
466 apply_mentor = decorators.view(view.applyMentor)
467 create = decorators.view(view.create)
468 delete = decorators.view(view.delete)
469 edit = decorators.view(view.edit)
470 home = decorators.view(view.home)
471 list = decorators.view(view.list)
472 list_proposals = decorators.view(view.listProposals)
473 list_public = decorators.view(view.listPublic)
474 list_requests = decorators.view(view.listRequests)
475 list_roles = decorators.view(view.listRoles)
476 public = decorators.view(view.public)
477 export = decorators.view(view.export)
478 pick = decorators.view(view.pick)