--- a/app/soc/views/models/student_project.py Tue Apr 07 08:44:56 2009 +0000
+++ b/app/soc/views/models/student_project.py Tue Apr 07 08:49:47 2009 +0000
@@ -29,10 +29,18 @@
from soc.logic import cleaning
from soc.logic import dicts
from soc.logic.models import mentor as mentor_logic
+from soc.logic.models.organization import logic as org_logic
+from soc.logic.models.org_admin import logic as org_admin_logic
from soc.logic.models import student as student_logic
+from soc.logic.models.student_project import logic as project_logic
from soc.views.helper import access
from soc.views.helper import decorators
+from soc.views.helper import dynaform
+from soc.views.helper import forms as forms_helper
+from soc.views.helper import lists
+from soc.views.helper import params as params_helper
from soc.views.helper import redirects
+from soc.views.helper import responses
from soc.views.helper import widgets
from soc.views.models import base
from soc.views.models import organization as org_view
@@ -54,12 +62,20 @@
rights = access.Checker(params)
rights['create'] = ['checkIsDeveloper']
- # TODO who should be able to edit this?
rights['edit'] = ['checkIsDeveloper']
-
rights['delete'] = ['checkIsDeveloper']
rights['show'] = ['allow']
rights['list'] = ['checkIsDeveloper']
+ rights['manage'] = [('checkHasActiveRoleForScope',
+ org_admin_logic),
+ ('checkStudentProjectHasStatus', ['accepted', 'mid_term_passed'])]
+ rights['manage_overview'] = [('checkHasActiveRoleForScope',
+ org_admin_logic)]
+ # TODO lack of better name here!
+ rights['st_edit'] = ['checkIsMyStudentProject',
+ ('checkStudentProjectHasStatus',
+ ['accepted', 'mid_term_passed', 'passed'])
+ ]
new_params = {}
new_params['logic'] = soc.logic.models.student_project.logic
@@ -83,28 +99,58 @@
required=True),
'mentor_id': forms.CharField(label='Mentor Link ID',
required=True),
+ 'clean_abstract': cleaning.clean_content_length('abstract'),
'clean_student': cleaning.clean_link_id('student'),
'clean_mentor': cleaning.clean_link_id('mentor'),
'clean_additional_info': cleaning.clean_url('additional_info'),
- 'clean': cleaning.validate_new_student_project('scope_path',
+ 'clean': cleaning.validate_student_project('scope_path',
'mentor_id', 'student_id')
}
new_params['edit_extra_dynaproperties'] = {
- 'student_id': forms.CharField(label='Student Link ID',
- widget=widgets.ReadOnlyInput),
- 'mentor_id': forms.CharField(label='Mentor Link ID',
- widget=widgets.ReadOnlyInput),
'link_id': forms.CharField(widget=forms.HiddenInput),
- 'clean': (lambda x: x.cleaned_data)
}
- # TODO(ljvderijk) OrgAdmins should be able to assign another Mentor
+ patterns = [
+ (r'^%(url_name)s/(?P<access_type>manage_overview)/%(scope)s$',
+ 'soc.views.models.%(module_name)s.manage_overview',
+ 'Overview of %(name_plural)s to Manage for'),
+ (r'^%(url_name)s/(?P<access_type>manage)/%(key_fields)s$',
+ 'soc.views.models.%(module_name)s.manage',
+ 'Manage %(name)s'),
+ (r'^%(url_name)s/(?P<access_type>st_edit)/%(key_fields)s$',
+ 'soc.views.models.%(module_name)s.st_edit',
+ 'Edit my %(name)s'),
+ ]
+
+ new_params['extra_django_patterns'] = patterns
+
+ new_params['edit_template'] = 'soc/student_project/edit.html'
+
+ # TODO(ljvderijk) list all projects for one org on their homepage
+ # TODO(ljvderijk) list all projects for one student
+ # TODO(ljvderijk) add manage item to org menu for admins
params = dicts.merge(params, new_params)
super(View, self).__init__(params=params)
+ # create the form that students will use to edit their projects
+ dynaproperties = {
+ 'clean_abstract': cleaning.clean_content_length('abstract'),
+ 'clean_additional_info': cleaning.clean_url('additional_info'),
+ }
+
+ student_edit_form = dynaform.newDynaForm(
+ dynabase = params['dynabase'],
+ dynamodel = params['logic'].getModel(),
+ dynaexclude = params['create_dynaexclude'],
+ dynaproperties = dynaproperties,
+ )
+
+ params['student_edit_form'] = student_edit_form
+
+
def _editGet(self, request, entity, form):
"""See base.View._editGet().
"""
@@ -127,18 +173,246 @@
# fill in the scope via call to super
super(View, self)._editPost(request, entity, fields)
- if not entity:
- # creating a new project so set the program, student and mentor field
- fields['program'] = fields['scope'].scope
+ # editing a project so set the program, student and mentor field
+ if entity:
+ organization = entity.scope
+ else:
+ organization = fields['scope']
+
+ fields['program'] = organization.scope
+
+ filter = {'scope': fields['program'],
+ 'link_id': fields['student_id']}
+ fields['student'] = student_logic.logic.getForFields(filter, unique=True)
+
+ filter = {'scope': organization,
+ 'link_id': fields['mentor_id'],
+ 'status': 'active'}
+ fields['mentor'] = mentor_logic.logic.getForFields(filter, unique=True)
+
+ @decorators.merge_params
+ @decorators.check_access
+ def manage(self, request, access_type,
+ page_name=None, params=None, **kwargs):
+ """View that allows Organization Admins to manage their Student Projects.
+
+ For params see base.View().public()
+ """
+
+ try:
+ entity = self._logic.getFromKeyFieldsOr404(kwargs)
+ except out_of_band.Error, error:
+ return helper.responses.errorResponse(
+ error, request, template=params['error_public'])
+
+ # get the context for this webpage
+ context = responses.getUniversalContext(request)
+ responses.useJavaScript(context, params['js_uses_all'])
+ context['page_name'] = "%s '%s' from %s" %(page_name, entity.title,
+ entity.student.name())
+
+ # use another template and make the cancel button goes to the public view
+ params['edit_template'] = 'soc/student_project/manage.html'
+ params['edit_cancel_redirect'] = redirects.getManageOverviewRedirect(
+ entity.scope, params)
+
+ # get all mentors for this organization
+ fields = {'scope': entity.scope,
+ 'status': 'active'}
+ mentors = mentor_logic.logic.getForFields(fields)
+
+ choices = [(mentor.link_id,'%s (%s)' %(mentor.name(), mentor.link_id))
+ for mentor in mentors]
+
+ # create the form that org admins will use to reassign a mentor
+ dynafields = [
+ {'name': 'mentor_id',
+ 'base': forms.ChoiceField,
+ 'label': 'Mentor',
+ 'required': True,
+ 'passthrough': ['required', 'choices', 'label'],
+ 'choices': choices,
+ },]
+
+ dynaproperties = params_helper.getDynaFields(dynafields)
+
+ mentor_edit_form = dynaform.newDynaForm(
+ dynabase = params['dynabase'],
+ dynaproperties = dynaproperties,
+ )
+
+ params['mentor_edit_form'] = mentor_edit_form
+
+ if request.POST:
+ return self.managePost(request, context, params, entity, **kwargs)
+ else: #request.GET
+ return self.manageGet(request, context, params, entity, **kwargs)
+
+ def manageGet(self, request, context, params, entity, **kwargs):
+ """Handles the GET request for the project's manage page.
+
+ Args:
+ entity: the student project entity
+ rest: see base.View.public()
+ """
+
+ # populate form with the current mentor
+ initial = {'mentor_id': entity.mentor.link_id}
+ form = params['mentor_edit_form'](initial=initial)
+
+ return self._constructResponse(request, entity, context, form, params)
+
+ def managePost(self, request, context, params, entity, **kwargs):
+ """Handles the POST request for the project's manage page.
+
+ Args:
+ entity: the student project entity
+ rest: see base.View.public()
+ """
+
+ form = params['mentor_edit_form'](request.POST)
+
+ if not form.is_valid():
+ return self._constructResponse(request, entity, context, form, params)
+
+ key_name, fields = forms_helper.collectCleanedFields(form)
+
+ # get the mentor from the form
+ fields = {'link_id': fields['mentor_id'],
+ 'scope': entity.scope,
+ 'status': 'active'}
+ mentor = mentor_logic.logic.getForFields(fields, unique=True)
+
+ # update the project with the assigned mentor
+ fields = {'mentor': mentor}
+ project_logic.updateEntityProperties(entity, fields)
+
+ return self.manageGet(request, context, params, entity)
- filter = {'scope': fields['program'],
- 'link_id': fields['student_id']}
- fields['student'] = student_logic.logic.getForFields(filter, unique=True)
+ @decorators.merge_params
+ @decorators.check_access
+ def manageOverview(self, request, access_type,
+ page_name=None, params=None, **kwargs):
+ """View that allows Organization Admins to see an overview of
+ their Organization's Student Projects.
+
+ For params see base.View().public()
+ """
+
+ # make sure the organization exists
+ org_entity = org_logic.getFromKeyNameOr404(kwargs['scope_path'])
+ fields = {'scope': org_entity}
+
+ # get the context for this webpage
+ context = responses.getUniversalContext(request)
+ responses.useJavaScript(context, params['js_uses_all'])
+ context['page_name'] = '%s %s' %(page_name, org_entity.name)
+
+ list_params = params.copy()
+
+ #list all active projects
+ fields['status'] = ['accepted', 'mid_term_passed']
+ active_params = list_params.copy()
+ active_params['list_description'] = \
+ 'List of all active %(name_plural)s' % list_params
+ active_params['list_action'] = (redirects.getManageRedirect, list_params)
+
+ active_list = lists.getListContent(
+ request, active_params, fields, idx=0)
+
+ # list all failed projects
+ fields['status'] = ['mid_term_failed', 'final_failed']
+ failed_params = list_params.copy()
+ failed_params['list_description'] = ('List of all failed %(name_plural)s, '
+ 'these cannot be managed.') % list_params
+ failed_params['list_action'] = (redirects.getPublicRedirect, list_params)
+
+ failed_list = lists.getListContent(
+ request, failed_params, fields, idx=1, need_content=True)
+
+ #list all completed projects
+ fields['status'] = ['passed']
+ completed_params = list_params.copy()
+ completed_params['list_description'] = ('List of %(name_plural)s that have '
+ 'successfully completed the program, these cannot be managed.' % list_params)
+ completed_params['list_action'] = (redirects.getPublicRedirect, list_params)
+
+ completed_list = lists.getListContent(
+ request, completed_params, fields, idx=2, need_content=True)
+
+ # always show the list with active projects
+ content = [active_list]
+
+ if failed_list != None:
+ # do not show empty failed list
+ content.append(failed_list)
+
+ if completed_list != None:
+ # do not show empty completed list
+ content.append(completed_list)
- filter = {'scope': fields['scope'],
- 'link_id': fields['mentor_id'],
- 'status': 'active'}
- fields['mentor'] = mentor_logic.logic.getForFields(filter, unique=True)
+ # call the _list method from base to display the list
+ return self._list(request, list_params, content,
+ context['page_name'], context)
+
+ @decorators.merge_params
+ @decorators.check_access
+ def stEdit(self, request, access_type,
+ page_name=None, params=None, **kwargs):
+ """View that allows students to edit information about their project.
+
+ For params see base.View().public()
+ """
+
+ try:
+ entity = self._logic.getFromKeyFieldsOr404(kwargs)
+ except out_of_band.Error, error:
+ return helper.responses.errorResponse(
+ error, request, template=params['error_public'])
+
+ # get the context for this webpage
+ context = responses.getUniversalContext(request)
+ responses.useJavaScript(context, params['js_uses_all'])
+ context['page_name'] = page_name
+ # cancel should go to the public view
+ params['edit_cancel_redirect'] = redirects.getPublicRedirect(entity, params)
+
+ if request.POST:
+ return self.stEditPost(request, context, params, entity, **kwargs)
+ else: #request.GET
+ return self.stEditGet(request, context, params, entity, **kwargs)
+
+ def stEditGet(self, request, context, params, entity, **kwargs):
+ """Handles the GET request for the student's edit page.
+
+ Args:
+ entity: the student project entity
+ rest: see base.View.public()
+ """
+
+ # populate form with the existing entity
+ form = params['student_edit_form'](instance=entity)
+
+ return self._constructResponse(request, entity, context, form, params)
+
+ def stEditPost(self, request, context, params, entity, **kwargs):
+ """Handles the POST request for the student's edit page.
+
+ Args:
+ entity: the student project entity
+ rest: see base.View.public()
+ """
+
+ form = params['student_edit_form'](request.POST)
+
+ if not form.is_valid():
+ return self._constructResponse(request, entity, context, form, params)
+
+ key_name, fields = forms_helper.collectCleanedFields(form)
+
+ project_logic.updateEntityProperties(entity, fields)
+
+ return self.stEditGet(request, context, params, entity, **kwargs)
view = View()
@@ -148,6 +422,9 @@
delete = decorators.view(view.delete)
edit = decorators.view(view.edit)
list = decorators.view(view.list)
+manage = decorators.view(view.manage)
+manage_overview = decorators.view(view.manageOverview)
public = decorators.view(view.public)
+st_edit = decorators.view(view.stEdit)
export = decorators.view(view.export)
pick = decorators.view(view.pick)