3 # Copyright 2009 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 Student Project.
21 '"Lennard de Rijk" <ljvderijk@gmail.com>',
27 from django
import forms
29 from soc
.logic
import cleaning
30 from soc
.logic
import dicts
31 from soc
.logic
.models
import mentor
as mentor_logic
32 from soc
.logic
.models
.organization
import logic
as org_logic
33 from soc
.logic
.models
.org_admin
import logic
as org_admin_logic
34 from soc
.logic
.models
import student
as student_logic
35 from soc
.logic
.models
.student_project
import logic
as project_logic
36 from soc
.views
import out_of_band
37 from soc
.views
.helper
import access
38 from soc
.views
.helper
import decorators
39 from soc
.views
.helper
import dynaform
40 from soc
.views
.helper
import forms
as forms_helper
41 from soc
.views
.helper
import lists
42 from soc
.views
.helper
import params
as params_helper
43 from soc
.views
.helper
import redirects
44 from soc
.views
.helper
import responses
45 from soc
.views
.models
import base
46 from soc
.views
.models
import organization
as org_view
48 import soc
.logic
.models
.student_project
51 class View(base
.View
):
52 """View methods for the Student Project model.
55 def __init__(self
, params
=None):
56 """Defines the fields and methods required for the base View class
57 to provide the user with list, public, create, edit and delete views.
60 params: a dict with params for this View
63 rights
= access
.Checker(params
)
64 rights
['create'] = ['checkIsDeveloper']
65 rights
['edit'] = ['checkIsDeveloper']
66 rights
['delete'] = ['checkIsDeveloper']
67 rights
['show'] = ['allow']
68 rights
['list'] = ['checkIsDeveloper']
69 rights
['manage'] = [('checkHasActiveRoleForScope',
71 ('checkStudentProjectHasStatus', ['accepted', 'mid_term_passed'])]
72 rights
['manage_overview'] = [('checkHasActiveRoleForScope',
74 # TODO lack of better name here!
75 rights
['st_edit'] = ['checkIsMyStudentProject',
76 ('checkStudentProjectHasStatus',
77 ['accepted', 'mid_term_passed', 'passed'])
81 new_params
['logic'] = soc
.logic
.models
.student_project
.logic
82 new_params
['rights'] = rights
83 new_params
['name'] = "Student Project"
84 new_params
['url_name'] = "student_project"
85 new_params
['sidebar_grouping'] = 'Students'
87 new_params
['scope_view'] = org_view
88 new_params
['scope_redirect'] = redirects
.getCreateRedirect
90 new_params
['no_create_with_key_fields'] = True
92 new_params
['extra_dynaexclude'] = ['program', 'status', 'link_id',
95 new_params
['create_extra_dynaproperties'] = {
96 'scope_path': forms
.CharField(widget
=forms
.HiddenInput
,
98 'student_id': forms
.CharField(label
='Student Link ID',
100 'mentor_id': forms
.CharField(label
='Mentor Link ID',
102 'clean_abstract': cleaning
.clean_content_length('abstract'),
103 'clean_student': cleaning
.clean_link_id('student'),
104 'clean_mentor': cleaning
.clean_link_id('mentor'),
105 'clean_additional_info': cleaning
.clean_url('additional_info'),
106 'clean_feed_url': cleaning
.clean_feed_url
,
107 'clean': cleaning
.validate_student_project('scope_path',
108 'mentor_id', 'student_id')
111 new_params
['edit_extra_dynaproperties'] = {
112 'link_id': forms
.CharField(widget
=forms
.HiddenInput
),
116 (r
'^%(url_name)s/(?P<access_type>manage_overview)/%(scope)s$',
117 'soc.views.models.%(module_name)s.manage_overview',
118 'Overview of %(name_plural)s to Manage for'),
119 (r
'^%(url_name)s/(?P<access_type>manage)/%(key_fields)s$',
120 'soc.views.models.%(module_name)s.manage',
122 (r
'^%(url_name)s/(?P<access_type>st_edit)/%(key_fields)s$',
123 'soc.views.models.%(module_name)s.st_edit',
127 new_params
['extra_django_patterns'] = patterns
129 new_params
['edit_template'] = 'soc/student_project/edit.html'
131 # TODO(ljvderijk) list all projects for one student
132 # TODO(ljvderijk) add manage item to org menu for admins
134 params
= dicts
.merge(params
, new_params
)
136 super(View
, self
).__init
__(params
=params
)
138 # create the form that students will use to edit their projects
140 'clean_abstract': cleaning
.clean_content_length('abstract'),
141 'clean_additional_info': cleaning
.clean_url('additional_info'),
142 'clean_feed_url': cleaning
.clean_feed_url
,
145 student_edit_form
= dynaform
.newDynaForm(
146 dynabase
= params
['dynabase'],
147 dynamodel
= params
['logic'].getModel(),
148 dynaexclude
= params
['create_dynaexclude'],
149 dynaproperties
= dynaproperties
,
152 params
['student_edit_form'] = student_edit_form
155 def _editGet(self
, request
, entity
, form
):
156 """See base.View._editGet().
159 form
.fields
['link_id'].initial
= entity
.link_id
160 form
.fields
['student_id'].initial
= entity
.student
.link_id
161 form
.fields
['mentor_id'].initial
= entity
.mentor
.link_id
163 return super(View
, self
)._editGet
(request
, entity
, form
)
165 def _editPost(self
, request
, entity
, fields
):
166 """See base.View._editPost().
170 fields
['link_id'] = 't%i' % (int(time
.time()*100))
172 fields
['link_id'] = entity
.link_id
174 # fill in the scope via call to super
175 super(View
, self
)._editPost
(request
, entity
, fields
)
177 # editing a project so set the program, student and mentor field
179 organization
= entity
.scope
181 organization
= fields
['scope']
183 fields
['program'] = organization
.scope
185 filter = {'scope': fields
['program'],
186 'link_id': fields
['student_id']}
187 fields
['student'] = student_logic
.logic
.getForFields(filter, unique
=True)
189 filter = {'scope': organization
,
190 'link_id': fields
['mentor_id'],
192 fields
['mentor'] = mentor_logic
.logic
.getForFields(filter, unique
=True)
194 @decorators.merge_params
195 @decorators.check_access
196 def manage(self
, request
, access_type
,
197 page_name
=None, params
=None, **kwargs
):
198 """View that allows Organization Admins to manage their Student Projects.
200 For params see base.View().public()
204 entity
= self
._logic
.getFromKeyFieldsOr404(kwargs
)
205 except out_of_band
.Error
, error
:
206 return responses
.errorResponse(
207 error
, request
, template
=params
['error_public'])
209 # get the context for this webpage
210 context
= responses
.getUniversalContext(request
)
211 responses
.useJavaScript(context
, params
['js_uses_all'])
212 context
['page_name'] = "%s '%s' from %s" % (page_name
, entity
.title
,
213 entity
.student
.name())
215 # use another template and make the cancel button goes to the public view
216 params
['edit_template'] = 'soc/student_project/manage.html'
217 params
['edit_cancel_redirect'] = redirects
.getManageOverviewRedirect(
218 entity
.scope
, params
)
220 # get all mentors for this organization
221 fields
= {'scope': entity
.scope
,
223 mentors
= mentor_logic
.logic
.getForFields(fields
)
225 choices
= [(mentor
.link_id
,'%s (%s)' %(mentor
.name(), mentor
.link_id
))
226 for mentor
in mentors
]
228 # create the form that org admins will use to reassign a mentor
230 {'name': 'mentor_id',
231 'base': forms
.ChoiceField
,
234 'passthrough': ['required', 'choices', 'label'],
238 dynaproperties
= params_helper
.getDynaFields(dynafields
)
240 mentor_edit_form
= dynaform
.newDynaForm(
241 dynabase
= params
['dynabase'],
242 dynaproperties
= dynaproperties
,
245 params
['mentor_edit_form'] = mentor_edit_form
248 return self
.managePost(request
, context
, params
, entity
, **kwargs
)
250 return self
.manageGet(request
, context
, params
, entity
, **kwargs
)
252 def manageGet(self
, request
, context
, params
, entity
, **kwargs
):
253 """Handles the GET request for the project's manage page.
256 entity: the student project entity
257 rest: see base.View.public()
260 # populate form with the current mentor
261 initial
= {'mentor_id': entity
.mentor
.link_id
}
262 form
= params
['mentor_edit_form'](initial
=initial
)
264 return self
._constructResponse
(request
, entity
, context
, form
, params
)
266 def managePost(self
, request
, context
, params
, entity
, **kwargs
):
267 """Handles the POST request for the project's manage page.
270 entity: the student project entity
271 rest: see base.View.public()
274 form
= params
['mentor_edit_form'](request
.POST
)
276 if not form
.is_valid():
277 return self
._constructResponse
(request
, entity
, context
, form
, params
)
279 _
, fields
= forms_helper
.collectCleanedFields(form
)
281 # get the mentor from the form
282 fields
= {'link_id': fields
['mentor_id'],
283 'scope': entity
.scope
,
285 mentor
= mentor_logic
.logic
.getForFields(fields
, unique
=True)
287 # update the project with the assigned mentor
288 fields
= {'mentor': mentor
}
289 project_logic
.updateEntityProperties(entity
, fields
)
291 return self
.manageGet(request
, context
, params
, entity
)
293 @decorators.merge_params
294 @decorators.check_access
295 def manageOverview(self
, request
, access_type
,
296 page_name
=None, params
=None, **kwargs
):
297 """View that allows Organization Admins to see an overview of
298 their Organization's Student Projects.
300 For params see base.View().public()
303 # make sure the organization exists
304 org_entity
= org_logic
.getFromKeyNameOr404(kwargs
['scope_path'])
305 fields
= {'scope': org_entity
}
307 # get the context for this webpage
308 context
= responses
.getUniversalContext(request
)
309 responses
.useJavaScript(context
, params
['js_uses_all'])
310 context
['page_name'] = '%s %s' % (page_name
, org_entity
.name
)
312 list_params
= params
.copy()
314 #list all active projects
315 fields
['status'] = ['accepted', 'mid_term_passed']
316 active_params
= list_params
.copy()
317 active_params
['list_description'] = \
318 'List of all active %(name_plural)s' % list_params
319 active_params
['list_action'] = (redirects
.getManageRedirect
, list_params
)
321 active_list
= lists
.getListContent(
322 request
, active_params
, fields
, idx
=0)
324 # list all failed projects
325 fields
['status'] = ['mid_term_failed', 'final_failed']
326 failed_params
= list_params
.copy()
327 failed_params
['list_description'] = ('List of all failed %(name_plural)s, '
328 'these cannot be managed.') % list_params
329 failed_params
['list_action'] = (redirects
.getPublicRedirect
, list_params
)
331 failed_list
= lists
.getListContent(
332 request
, failed_params
, fields
, idx
=1, need_content
=True)
334 #list all completed projects
335 fields
['status'] = ['passed']
336 completed_params
= list_params
.copy()
337 completed_params
['list_description'] = ('List of %(name_plural)s that have '
338 'successfully completed the program, '
339 'these cannot be managed.' % list_params
)
340 completed_params
['list_action'] = (redirects
.getPublicRedirect
, list_params
)
342 completed_list
= lists
.getListContent(
343 request
, completed_params
, fields
, idx
=2, need_content
=True)
345 # always show the list with active projects
346 content
= [active_list
]
348 if failed_list
!= None:
349 # do not show empty failed list
350 content
.append(failed_list
)
352 if completed_list
!= None:
353 # do not show empty completed list
354 content
.append(completed_list
)
356 # call the _list method from base to display the list
357 return self
._list
(request
, list_params
, content
,
358 context
['page_name'], context
)
360 @decorators.merge_params
361 @decorators.check_access
362 def stEdit(self
, request
, access_type
,
363 page_name
=None, params
=None, **kwargs
):
364 """View that allows students to edit information about their project.
366 For params see base.View().public()
370 entity
= self
._logic
.getFromKeyFieldsOr404(kwargs
)
371 except out_of_band
.Error
, error
:
372 return responses
.errorResponse(
373 error
, request
, template
=params
['error_public'])
375 # get the context for this webpage
376 context
= responses
.getUniversalContext(request
)
377 responses
.useJavaScript(context
, params
['js_uses_all'])
378 context
['page_name'] = page_name
379 # cancel should go to the public view
380 params
['edit_cancel_redirect'] = redirects
.getPublicRedirect(entity
, params
)
383 return self
.stEditPost(request
, context
, params
, entity
, **kwargs
)
385 return self
.stEditGet(request
, context
, params
, entity
, **kwargs
)
387 def stEditGet(self
, request
, context
, params
, entity
, **kwargs
):
388 """Handles the GET request for the student's edit page.
391 entity: the student project entity
392 rest: see base.View.public()
395 # populate form with the existing entity
396 form
= params
['student_edit_form'](instance
=entity
)
398 return self
._constructResponse
(request
, entity
, context
, form
, params
)
400 def stEditPost(self
, request
, context
, params
, entity
, **kwargs
):
401 """Handles the POST request for the student's edit page.
404 entity: the student project entity
405 rest: see base.View.public()
408 form
= params
['student_edit_form'](request
.POST
)
410 if not form
.is_valid():
411 return self
._constructResponse
(request
, entity
, context
, form
, params
)
413 _
, fields
= forms_helper
.collectCleanedFields(form
)
415 project_logic
.updateEntityProperties(entity
, fields
)
417 return self
.stEditGet(request
, context
, params
, entity
, **kwargs
)
422 admin
= decorators
.view(view
.admin
)
423 create
= decorators
.view(view
.create
)
424 delete
= decorators
.view(view
.delete
)
425 edit
= decorators
.view(view
.edit
)
426 list = decorators
.view(view
.list)
427 manage
= decorators
.view(view
.manage
)
428 manage_overview
= decorators
.view(view
.manageOverview
)
429 public
= decorators
.view(view
.public
)
430 st_edit
= decorators
.view(view
.stEdit
)
431 export
= decorators
.view(view
.export
)
432 pick
= decorators
.view(view
.pick
)