Added listing of all Accepted GHOPOrganizations to the Program View.
Reviewed by: Lennard de Rijk
#!/usr/bin/python2.5
#
# Copyright 2009 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""GHOP specific views for Programs.
"""
__authors__ = [
'"Madhusudan.C.S" <madhusudancs@gmail.com>',
'"Lennard de Rijk" <ljvderijk@gmail.com>',
]
import datetime
import os
from django import forms
from django import http
from django.utils.translation import ugettext
from soc.logic import cleaning
from soc.logic import dicts
from soc.logic.helper import timeline as timeline_helper
from soc.logic.models import host as host_logic
from soc.views import out_of_band
from soc.views import helper
from soc.views.helper import decorators
from soc.views.helper import dynaform
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 widgets
from soc.views.models import document as document_view
from soc.views.models import program
from soc.views.sitemap import sidebar
import soc.cache.logic
from soc.modules.ghop.logic.models import mentor as ghop_mentor_logic
from soc.modules.ghop.logic.models import org_admin as ghop_org_admin_logic
from soc.modules.ghop.logic.models import program as ghop_program_logic
from soc.modules.ghop.logic.models import student as ghop_student_logic
from soc.modules.ghop.logic.models import task as ghop_task_logic
from soc.modules.ghop.models import task as ghop_task_model
from soc.modules.ghop.views.helper import access as ghop_access
from soc.modules.ghop.views.helper import redirects as ghop_redirects
import soc.modules.ghop.logic.models.program
class View(program.View):
"""View methods for the GHOP Program model.
"""
DEF_PARTICIPATING_ORGS_MSG_FMT = ugettext(
'The following is a list of all the participating organizations under '
'the programme %(name)s. To know more about each organization and see '
'the tasks published by them please visit the corresponding links.')
DEF_TASK_QUOTA_ALLOCATION_MSG = ugettext(
"Use this view to assign task quotas.")
DEF_TASK_QUOTA_ERROR_MSG_FMT = ugettext(
"Task Quota limit for the organizations %s do not contain"
" a valid number(>0) and has not been updated.")
def __init__(self, params=None):
"""Defines the fields and methods required for the program View class
to provide the user with list, public, create, edit and delete views.
Params:
params: a dict with params for this View
"""
rights = ghop_access.GHOPChecker(params)
rights['show'] = ['allow']
rights['create'] = [('checkSeeded', ['checkHasActiveRoleForScope',
host_logic.logic])]
rights['edit'] = [('checkIsHostForProgram',
[ghop_program_logic.logic])]
rights['delete'] = ['checkIsDeveloper']
rights['accepted_orgs'] = [('checkIsAfterEvent',
['student_signup_start',
'__all__', ghop_program_logic.logic])]
rights['task_difficulty'] = [('checkIsHostForProgram',
[ghop_program_logic.logic])]
rights['task_type'] = [('checkIsHostForProgram',
[ghop_program_logic.logic])]
rights['difficulty_tag_edit'] = [('checkIsHostForProgram',
[ghop_program_logic.logic])]
rights['type_tag_edit'] = [('checkIsHostForProgram',
[ghop_program_logic.logic])]
new_params = {}
new_params['logic'] = soc.modules.ghop.logic.models.program.logic
new_params['rights'] = rights
new_params['name'] = "GHOP Program"
new_params['module_name'] = "program"
new_params['sidebar_grouping'] = 'Programs'
new_params['module_package'] = 'soc.modules.ghop.views.models'
new_params['url_name'] = 'ghop/program'
# TODO: this list can be reduced after GSoC has been moved
new_params['extra_dynaexclude'] = ['min_slots', 'max_slots',
'slot_allocation', 'allocations_visible',
'task_difficulties', 'task_types',
]
patterns = []
patterns += [
(r'^%(url_name)s/(?P<access_type>assign_task_quotas)/%(key_fields)s$',
'%(module_package)s.%(module_name)s.assign_task_quotas',
'Assign task quota limits'),
(r'^%(url_name)s/(?P<access_type>task_difficulty)/%(key_fields)s$',
'%(module_package)s.%(module_name)s.task_difficulty_edit',
'Edit Task Difficulty Tags'),
(r'^%(url_name)s/(?P<access_type>task_type)/%(key_fields)s$',
'%(module_package)s.%(module_name)s.task_type_edit',
'Edit Task Type Tags'),
(r'^%(url_name)s/(?P<access_type>difficulty_tag_edit)$',
'%(module_package)s.%(module_name)s.difficulty_tag_edit',
'Edit a Difficulty Tag'),
(r'^%(url_name)s/(?P<access_type>type_tag_edit)$',
'%(module_package)s.%(module_name)s.task_type_tag_edit',
'Edit a Task Type Tag'),
]
new_params['extra_django_patterns'] = patterns
params = dicts.merge(params, new_params, sub_merge=True)
super(View, self).__init__(params=params)
dynafields = [
{'name': 'overview_task_difficulties',
'base': forms.CharField,
'label': 'Task Difficulty Levels',
'group': 'Task Settings',
'widget': widgets.ReadOnlyInput(),
'required': False,
'help_text': ugettext('Lists all the difficulty levels that '
'can be assigned to a task. Edit them '
'from the Program menu on sidebar.'),
},
{'name': 'overview_task_types',
'base': forms.CharField,
'label': 'Task Type Tags',
'group': 'Task Settings',
'widget': widgets.ReadOnlyInput(),
'required': False,
'help_text': ugettext('Lists all the types a task can be in. '
'Edit them from the Program menu on sidebar.'),
},
]
dynaproperties = params_helper.getDynaFields(dynafields)
edit_form = dynaform.extendDynaForm(
dynaform=self._params['edit_form'],
dynaproperties=dynaproperties)
self._params['edit_form'] = edit_form
def _editGet(self, request, entity, form):
"""See base.View._editGet().
"""
# TODO: can't a simple join operation do this?
tds = ghop_task_model.TaskDifficultyTag.get_by_scope(entity)
if tds:
td_str = ''
for td in tds[:-1]:
td_str += str(td) + ', '
td_str += str(tds[-1])
form.fields['overview_task_difficulties'].initial = td_str
tts = ghop_task_model.TaskTypeTag.get_by_scope(entity)
if tts:
tt_str = ''
for tt in tts[:-1]:
tt_str += str(tt) + ', '
tt_str += str(tts[-1])
form.fields['overview_task_types'].initial = tt_str
return super(View, self)._editGet(request, entity, form)
@decorators.merge_params
@decorators.check_access
def assignTaskQuotas(self, request, access_type, page_name=None,
params=None, filter=None, **kwargs):
"""View that allows to assign task quotas for accepted GHOP organization.
This view allows the program admin to set the task quota limits
and change them at any time when the program is active.
"""
# TODO: Once GAE Task APIs arrive, this view will be managed by them
program = ghop_program_logic.logic.getFromKeyFieldsOr404(kwargs)
from soc.modules.ghop.views.models import \
organization as ghop_organization_view
org_params = ghop_organization_view.view.getParams().copy()
context = {}
if request.method == 'POST':
return self.assignTaskQuotasPost(request, context, org_params,
page_name, params, program,
**kwargs)
else: # request.method == 'GET'
return self.assignTaskQuotasGet(request, context, org_params,
page_name, params, program,
**kwargs)
def assignTaskQuotasPost(self, request, context, org_params,
page_name, params, entity, **kwargs):
"""Handles the POST request for the task quota allocation page.
Args:
entity: the program entity
rest: see base.View.public()
"""
ghop_org_logic = org_params['logic']
error_orgs = ''
for link_id, task_count in request.POST.items():
fields = {
'link_id': link_id,
'scope': entity,
'scope_path': entity.key().id_or_name(),
}
key_name = ghop_org_logic.getKeyNameFromFields(fields)
try:
task_count = int(task_count)
if task_count >= 0:
fields['task_quota_limit'] = task_count
ghop_org_logic.updateOrCreateFromKeyName(fields, key_name)
else:
raise ValueError
except ValueError:
org_entity = ghop_org_logic.getFromKeyName(key_name)
error_orgs += org_entity.name + ', '
if error_orgs:
context['error_message'] = self.DEF_TASK_QUOTA_ERROR_MSG_FMT % (
error_orgs[:-2])
return self.assignTaskQuotasGet(request, context, org_params,
page_name, params, entity,
**kwargs)
# redirect to the same page
return http.HttpResponseRedirect('')
def assignTaskQuotasGet(self, request, context, org_params,
page_name, params, entity, **kwargs):
"""Handles the GET request for the task quota allocation page.
Args:
entity: the program entity
rest see base.View.public()
"""
org_params['list_template'] = ('modules/ghop/program/'
'allocation/allocation.html')
org_params['list_heading'] = ('modules/ghop/program/'
'allocation/heading.html')
org_params['list_row'] = 'modules/ghop/program/allocation/row.html'
org_params['list_pagination'] = 'soc/list/no_pagination.html'
description = self.DEF_TASK_QUOTA_ALLOCATION_MSG
filter = {
'scope': entity,
'status': 'active',
}
content = self._getAcceptedOrgsList(description, org_params,
filter, False)
contents = [content]
return self._list(request, org_params, contents, page_name, context)
@decorators.merge_params
def getExtraMenus(self, id, user, params=None):
"""See soc.views.models.program.View.getExtraMenus().
"""
logic = params['logic']
rights = params['rights']
# only get all invisible and visible programs
fields = {'status': ['invisible', 'visible']}
entities = logic.getForFields(fields)
menus = []
rights.setCurrentUser(id, user)
for entity in entities:
items = []
if entity.status == 'visible':
# show the documents for this program, even for not logged in users
items += document_view.view.getMenusForScope(entity, params)
items += self._getTimeDependentEntries(entity, params, id, user)
try:
# check if the current user is a host for this program
rights.doCachedCheck('checkIsHostForProgram',
{'scope_path': entity.scope_path,
'link_id': entity.link_id}, [])
if entity.status == 'invisible':
# still add the document links so hosts can see how it looks like
items += document_view.view.getMenusForScope(entity, params)
items += self._getTimeDependentEntries(entity, params, id, user)
items += [(redirects.getReviewOverviewRedirect(
entity, {'url_name': 'ghop/org_app', 'scope_view': self}),
"Review Organization Applications", 'any_access')]
# add link to edit Program Profile
items += [(redirects.getEditRedirect(entity, params),
'Edit Program Profile', 'any_access')]
# add link to Assign Task Quota limits
items += [(ghop_redirects.getAssignTaskQuotasRedirect(entity, params),
'Assign Task Quota limits', 'any_access')]
# add link to edit Program Timeline
items += [(redirects.getEditRedirect(
entity, {'url_name': 'ghop/timeline'}),
"Edit Program Timeline", 'any_access')]
# add link to create a new Program Document
items += [(redirects.getCreateDocumentRedirect(entity, 'ghop/program'),
"Create a New Document", 'any_access')]
# add link to list all Program Document
items += [(redirects.getListDocumentsRedirect(entity, 'ghop/program'),
"List Documents", 'any_access')]
# add link to edit Task Difficulty Levels
items += [(ghop_redirects.getDifficultyEditRedirect(
entity, {'url_name': 'ghop/program'}),
"Edit Task Difficulty Levels", 'any_access')]
# add link to edit Task Type Tags
items += [(ghop_redirects.getTaskTypeEditRedirect(
entity, {'url_name': 'ghop/program'}),
"Edit Task Type Tags", 'any_access')]
except out_of_band.Error:
pass
items = sidebar.getSidebarMenu(id, user, items, params=params)
if not items:
continue
menu = {}
menu['heading'] = entity.short_name
menu['items'] = items
menu['group'] = 'Programs'
menus.append(menu)
return menus
def _getTimeDependentEntries(self, ghop_program_entity, params, id, user):
"""Returns a list with time dependent menu items.
"""
items = []
timeline_entity = ghop_program_entity.timeline
# get the student entity for this user and program
filter = {'user': user,
'scope': ghop_program_entity,
'status': 'active'}
student_entity = ghop_student_logic.logic.getForFields(filter, unique=True)
if student_entity:
items += self._getStudentEntries(ghop_program_entity, student_entity,
params, id, user)
# get mentor and org_admin entity for this user and program
filter = {'user': user,
'program': ghop_program_entity,
'status': 'active'}
mentor_entity = ghop_mentor_logic.logic.getForFields(filter, unique=True)
org_admin_entity = ghop_org_admin_logic.logic.getForFields(
filter, unique=True)
if mentor_entity or org_admin_entity:
items += self._getOrganizationEntries(
ghop_program_entity, org_admin_entity,
mentor_entity, params, id, user)
if user and not (student_entity or mentor_entity or org_admin_entity):
if timeline_helper.isActivePeriod(timeline_entity, 'student_signup'):
# this user does not have a role yet for this program
items += [('/ghop/student/apply/%s' % (
ghop_program_entity.key().id_or_name()),
"Register as a Student", 'any_access')]
if timeline_helper.isAfterEvent(timeline_entity, 'org_signup_start'):
url = redirects.getAcceptedOrgsRedirect(
ghop_program_entity, params)
# add a link to list all the organizations
items += [(url, "List participating Organizations", 'any_access')]
return items
def _getStudentEntries(self, ghop_program_entity, student_entity,
params, id, user):
"""Returns a list with menu items for students in a specific program.
"""
items = []
timeline_entity = ghop_program_entity.timeline
if timeline_helper.isAfterEvent(timeline_entity,
'student_signup_start'):
# add a link to show all projects
items += [(redirects.getListProjectsRedirect(ghop_program_entity,
{'url_name':'ghop/task'}),
"List my Tasks", 'any_access')]
items += [(redirects.getEditRedirect(student_entity,
{'url_name': 'ghop/student'}),
"Edit my Student Profile", 'any_access')]
items += [(redirects.getManageRedirect(student_entity,
{'url_name':'ghop/student'}),
"Resign as a Student", 'any_access')]
return items
@decorators.merge_params
@decorators.check_access
def taskDifficultyEdit(self, request, access_type, page_name=None,
params=None, filter=None, **kwargs):
"""View method used to edit Difficulty Level tags.
"""
params = dicts.merge(params, self._params)
try:
entity = self._logic.getFromKeyFieldsOr404(kwargs)
except out_of_band.Error, error:
return helper.responses.errorResponse(
error, request, template=params['error_public'])
context = helper.responses.getUniversalContext(request)
helper.responses.useJavaScript(context, params['js_uses_all'])
context['page_name'] = page_name
context['program_key_name'] = entity.key().name()
context['difficulties'] = ghop_task_model.TaskDifficultyTag.get_by_scope(
entity)
params['edit_template'] = 'modules/ghop/program/tag/difficulty.html'
return self._constructResponse(request, entity, context, None, params)
@decorators.merge_params
@decorators.check_access
def difficultyTagEdit(self, request, access_type, page_name=None,
params=None, filter=None, **kwargs):
"""View method used to edit a supplied Difficulty level tag.
"""
get_params = request.GET
order = get_params.getlist('order')
program_key_name = get_params.get('program_key_name')
program_entity = ghop_program_logic.logic.getFromKeyName(
program_key_name)
if order:
for index, elem in enumerate(order):
ghop_task_model.TaskDifficultyTag.update_order(
program_entity, elem, index)
return http.HttpResponse()
else:
tag_data = get_params.getlist('tag_data')
tag_name = tag_data[0].strip()
tag_value = tag_data[1].strip()
if tag_name:
if not tag_value:
ghop_task_model.TaskDifficultyTag.delete_tag(
program_entity, tag_name)
elif tag_name != tag_value:
ghop_task_model.TaskDifficultyTag.copy_tag(
program_entity, tag_name, tag_value)
else:
ghop_task_model.TaskDifficultyTag.get_or_create(
program_entity, tag_value)
return http.HttpResponse(tag_value)
@decorators.merge_params
@decorators.check_access
def taskTypeEdit(self, request, access_type, page_name=None,
params=None, filter=None, **kwargs):
"""View method used to edit Task Type tags.
"""
params = dicts.merge(params, self._params)
try:
entity = self._logic.getFromKeyFieldsOr404(kwargs)
except out_of_band.Error, error:
return helper.responses.errorResponse(
error, request, template=params['error_public'])
context = helper.responses.getUniversalContext(request)
helper.responses.useJavaScript(context, params['js_uses_all'])
context['page_name'] = page_name
context['program_key_name'] = entity.key().name()
context['task_types'] = ghop_task_model.TaskTypeTag.get_by_scope(
entity)
params['edit_template'] = 'modules/ghop/program/tag/task_type.html'
return self._constructResponse(request, entity, context, None, params)
@decorators.merge_params
@decorators.check_access
def taskTypeTagEdit(self, request, access_type, page_name=None,
params=None, filter=None, **kwargs):
"""View method used to edit a supplied Task Type tag.
"""
get_params = request.GET
order = get_params.getlist('order')
program_key_name = get_params.get('program_key_name')
program_entity = ghop_program_logic.logic.getFromKeyName(
program_key_name)
if order:
for index, elem in enumerate(order):
ghop_task_model.TaskTypeTag.update_order(
program_entity, elem, index)
return http.HttpResponse()
else:
tag_data = get_params.getlist('tag_data')
program_key_name = get_params.get('program_key_name')
tag_name = tag_data[0].strip()
tag_value = tag_data[1].strip()
program_entity = ghop_program_logic.logic.getFromKeyName(
program_key_name)
if tag_name:
if not tag_value:
ghop_task_model.TaskTypeTag.delete_tag(
program_entity, tag_name)
elif tag_name != tag_value:
ghop_task_model.TaskTypeTag.copy_tag(
program_entity, tag_name, tag_value)
else:
ghop_task_model.TaskTypeTag.get_or_create(program_entity, tag_value)
return http.HttpResponse(tag_value)
@decorators.merge_params
@decorators.check_access
def acceptedOrgs(self, request, access_type,
page_name=None, params=None, filter=None, **kwargs):
"""List all the accepted orgs for the given program.
"""
from soc.modules.ghop.views.models.organization import view as \
ghop_org_view
contents = []
logic = params['logic']
ghop_program_entity = logic.getFromKeyFieldsOr404(kwargs)
ao_params = ghop_org_view.getParams().copy()
ao_params['list_action'] = (redirects.getHomeRedirect,
ao_params)
ao_params['list_description'] = self.DEF_PARTICIPATING_ORGS_MSG_FMT % {
'name': ghop_program_entity.name
}
filter = {
'scope': ghop_program_entity,
'status': ['new', 'active'],
}
order = ['name']
ao_list = lists.getListContent(request, ao_params, filter=filter,
order=order, idx=0)
contents.append(ao_list)
params = params.copy()
params['list_msg'] = ghop_program_entity.accepted_orgs_msg
return self._list(request, params, contents, page_name)
view = View()
admin = decorators.view(view.admin)
accepted_orgs = decorators.view(view.acceptedOrgs)
assign_task_quotas = decorators.view(view.assignTaskQuotas)
create = decorators.view(view.create)
delete = decorators.view(view.delete)
edit = decorators.view(view.edit)
list = decorators.view(view.list)
public = decorators.view(view.public)
export = decorators.view(view.export)
home = decorators.view(view.home)
difficulty_tag_edit = decorators.view(view.difficultyTagEdit)
task_type_tag_edit = decorators.view(view.taskTypeTagEdit)
task_difficulty_edit = decorators.view(view.taskDifficultyEdit)
task_type_edit = decorators.view(view.taskTypeEdit)