blob: e0d3e18e2cffb5966fa56ab963c64c19f323e02f [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 containing the view for GCI request page."""
from google.appengine.ext import db
from soc.logic import exceptions
from soc.logic.helper import notifications
from soc.views.helper import lists
from soc.views.helper import url_patterns
from soc.views.helper.access_checker import isSet
from soc.views.template import Template
from soc.tasks import mailer
from soc.modules.gci.models.profile import GCIProfile
from soc.modules.gci.models.request import GCIRequest
from soc.modules.gci.views import forms as gci_forms
from soc.modules.gci.views.base import GCIRequestHandler
from soc.modules.gci.views.helper import url_names
from soc.modules.gci.views.helper.url_patterns import url
class RequestForm(gci_forms.GCIModelForm):
"""Django form for the invite page."""
class Meta:
model = GCIRequest
css_prefix = 'gci_intivation'
fields = ['message']
class SendRequestPage(GCIRequestHandler):
"""Encapsulate all the methods required to generate Send Request page."""
def templatePath(self):
return 'v2/modules/gci/request/base.html'
def djangoURLPatterns(self):
return [
url(r'request/send/%s$' % url_patterns.REQUEST,
self, name=url_names.GCI_SEND_REQUEST)
]
def checkAccess(self):
"""Access checks for GCI Send Request page.
"""
#TODO(dhans): check if the program is visible
self.check.isProfileActive()
# check if the user is not a student
# check if the user does not have role for the organization
def context(self):
"""Handler to for GCI Send Request page HTTP get request.
"""
request_form = RequestForm(self.data.POST or None)
return {
'logout_link': self.data.redirect.logout(),
'forms': [request_form],
'page_name': self._constructPageName()
}
def _constructPageName(self):
role = 'Mentor' if self.data.kwargs['role'] == 'mentor' else 'Org Admin'
return "Request to become %s" % role
def validate(self):
"""Validates the form data.
Returns a newly created request entity or None if an error occurs.
"""
assert isSet(self.data.organization)
request_form = RequestForm(self.data.POST)
if not request_form.is_valid():
return None
request_form.cleaned_data['org'] = self.data.organization
request_form.cleaned_data['role'] = self.data.kwargs['role']
request_form.cleaned_data['type'] = 'Request'
request_form.cleaned_data['user'] = self.data.user
q = GCIProfile.all().filter('org_admin_for', self.data.organization)
q = q.filter('status', 'active').filter('notify_new_requests', True)
admins = q.fetch(1000)
admin_emails = [i.email for i in admins]
def create_request_txn():
request = request_form.create(commit=True, parent=self.data.user)
context = notifications.requestContext(self.data, request, admin_emails)
sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
sub_txn()
return request
return db.run_in_transaction(create_request_txn)
def post(self):
"""Handler to for GCI Send Request Page HTTP post request.
"""
request = self.validate()
if not request:
self.get()
return
self.redirect.id(request.key().id()).to(url_names.GCI_MANAGE_REQUEST)
class ManageRequestPage(GCIRequestHandler):
"""View to manage the invitation by the sender."""
def templatePath(self):
return 'v2/modules/gci/request/base.html'
def djangoURLPatterns(self):
return [
url(r'request/manage/%s$' % url_patterns.ID, self,
name=url_names.GCI_MANAGE_REQUEST)
]
def checkAccess(self):
self.check.isProfileActive()
request_id = int(self.data.kwargs['id'])
self.data.request_entity = GCIRequest.get_by_id(
request_id, parent=self.data.user)
self.check.isRequestPresent(request_id)
self.check.canManageRequest()
# check if the submitted action is legal
if self.data.POST:
if 'withdraw' not in self.data.POST and 'resubmit' not in self.data.POST:
raise exceptions.BadRequest(
'Valid action is not specified in the request.')
self.check.isRequestManageable()
def context(self):
page_name = self._constructPageName()
form = RequestForm(
self.data.POST or None, instance=self.data.request_entity)
button_name = self._constructButtonName()
button_value = self._constructButtonValue()
return {
'page_name': page_name,
'forms': [form],
'button_name': button_name,
'button_value': button_value
}
def post(self):
if 'withdraw' in self.data.POST:
def withdraw_request_txn():
request = db.get(self.data.request_entity.key())
request.status = 'withdrawn'
request.put()
db.run_in_transaction(withdraw_request_txn)
elif 'resubmit' in self.data.POST:
def resubmit_request_txn():
request = db.get(self.data.request_entity.key())
request.status = 'pending'
request.put()
db.run_in_transaction(resubmit_request_txn)
self.redirect.id().to(url_names.GCI_MANAGE_REQUEST)
def _constructPageName(self):
request = self.data.request_entity
return "%s Request To %s" % (request.role, request.org.name)
def _constructButtonName(self):
request = self.data.request_entity
if request.status == 'pending':
return 'withdraw'
if request.status in ['withdrawn', 'rejected']:
return 'resubmit'
def _constructButtonValue(self):
request = self.data.request_entity
if request.status == 'pending':
return 'Withdraw'
if request.status in ['withdrawn', 'rejected']:
return 'Resubmit'
class RespondRequestPage(GCIRequestHandler):
"""View to accept or reject requests by organization admins."""
def templatePath(self):
return 'v2/modules/gci/request/show.html'
def djangoURLPatterns(self):
return [
url(r'request/respond/%s$' % url_patterns.USER_ID, self,
name=url_names.GCI_RESPOND_REQUEST)
]
def checkAccess(self):
self.check.isProfileActive()
key_name = self.data.kwargs['user']
user_key = db.Key.from_path('User', key_name)
# fetch the request entity based on the id and parent key
request_id = int(self.data.kwargs['id'])
self.data.request_entity = GCIRequest.get_by_id(
request_id, parent=user_key)
self.check.isRequestPresent(request_id)
# get the organization and check if the current user can manage the request
self.data.organization = self.data.request_entity.org
self.check.isOrgAdmin()
self.data.is_respondable = self.data.request_entity.status == 'pending'
def context(self):
"""Handler to for GCI Respond Request page HTTP get request.
"""
return {
'request': self.data.request_entity,
'page_name': 'Respond to request',
'is_respondable': self.data.is_respondable
}
def post(self):
"""Handler to for GCI Respond Request Page HTTP post request.
"""
user_key = GCIRequest.user.get_value_for_datastore(
self.data.request_entity)
if 'accept' in self.data.POST:
options = db.create_transaction_options(xg=True)
request_key = self.data.request_entity.key()
organization_key = self.data.organization.key()
messages = self.data.program.getProgramMessages()
link_id = user_key.name()
profile_key_name = '/'.join([self.data.program.key().name(), link_id])
profile_key = db.Key.from_path(
'GCIProfile', profile_key_name, parent=user_key)
def accept_request_txn():
request = db.get(request_key)
self.data.requester_profile = profile = db.get(profile_key)
request.status = 'accepted'
profile.is_mentor = True
profile.mentor_for.append(organization_key)
profile.mentor_for = list(set(profile.mentor_for))
new_mentor = not profile.is_mentor
profile.is_mentor = True
profile.mentor_for.append(organization_key)
profile.mentor_for = list(set(profile.mentor_for))
# Send out a welcome email to new mentors.
if new_mentor:
mentor_mail = notifications.getMentorWelcomeMailContext(
profile, self.data, messages)
if mentor_mail:
mailer.getSpawnMailTaskTxn(mentor_mail, parent=request)()
profile.put()
request.put()
context = notifications.handledRequestContext(self.data, request.status)
sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
sub_txn()
db.run_in_transaction_options(options, accept_request_txn)
else: # reject
def reject_request_txn():
request = db.get(self.data.request_entity.key())
request.status = 'rejected'
request.put()
context = notifications.handledRequestContext(self.data, request.status)
sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
sub_txn()
db.run_in_transaction(reject_request_txn)
self.redirect.userId(user_key.name()).to(url_names.GCI_RESPOND_REQUEST)
class UserRequestsList(Template):
"""Template for list of requests that have been sent by the current user.
"""
def __init__(self, request, data):
self.request = request
self.data = data
r = data.redirect
list_config = lists.ListConfiguration()
list_config.addColumn('org', 'To',
lambda entity, *args: entity.org.name)
list_config.addSimpleColumn('status', 'Status')
list_config.setRowAction(
lambda e, *args: r.id(e.key().id())
.urlOf(url_names.GCI_MANAGE_REQUEST))
self._list_config = list_config
def getListData(self):
q = GCIRequest.all()
q.filter('type', 'Request')
q.filter('user', self.data.user)
response_builder = lists.RawQueryContentResponseBuilder(
self.request, self._list_config, q, lists.keyStarter)
return response_builder.build()
def context(self):
request_list = lists.ListConfigurationResponse(
self.data, self._list_config, 0)
return {
'lists': [request_list],
}
def templatePath(self):
return 'v2/modules/gci/request/_request_list.html'
class ListUserRequestsPage(GCIRequestHandler):
"""View for the page that lists all the requests which have been sent by
the current user.
"""
def templatePath(self):
return 'v2/modules/gci/request/request_list.html'
def djangoURLPatterns(self):
return [
url(r'request/list_user/%s$' % url_patterns.PROGRAM, self,
name=url_names.GCI_LIST_REQUESTS),
]
def checkAccess(self):
self.check.isProfileActive()
def jsonContext(self):
list_content = UserRequestsList(self.request, self.data).getListData()
if not list_content:
raise exceptions.AccessViolation('You do not have access to this data')
return list_content.content()
def context(self):
return {
'page_name': 'Your requests',
'request_list': UserRequestsList(self.request, self.data),
}