blob: 4e47da91edce1595a13d0f1148eae0d3e003063f [file] [log] [blame]
# Copyright 2011 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.
"""Module for the GSoC slot transfer page."""
from google.appengine.ext import db
from django import forms as django_forms
from soc.logic import cleaning
from soc.logic import host as host_logic
from soc.logic.exceptions import RedirectRequest
from soc.tasks import mailer
from soc.views.helper import url_patterns
from soc.modules.gsoc.logic.helper import notifications
from soc.modules.gsoc.models.slot_transfer import GSoCSlotTransfer
from soc.modules.gsoc.views import readonly_template
from soc.modules.gsoc.views.base import GSoCRequestHandler
from soc.modules.gsoc.views import forms
from soc.modules.gsoc.views.helper.url_patterns import url
class SlotTransferForm(forms.GSoCModelForm):
"""Django form for the slot transfer page.
"""
def __init__(self, max_slots, *args, **kwargs):
super(SlotTransferForm, self).__init__(*args, **kwargs)
choices = [('None', self.fields['nr_slots'].label)] + [
(i, i) for i in range(1, max_slots + 1)]
self.fields['nr_slots'].widget = django_forms.widgets.Select(
choices=choices)
class Meta:
model = GSoCSlotTransfer
css_prefix = 'gsoc_slot_transfer'
exclude = ['status', 'created_on', 'last_modified_on',
'program', 'admin_remarks']
clean_remarks = cleaning.clean_html_content('remarks')
class SlotTransferReadOnlyTemplate(readonly_template.GSoCModelReadOnlyTemplate):
"""Template to display readonly information from previous requests.
"""
template_path = 'v2/modules/gsoc/slot_transfer/_readonly_template.html'
def __init__(self, counter, *args, **kwargs):
super(SlotTransferReadOnlyTemplate, self).__init__(*args, **kwargs)
self.counter = counter
class Meta:
model = GSoCSlotTransfer
css_prefix = 'gsoc_slot_transfer'
exclude = ['program']
class SlotTransferPage(GSoCRequestHandler):
"""View for transferring the slots.
"""
def djangoURLPatterns(self):
return [
url(r'slots/transfer/%s$' % url_patterns.ORG,
self, name='gsoc_slot_transfer'),
]
def checkAccess(self, data, check, mutator):
check.isLoggedIn()
check.isProgramVisible()
check.isOrganizationInURLActive()
check.isOrgAdminForOrganization(data.organization)
check.isSlotTransferActive()
mutator.slotTransferEntities()
if not data.slot_transfer_entities:
if 'new' not in data.kwargs:
# TODO(nathaniel): make this .organization() call unnecessary.
data.redirect.organization()
new_url = data.redirect.urlOf('gsoc_update_slot_transfer')
raise RedirectRequest(new_url)
def templatePath(self):
return 'v2/modules/gsoc/slot_transfer/base.html'
def context(self, data, check, mutator):
requests = []
require_new_link = True
for i, ent in enumerate(data.slot_transfer_entities):
requests.append(SlotTransferReadOnlyTemplate(i, instance=ent))
if ent.status == 'pending':
require_new_link = False
context = {
'page_name': 'Transfer slots to pool',
'requests': requests,
}
if (data.program.allocations_visible and
data.timeline.beforeStudentsAnnounced()):
# TODO(nathaniel): make this .organization() call unnecessary.
data.redirect.organization()
edit_url = data.redirect.urlOf('gsoc_update_slot_transfer')
if require_new_link:
context['new_slot_transfer_page_link'] = edit_url
else:
context['edit_slot_transfer_page_link'] = edit_url
return context
class UpdateSlotTransferPage(GSoCRequestHandler):
"""View for transferring the slots."""
def djangoURLPatterns(self):
return [
url(r'slots/transfer/update/%s$' % url_patterns.ORG,
self, name='gsoc_update_slot_transfer'),
]
def checkAccess(self, data, check, mutator):
check.isLoggedIn()
check.isProgramVisible()
check.isOrganizationInURLActive()
check.isOrgAdminForOrganization(data.organization)
check.isSlotTransferActive()
mutator.slotTransferEntities()
def templatePath(self):
return 'v2/modules/gsoc/slot_transfer/form.html'
def context(self, data, check, mutator):
slots = data.organization.slots
if data.POST:
slot_transfer_form = SlotTransferForm(slots, data.POST)
else:
slot_transfer_form = SlotTransferForm(slots)
for ent in data.slot_transfer_entities:
if ent.status == 'pending':
if data.POST:
slot_transfer_form = SlotTransferForm(slots, data.POST, instance=ent)
else:
slot_transfer_form = SlotTransferForm(slots, instance=ent)
context = {
'page_name': 'Transfer slots to pool',
'form_header_msg': 'Transfer the slots to the pool',
'forms': [slot_transfer_form],
'error': slot_transfer_form.errors
}
# TODO(nathaniel): make this .organization() call unnecessary.
data.redirect.organization()
context['org_home_page_link'] = data.redirect.urlOf('gsoc_org_home')
context['slot_transfer_page_link'] = data.redirect.urlOf(
'gsoc_slot_transfer')
return context
def createOrUpdateFromForm(self, data):
"""Creates a new proposal based on the data inserted in the form.
Args:
data: A RequestData describing the current request.
Returns:
a newly created proposal entity or None
"""
slot_transfer_entity = None
slot_transfer_form = SlotTransferForm(
data.organization.slots, data.POST)
if not slot_transfer_form.is_valid():
return None
slot_transfer_form.cleaned_data['program'] = data.program
for ent in data.slot_transfer_entities:
if ent.status == 'pending':
slot_transfer_entity = ent
break
# TODO(Madhu): This should return the host entities and not the user
# entities and we should check for host.notify_slot_transfer before
# sending the email. But at the moment we haved saved all our hosts
# without reference to their user entities as parents, so we don't
# have a way to get the relationship between the user entities and
# the host entities. So use the user entities for now.
host_users = host_logic.getHostsForProgram(data.program)
to_emails = [u.account.email() for u in host_users]
def create_or_update_slot_transfer_trx():
update = False
if slot_transfer_entity:
slot_transfer = db.get(slot_transfer_entity.key())
slot_transfer_form.instance = slot_transfer
slot_transfer = slot_transfer_form.save(commit=True)
update = True
else:
slot_transfer = slot_transfer_form.create(
commit=True, parent=data.organization)
context = notifications.createOrUpdateSlotTransferContext(
data, slot_transfer, to_emails, update)
sub_txn = mailer.getSpawnMailTaskTxn(
context, parent=slot_transfer.parent())
sub_txn()
return slot_transfer
return db.run_in_transaction(create_or_update_slot_transfer_trx)
def post(self, data, check, mutator):
"""Handler for HTTP POST request."""
slot_transfer_entity = self.createOrUpdateFromForm(data)
if slot_transfer_entity:
# TODO(nathaniel): make this .organization call unnecessary.
data.redirect.organization(organization=data.organization)
return data.redirect.to('gsoc_update_slot_transfer', validated=True)
else:
# TODO(nathaniel): problematic self-use.
return self.get(data, check, mutator)