Fixed wrong import for list proposals view.
[Melange.git] / app / soc / views / models / organization.py
blob82a349a5dfab4def9ace5263b56076489ee6d3d4
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.student_proposal import logic 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 program_entity = entity.scope
395 if timeline_helper.isAfterEvent(program_entity.timeline,
396 'accepted_students_announced_deadline'):
397 ap_params = student_project_view.view.getParams().copy() # accepted projects
399 # define the list redirect action to show the notification
400 ap_params['list_action'] = (redirects.getPublicRedirect, ap_params)
401 ap_params['list_description'] = self.DEF_ACCEPTED_PROJECTS_MSG_FMT % (
402 entity.name)
403 ap_params['list_heading'] = 'soc/student_project/list/heading.html'
404 ap_params['list_row'] = 'soc/student_project/list/row.html'
406 # only show projects that have not failed
407 filter = {'scope': entity,
408 'status': ['accepted', 'mid_term_passed', 'passed']}
410 ap_list = lists.getListContent(request, ap_params, filter, idx=0,
411 need_content=True)
413 contents = []
415 if ap_list:
416 contents.append(ap_list)
418 # construct the list and put it into the context
419 context['list'] = soc.logic.lists.Lists(contents)
421 return super(View, self)._public(request=request,
422 entity=entity, context=context)
424 def _getExtraMenuItems(self, role_description, params=None):
425 """Used to create the specific Organization menu entries.
427 For args see group.View._getExtraMenuItems().
429 submenus = []
431 group_entity = role_description['group']
432 program_entity = group_entity.scope
433 roles = role_description['roles']
435 if roles.get('org_admin') or roles.get('mentor'):
436 # add a link to view all the student proposals
437 submenu = (redirects.getListProposalsRedirect(group_entity, params),
438 "View all Student Proposals", 'any_access')
439 submenus.append(submenu)
442 if roles.get('org_admin'):
443 # add a link to manage student projects after they have been announced
444 if timeline_helper.isAfterEvent(program_entity.timeline,
445 'accepted_students_announced_deadline'):
446 submenu = (redirects.getManageOverviewRedirect(group_entity,
447 {'url_name': 'student_project'}),
448 "Manage Student Projects", 'any_access')
449 submenus.append(submenu)
451 # add a link to the management page
452 submenu = (redirects.getListRolesRedirect(group_entity, params),
453 "Manage Admins and Mentors", 'any_access')
454 submenus.append(submenu)
456 # add a link to invite an org admin
457 submenu = (redirects.getInviteRedirectForRole(group_entity, 'org_admin'),
458 "Invite an Admin", 'any_access')
459 submenus.append(submenu)
461 # add a link to invite a member
462 submenu = (redirects.getInviteRedirectForRole(group_entity, 'mentor'),
463 "Invite a Mentor", 'any_access')
464 submenus.append(submenu)
466 # add a link to the request page
467 submenu = (redirects.getListRequestsRedirect(group_entity, params),
468 "List Requests and Invites", 'any_access')
469 submenus.append(submenu)
471 # add a link to the edit page
472 submenu = (redirects.getEditRedirect(group_entity, params),
473 "Edit Organization Profile", 'any_access')
474 submenus.append(submenu)
476 if roles.get('org_admin') or roles.get('mentor'):
477 submenu = (redirects.getCreateDocumentRedirect(group_entity, 'org'),
478 "Create a New Document", 'any_access')
479 submenus.append(submenu)
481 submenu = (redirects.getListDocumentsRedirect(group_entity, 'org'),
482 "List Documents", 'any_access')
483 submenus.append(submenu)
486 if roles.get('org_admin'):
487 # add a link to the resign page
488 submenu = (redirects.getManageRedirect(roles['org_admin'],
489 {'url_name': 'org_admin'}),
490 "Resign as Admin", 'any_access')
491 submenus.append(submenu)
493 # add a link to the edit page
494 submenu = (redirects.getEditRedirect(roles['org_admin'],
495 {'url_name': 'org_admin'}),
496 "Edit My Admin Profile", 'any_access')
497 submenus.append(submenu)
500 if roles.get('mentor'):
501 # add a link to the resign page
502 submenu = (redirects.getManageRedirect(roles['mentor'],
503 {'url_name' : 'mentor'}),
504 "Resign as Mentor", 'any_access')
505 submenus.append(submenu)
507 # add a link to the edit page
508 submenu = (redirects.getEditRedirect(roles['mentor'],
509 {'url_name': 'mentor'}),
510 "Edit My Mentor Profile", 'any_access')
511 submenus.append(submenu)
513 return submenus
516 view = View()
518 admin = decorators.view(view.admin)
519 applicant = decorators.view(view.applicant)
520 apply_mentor = decorators.view(view.applyMentor)
521 create = decorators.view(view.create)
522 delete = decorators.view(view.delete)
523 edit = decorators.view(view.edit)
524 home = decorators.view(view.home)
525 list = decorators.view(view.list)
526 list_proposals = decorators.view(view.listProposals)
527 list_public = decorators.view(view.listPublic)
528 list_requests = decorators.view(view.listRequests)
529 list_roles = decorators.view(view.listRoles)
530 public = decorators.view(view.public)
531 export = decorators.view(view.export)
532 pick = decorators.view(view.pick)