app/soc/views/models/student_proposal.py
changeset 1613 59e5cc89e509
parent 1584 d8ba8c917f37
child 1620 45f4e9cd9100
equal deleted inserted replaced
1612:09bccdf6bdec 1613:59e5cc89e509
    28 from django import forms
    28 from django import forms
    29 from django import http
    29 from django import http
    30 
    30 
    31 from soc.logic import cleaning
    31 from soc.logic import cleaning
    32 from soc.logic import dicts
    32 from soc.logic import dicts
       
    33 from soc.logic.models import mentor as mentor_logic
    33 from soc.logic.models import organization as org_logic
    34 from soc.logic.models import organization as org_logic
       
    35 from soc.logic.models import org_admin as org_admin_logic
    34 from soc.logic.models import student as student_logic
    36 from soc.logic.models import student as student_logic
    35 from soc.logic.models import user as user_logic
    37 from soc.logic.models import user as user_logic
       
    38 from soc.views import helper
       
    39 from soc.views import out_of_band
    36 from soc.views.helper import access
    40 from soc.views.helper import access
    37 from soc.views.helper import decorators
    41 from soc.views.helper import decorators
    38 from soc.views.helper import dynaform
    42 from soc.views.helper import dynaform
    39 from soc.views.helper import params as params_helper
    43 from soc.views.helper import params as params_helper
    40 from soc.views.helper import redirects
    44 from soc.views.helper import redirects
       
    45 from soc.views.helper import responses
    41 from soc.views.helper import widgets
    46 from soc.views.helper import widgets
    42 from soc.views.models import base
    47 from soc.views.models import base
    43 from soc.views.models import student as student_view
    48 from soc.views.models import student as student_view
    44 
    49 
    45 import soc.logic.models.student_proposal
    50 import soc.logic.models.student_proposal
    74     rights['list_self'] = [
    79     rights['list_self'] = [
    75         ('checkIsStudent', ['scope_path', ['active', 'inactive']])]
    80         ('checkIsStudent', ['scope_path', ['active', 'inactive']])]
    76     rights['apply'] = [
    81     rights['apply'] = [
    77         ('checkIsStudent', ['scope_path', ['active']]),
    82         ('checkIsStudent', ['scope_path', ['active']]),
    78         ('checkCanStudentPropose', 'scope_path')]
    83         ('checkCanStudentPropose', 'scope_path')]
       
    84     # TODO(ljvderijk) access check for review view
       
    85     rights['review'] = ['checkIsDeveloper']
    79 
    86 
    80     new_params = {}
    87     new_params = {}
    81     new_params['logic'] = soc.logic.models.student_proposal.logic
    88     new_params['logic'] = soc.logic.models.student_proposal.logic
    82     new_params['rights'] = rights
    89     new_params['rights'] = rights
    83     new_params['name'] = "Student Proposal"
    90     new_params['name'] = "Student Proposal"
    96         (r'^%(url_name)s/(?P<access_type>list_self)/%(scope)s$',
   103         (r'^%(url_name)s/(?P<access_type>list_self)/%(scope)s$',
    97         'soc.views.models.%(module_name)s.list_self',
   104         'soc.views.models.%(module_name)s.list_self',
    98         'List my %(name_plural)s'),
   105         'List my %(name_plural)s'),
    99         (r'^%(url_name)s/(?P<access_type>list_orgs)/%(scope)s$',
   106         (r'^%(url_name)s/(?P<access_type>list_orgs)/%(scope)s$',
   100         'soc.views.models.%(module_name)s.list_orgs',
   107         'soc.views.models.%(module_name)s.list_orgs',
   101         'List my %(name_plural)s')
   108         'List my %(name_plural)s'),
       
   109         (r'^%(url_name)s/(?P<access_type>review)/%(key_fields)s$',
       
   110         'soc.views.models.%(module_name)s.review',
       
   111         'Review %(name)s'),
   102     ]
   112     ]
   103 
   113 
   104     new_params['extra_django_patterns'] = patterns
   114     new_params['extra_django_patterns'] = patterns
   105 
   115 
   106     new_params['extra_dynaexclude'] = ['org', 'program', 'score',
   116     new_params['extra_dynaexclude'] = ['org', 'program', 'score',
   107                                        'status', 'mentor', 'link_id',]
   117                                        'status', 'mentor', 'link_id',
       
   118                                        'possible_mentors']
   108 
   119 
   109     new_params['create_extra_dynaproperties'] = {
   120     new_params['create_extra_dynaproperties'] = {
   110         'content': forms.fields.CharField(required=True,
   121         'content': forms.fields.CharField(required=True,
   111             widget=widgets.FullTinyMCE(attrs={'rows': 25, 'cols': 100})),
   122             widget=widgets.FullTinyMCE(attrs={'rows': 25, 'cols': 100})),
   112         'scope_path': forms.CharField(widget=forms.HiddenInput,
   123         'scope_path': forms.CharField(widget=forms.HiddenInput,
   124             widget=widgets.ReadOnlyInput),
   135             widget=widgets.ReadOnlyInput),
   125         'link_id': forms.CharField(widget=forms.HiddenInput)
   136         'link_id': forms.CharField(widget=forms.HiddenInput)
   126         }
   137         }
   127 
   138 
   128     new_params['edit_template'] = 'soc/student_proposal/edit.html'
   139     new_params['edit_template'] = 'soc/student_proposal/edit.html'
       
   140     new_params['review_template'] = 'soc/student_proposal/review.html'
   129 
   141 
   130     params = dicts.merge(params, new_params)
   142     params = dicts.merge(params, new_params)
   131 
   143 
   132     super(View, self).__init__(params=params)
   144     super(View, self).__init__(params=params)
   133 
   145 
   147         dynaform=self._params['create_form'],
   159         dynaform=self._params['create_form'],
   148         dynaproperties=dynaproperties)
   160         dynaproperties=dynaproperties)
   149 
   161 
   150     params['student_create_form'] = student_create_form
   162     params['student_create_form'] = student_create_form
   151 
   163 
       
   164     # create the special form for mentors
       
   165     dynafields = [
       
   166         {'name': 'score',
       
   167          'base': forms.ChoiceField,
       
   168          'label': 'Score',
       
   169          'initial': 0,
       
   170          'required': False,
       
   171          'passthrough': ['initial', 'required', 'choices'],
       
   172          'choices': [(-4,'-4: Wow. This. Sucks.'),
       
   173                      (-3,'-3: Needs a lot of work'),
       
   174                      (-2,'-2: This is bad'),
       
   175                      (-1,'-1: I dont like this'),
       
   176                      (0,'0: No score'),
       
   177                      (1,'1: Might have potential'),
       
   178                      (2,'2: Good'),
       
   179                      (3,'3: Almost there'),
       
   180                      (4,'4: Made. Of. Awesome.')]
       
   181         },
       
   182         {'name': 'comment',
       
   183          'base': forms.CharField,
       
   184          'widget': forms.Textarea,
       
   185          'label': 'Comment',
       
   186          'required': False,
       
   187          },
       
   188         {'name': 'public',
       
   189          'base': forms.BooleanField,
       
   190          'label': 'Public comment',
       
   191          'initial': False,
       
   192          'required': False,
       
   193          },
       
   194          ]
       
   195 
       
   196     dynaproperties = params_helper.getDynaFields(dynafields)
       
   197 
       
   198     mentor_review_form = dynaform.newDynaForm(dynamodel=None, dynabase=helper.forms.BaseForm,
       
   199         dynainclude=None, dynaexclude=None, dynaproperties=dynaproperties)
       
   200     params['mentor_review_form'] = mentor_review_form
       
   201 
       
   202     # TODO see if autocomplete can be used for this field
       
   203     dynafields = [
       
   204       {'name': 'mentor',
       
   205        'base': forms.CharField,
       
   206        'label': 'Assign Mentor (Link ID)',
       
   207        'required': False
       
   208       },
       
   209       ]
       
   210 
       
   211     dynaproperties = params_helper.getDynaFields(dynafields)
       
   212 
       
   213     admin_review_form = dynaform.extendDynaForm(dynaform=mentor_review_form, dynaproperties=dynaproperties)
       
   214 
       
   215     params['admin_review_form'] = admin_review_form
   152 
   216 
   153   def _editGet(self, request, entity, form):
   217   def _editGet(self, request, entity, form):
   154     """See base.View._editGet().
   218     """See base.View._editGet().
   155     """
   219     """
   156 
   220 
   306     list_params = params.copy()
   370     list_params = params.copy()
   307     list_params['list_description'] = 'List of my %(name_plural)s' % list_params
   371     list_params['list_description'] = 'List of my %(name_plural)s' % list_params
   308 
   372 
   309     return self.list(request, access_type=access_type, page_name=page_name,
   373     return self.list(request, access_type=access_type, page_name=page_name,
   310                      params=list_params, filter=filter, **kwargs)
   374                      params=list_params, filter=filter, **kwargs)
       
   375 
       
   376 
       
   377   @decorators.merge_params
       
   378   @decorators.check_access
       
   379   def review(self, request, access_type,
       
   380              page_name=None, params=None, **kwargs):
       
   381     """View that allows Organization Admins and Mentors to review the proposal.
       
   382 
       
   383        For Args see base.View.public().
       
   384     """
       
   385 
       
   386     try:
       
   387         entity = self._logic.getFromKeyFieldsOr404(kwargs)
       
   388     except out_of_band.Error, error:
       
   389       return helper.responses.errorResponse(
       
   390           error, request, template=params['error_public'])
       
   391 
       
   392     # get the context for this webpage
       
   393     context = responses.getUniversalContext(request)
       
   394     responses.useJavaScript(context, params['js_uses_all'])
       
   395     context['page_name'] = page_name
       
   396 
       
   397     context['student_name'] = entity.scope.name()
       
   398 
       
   399     if entity.mentor:
       
   400       context['mentor_name'] = entity.mentor.name()
       
   401     else:
       
   402       context['mentor_name'] = "No mentor assigned"
       
   403 
       
   404     context['entity'] = entity
       
   405     context['entity_type'] = params['name']
       
   406     context['entity_type_url'] = params['url_name']
       
   407 
       
   408     # get the roles important for reviewing an application
       
   409     filter = {'user': user_logic.logic.getForCurrentAccount(),
       
   410         'scope': entity.org,
       
   411         'status': 'active',}
       
   412 
       
   413     org_admin_entity = org_admin_logic.logic.getForFields(filter, unique=True)
       
   414     mentor_entity = mentor_logic.logic.getForFields(filter, unique=True)
       
   415 
       
   416     # check if the current user is a mentor and wants to change his role for this app
       
   417     choice = request.GET.get('mentor')
       
   418     if mentor_entity and choice:
       
   419       self._adjustPossibleMentors(entity, mentor_entity, choice)
       
   420 
       
   421     # set the possible mentors in the context
       
   422     possible_mentors = entity.possible_mentors
       
   423 
       
   424     if not possible_mentors:
       
   425       context['possible_mentors'] = "None"
       
   426     else:
       
   427       mentor_names = []
       
   428 
       
   429       for mentor_key in possible_mentors:
       
   430         mentor = mentor_logic.logic.getFromKeyName(mentor_key.name())
       
   431         mentor_names.append(mentor.name())
       
   432 
       
   433       context['possible_mentors'] = ', '.join(mentor_names)
       
   434 
       
   435     # decide which form to use
       
   436     if org_admin_entity:
       
   437       form = params['admin_review_form']
       
   438     else:
       
   439       form = params['mentor_review_form']
       
   440 
       
   441     if request.method == 'POST':
       
   442       return self.reviewPost(request, context, params, entity,
       
   443                              form, org_admin_entity, mentor_entity, **kwargs)
       
   444     else:
       
   445       # request.method == 'GET'
       
   446       return self.reviewGet(request, context, params, entity,
       
   447                             form, org_admin_entity, mentor_entity, **kwargs)
       
   448 
       
   449   def reviewPost(self, request, context, params, entity, form,
       
   450                  org_admin, mentor, **kwargs):
       
   451     """Handles the POST request for the proposal review view.
       
   452 
       
   453     Args:
       
   454         entity: the student proposal entity
       
   455         form: the form to use in this view
       
   456         org_admin: org admin entity for the current user/proposal (iff available)
       
   457         mentor: mentor entity for the current user/proposal (iff available)
       
   458         rest: see base.View.public()
       
   459     """
       
   460     # populate the form using the POST data
       
   461     form = form(request.POST)
       
   462 
       
   463     if not form.is_valid():
       
   464       # return the invalid form response
       
   465       return self._constructResponse(request, entity=entity, context=context,
       
   466           form=form, params=params, template=params['review_template'])
       
   467 
       
   468     fields = form.cleaned_data
       
   469 
       
   470     if org_admin:
       
   471       # org admin found, try to adjust the assigned mentor
       
   472       self._adjustMentor(entity, fields['mentor'])
       
   473 
       
   474     is_public = fields['public']
       
   475     comment = fields['comment']
       
   476     given_score = int(fields['score'])
       
   477 
       
   478     if not is_public and given_score is not 0:
       
   479       # if it is not a public comment we use the score and display
       
   480       # an additional message in the comment
       
   481       new_score = given_score + entity.score
       
   482 
       
   483       name = 'Someone'
       
   484 
       
   485       if org_admin:
       
   486         name = org_admin.name()
       
   487       elif mentor:
       
   488         name = mentor.name()
       
   489 
       
   490       # TODO(ljvderijk) hook up comments
       
   491       comment = '%s has given %i points \n %s' %(name, given_score, comment)
       
   492 
       
   493       # update the proposal with the new score
       
   494       self._logic.updateEntityProperties(entity, {'score': new_score})
       
   495 
       
   496     # redirect to the same page
       
   497     return http.HttpResponseRedirect('')
       
   498 
       
   499   def reviewGet(self, request, context, params, entity, form,
       
   500                  org_admin, mentor, **kwargs):
       
   501     """Handles the GET request for the proposal review view.
       
   502 
       
   503     Args:
       
   504         entity: the student proposal entity
       
   505         form: the form to use in this view
       
   506         org_admin: org admin entity for the current user/proposal (iff available)
       
   507         mentor: mentor entity for the current user/proposal (iff available)
       
   508         rest: see base.View.public()
       
   509     """
       
   510 
       
   511     initial = {}
       
   512 
       
   513     if org_admin and entity.mentor:
       
   514       initial['mentor'] = entity.mentor.link_id
       
   515 
       
   516     context['form'] = form(initial)
       
   517     template = params['review_template']
       
   518     context['mentor'] = mentor
       
   519 
       
   520     return responses.respond(request, template, context=context)
       
   521 
       
   522   def _adjustPossibleMentors(self, entity, mentor, choice):
       
   523     """Adjusts the possible mentors list for a proposal.
       
   524 
       
   525     Args:
       
   526       entity: Student Proposal entity
       
   527       mentor: Mentor entity
       
   528       choice: 1 means want to mentor, 0 do not want to mentor
       
   529     """
       
   530     possible_mentors = entity.possible_mentors
       
   531 
       
   532     if choice == '1':
       
   533       # add the mentor to possible mentors list if not already in
       
   534       if mentor.key() not in possible_mentors:
       
   535         possible_mentors.append(mentor.key())
       
   536         fields = {'possible_mentors': possible_mentors}
       
   537         self._logic.updateEntityProperties(entity, fields)
       
   538     elif choice == '0':
       
   539       # remove the mentor from the possible mentors list
       
   540       if mentor.key() in possible_mentors:
       
   541         possible_mentors.remove(mentor.key())
       
   542         fields = {'possible_mentors': possible_mentors}
       
   543         self._logic.updateEntityProperties(entity, fields)
       
   544 
       
   545   def _adjustMentor(self, entity, mentor_id):
       
   546     """Changes the mentor to the given link_id.
       
   547 
       
   548     Args:
       
   549       entity: Student Proposal entity
       
   550       mentor_id: Link ID of the mentor that needs to be assigned
       
   551                  Iff not given then removes the assigned mentor
       
   552     """
       
   553 
       
   554     if entity.mentor and entity.mentor.link_id == mentor_id:
       
   555       # no need to change
       
   556       return
       
   557 
       
   558     if mentor_id:
       
   559       # try to locate the mentor
       
   560       fields = {'link_id': mentor_id,
       
   561                 'scope': entity.org,
       
   562                 'status': 'active'}
       
   563 
       
   564       mentor_entity = mentor_logic.logic.getForFields(fields, unique=True)
       
   565 
       
   566       if not mentor_entity:
       
   567         # no mentor found, do not update
       
   568         return
       
   569     else:
       
   570       # reset to None
       
   571       mentor_entity = None
       
   572 
       
   573     # update the proposal
       
   574     properties = {'mentor': mentor_entity}
       
   575     self._logic.updateEntityProperties(entity, properties)
   311 
   576 
   312 view = View()
   577 view = View()
   313 
   578 
   314 admin = decorators.view(view.admin)
   579 admin = decorators.view(view.admin)
   315 apply = decorators.view(view.apply)
   580 apply = decorators.view(view.apply)
   318 edit = decorators.view(view.edit)
   583 edit = decorators.view(view.edit)
   319 list = decorators.view(view.list)
   584 list = decorators.view(view.list)
   320 list_orgs = decorators.view(view.listOrgs)
   585 list_orgs = decorators.view(view.listOrgs)
   321 list_self = decorators.view(view.listSelf)
   586 list_self = decorators.view(view.listSelf)
   322 public = decorators.view(view.public)
   587 public = decorators.view(view.public)
       
   588 review = decorators.view(view.review)
   323 export = decorators.view(view.export)
   589 export = decorators.view(view.export)
   324 pick = decorators.view(view.pick)
   590 pick = decorators.view(view.pick)