blob: a1aefd849b348f849a8be2e489c1e06b3d1e32fa [file] [log] [blame]
# Copyright 2013 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 profile related views for Summer Of Code."""
import collections
from google.appengine.ext import blobstore
from django.utils import html
from django.utils import translation
from melange.logic import timeline as timeline_logic
from melange.request import access
from melange.templates import readonly
from melange.views import profile as profile_view
from soc.modules.gsoc.views import base
from soc.modules.gsoc.views import forms as gsoc_forms
from soc.modules.gsoc.views.helper import url_patterns as soc_url_patterns
from summerofcode.logic import profile as soc_profile_logic
from summerofcode.request import error
from summerofcode.request import links
from summerofcode.request import render
from summerofcode.views.helper import urls as soc_urls
# Summer Of Code programs do not collect these fields:
_SKIP_FIELDS = ['grade', 'blog', 'web_page', 'photo_url']
TEE_SIZE_HELP_TEXT = translation.ugettext(
'Size of a T-Shirt that may be sent to you upon program completion.'
'<br>'
'<a href="'
'https://docs.google.com/file/d/0B7BZHIBakF7POVIwWXJHYmkwOTg/edit">'
'Men\'s</a> and <a href="'
'https://docs.google.com/file/d/0B7BZHIBakF7PWUZmWjAxYnVFQmc/edit">'
'Women\'s</a> size charts are available to help you choose.'
)
class SocProfileFormFactory(profile_view.ProfileFormFactory):
"""Implementation of profile_view.ProfileFormFactory to be used
for Summer Of Code programs.
"""
def create(self, request_data, terms_of_service, include_user_fields=None,
include_student_fields=None, **kwargs):
"""See profile_view.ProfileFormFactory.create for specification."""
form = profile_view._UserProfileForm(
gsoc_forms.GSoCBoundField, request_data,
terms_of_service=terms_of_service,
has_student_data=include_student_fields,
template_path=gsoc_forms.TEMPLATE_PATH, skip_fields=_SKIP_FIELDS,
**kwargs)
if not include_user_fields:
del form.fields['user_id']
# override help_text
form.fields['tee_size'].help_text = TEE_SIZE_HELP_TEXT
return form
SOC_PROFILE_FORM_FACTORY = SocProfileFormFactory()
class SOCProfileReadonlyFactory(profile_view.ProfileReadonlyFactory):
"""Implementation of profile_view.ProfileReadonlyFactory to be used for
Summer Of Code programs.
"""
def create(self, data, profile):
"""See profile_view.ProfileReadonlyFactory.create for specification."""
groups = []
fields = collections.OrderedDict()
fields[profile_view.USER_ID_LABEL] = profile.key.parent().id()
fields[profile_view.PUBLIC_NAME_LABEL] = profile.public_name
groups.append(
readonly.Group(
data, 'summerofcode/readonly/_group.html',
profile_view._BASIC_INFORMATION_GROUP, fields))
fields = collections.OrderedDict()
fields[profile_view.FIRST_NAME_LABEL] = profile.first_name
fields[profile_view.LAST_NAME_LABEL] = profile.last_name
fields[profile_view.EMAIL_LABEL] = profile.contact.email
fields[profile_view.PHONE_LABEL] = profile.contact.phone
groups.append(
readonly.Group(
data, 'summerofcode/readonly/_group.html',
profile_view._CONTACT_GROUP, fields))
fields = collections.OrderedDict()
fields[profile_view.RESIDENTIAL_STREET_LABEL] = (
profile_view.streetValue(profile.residential_address))
fields[profile_view.RESIDENTIAL_CITY_LABEL] = (
profile.residential_address.city)
fields[profile_view.RESIDENTIAL_PROVINCE_LABEL] = (
profile.residential_address.province)
fields[profile_view.RESIDENTIAL_POSTAL_CODE_LABEL] = (
profile.residential_address.postal_code)
fields[profile_view.RESIDENTIAL_COUNTRY_LABEL] = (
profile.residential_address.country)
groups.append(
readonly.Group(
data, 'summerofcode/readonly/_group.html',
profile_view._RESIDENTIAL_ADDRESS_GROUP, fields))
if profile.shipping_address:
fields = collections.OrderedDict()
fields[profile_view.SHIPPING_STREET_LABEL] = (
profile_view.streetValue(profile.shipping_address))
fields[profile_view.SHIPPING_CITY_LABEL] = profile.shipping_address.city
fields[profile_view.SHIPPING_PROVINCE_LABEL] = (
profile.shipping_address.province)
fields[profile_view.SHIPPING_POSTAL_CODE_LABEL] = (
profile.shipping_address.postal_code)
fields[profile_view.SHIPPING_COUNTRY_LABEL] = (
profile.shipping_address.country)
groups.append(
readonly.Group(
data, 'summerofcode/readonly/_group.html',
profile_view._SHIPPING_ADDRESS_GROUP, fields))
fields = collections.OrderedDict()
fields[profile_view.BIRTH_DATE_LABEL] = profile.birth_date
fields[profile_view.TEE_STYLE_LABEL] = profile.tee_style
fields[profile_view.TEE_SIZE_LABEL] = profile.tee_size
fields[profile_view.GENDER_LABEL] = (
profile_view._GENDER_ENUM_TO_VERBOSE_MAP[profile.gender])
if profile.program_knowledge not in (
[choice_id for choice_id, _ in profile_view.PROGRAM_KNOWLEDGE_CHOICES]):
fields[profile_view.PROGRAM_KNOWLEDGE_LABEL] = profile.program_knowledge
else:
fields[profile_view.PROGRAM_KNOWLEDGE_LABEL] = (
profile_view._PROGRAM_KNOWLEDGE_ENUM_TO_VERBOSE_MAP[(
profile.program_knowledge)])
groups.append(
readonly.Group(
data, 'summerofcode/readonly/_group.html',
profile_view._OTHER_INFORMATION_GROUP, fields))
if profile.is_student:
fields = collections.OrderedDict()
fields[profile_view.ENROLLMENT_FORM_LABEL] = (
_getEnrollmentFormItemValue(data, profile))
fields[profile_view.TAX_FORM_LABEL] = _getTaxFormItemValue(data, profile)
groups.append(
readonly.Group(
data, 'summerofcode/readonly/_group.html',
profile_view._FORMS_GROUP, fields))
return readonly.Readonly(
data, 'summerofcode/_readonly_template.html', groups)
SOC_PROFILE_READONLY_FACTORY = SOCProfileReadonlyFactory()
PROFILE_REGISTER_AS_STUDENT_ACCESS_CHECKER = access.ConjuctionAccessChecker([
access.HAS_NO_PROFILE_ACCESS_CHECKER,
access.STUDENT_SIGNUP_ACTIVE_ACCESS_CHECKER])
PROFILE_REGISTER_AS_ORG_MEMBER_PAGE = (
profile_view.ProfileRegisterAsOrgMemberPage(
base._GSOC_INITIALIZER, links.SOC_LINKER, render.SOC_RENDERER,
error.SOC_ERROR_HANDLER, soc_url_patterns.SOC_URL_PATTERN_CONSTRUCTOR,
soc_urls.UrlNames, 'summerofcode/profile/profile_edit.html',
SOC_PROFILE_FORM_FACTORY))
PROFILE_REGISTER_AS_STUDENT_PAGE = profile_view.ProfileRegisterAsStudentPage(
base._GSOC_INITIALIZER, links.SOC_LINKER, render.SOC_RENDERER,
error.SOC_ERROR_HANDLER, soc_url_patterns.SOC_URL_PATTERN_CONSTRUCTOR,
soc_urls.UrlNames, 'summerofcode/profile/profile_edit.html',
PROFILE_REGISTER_AS_STUDENT_ACCESS_CHECKER, SOC_PROFILE_FORM_FACTORY)
PROFILE_EDIT_PAGE = profile_view.ProfileEditPage(
base._GSOC_INITIALIZER, links.SOC_LINKER, render.SOC_RENDERER,
error.SOC_ERROR_HANDLER, soc_url_patterns.SOC_URL_PATTERN_CONSTRUCTOR,
soc_urls.UrlNames, 'summerofcode/profile/profile_edit.html',
SOC_PROFILE_FORM_FACTORY)
PROFILE_SHOW_PAGE = profile_view.ProfileShowPage(
base._GSOC_INITIALIZER, links.SOC_LINKER, render.SOC_RENDERER,
error.SOC_ERROR_HANDLER, soc_url_patterns.SOC_URL_PATTERN_CONSTRUCTOR,
soc_urls.UrlNames, 'summerofcode/profile/profile_show.html',
SOC_PROFILE_READONLY_FACTORY)
PROFILE_ADMIN_PAGE = profile_view.ProfileAdminPage(
base._GSOC_INITIALIZER, links.SOC_LINKER, render.SOC_RENDERER,
error.SOC_ERROR_HANDLER, soc_url_patterns.SOC_URL_PATTERN_CONSTRUCTOR,
soc_urls.UrlNames, 'summerofcode/profile/profile_show.html',
SOC_PROFILE_READONLY_FACTORY)
def _getEnrollmentFormItemValue(data, profile):
"""Returns a value to be displayed for Enrollment Form item in readonly
views for profiles.
Args:
data: request_data.RequestData object for the current request.
profile: Profile entity.
Returns:
A string to be rendered for Enrollment Form item.
"""
if data.ndb_profile.key == profile.key:
# the form may be still re-uploaded provided the program has not ended.
upload_url = (
links.ABSOLUTE_LINKER.program(
data.program, 'gsoc_enrollment_form', secure=True)
if timeline_logic.isProgramActive(data.program_timeline)
else None)
download_url = links.ABSOLUTE_LINKER.program(
data.program, 'gsoc_enrollment_form_download')
else:
upload_url = links.ABSOLUTE_LINKER.profile(
profile, 'gsoc_enrollment_form_admin', secure=True)
download_url = links.ABSOLUTE_LINKER.profile(
profile, 'gsoc_enrollment_form_download_admin')
if profile.student_data.enrollment_form:
blob_info = blobstore.BlobInfo.get(profile.student_data.enrollment_form)
return _formSubmittedValue(blob_info.filename, download_url, upload_url)
else:
return _formNotSubmittedValue(upload_url)
def _getTaxFormItemValue(data, profile):
"""Returns a value to be displayed for Tax Form item in readonly
views for profiles.
Args:
data: request_data.RequestData object for the current request.
profile: Profile entity.
Returns:
A string to be rendered for Tax Form item.
"""
if data.is_host:
upload_url = links.ABSOLUTE_LINKER.profile(
profile, 'gsoc_tax_form_admin', secure=True)
download_url = links.ABSOLUTE_LINKER.profile(
profile, 'gsoc_tax_form_download_admin')
else:
# the form may be still re-uploaded provided the program has not ended.
upload_url = (
links.ABSOLUTE_LINKER.program(
data.program, 'gsoc_tax_form', secure=True)
if timeline_logic.isProgramActive(data.program_timeline)
and data.timeline.afterFormSubmissionStart()
else None)
download_url = links.ABSOLUTE_LINKER.program(
data.program, 'gsoc_tax_form_download')
if profile.student_data.tax_form:
blob_info = blobstore.BlobInfo.get(profile.student_data.tax_form)
return _formSubmittedValue(blob_info.filename, download_url, upload_url)
elif (not data.timeline.afterFormSubmissionStart()
or not soc_profile_logic.hasProject(profile)):
return _formNotRequired()
else:
return _formNotSubmittedValue(upload_url)
def _formSubmittedValue(filename, download_url, upload_url):
"""Returns a value to be displayed for a form which has already
been submitted.
Args:
filename: A string containing name of the uploaded file.
download_url: A string containing URL to download the uploaded file.
upload_url: An string containing URL to re-upload the form. A link
is not included, if this parameter is set to None.
Returns:
A string to be displayed for the form.
"""
return (
html.format_html(
profile_view._FORM_SUBMITTED_UPLOAD_FORM_OPTION % (
filename, html.mark_safe(upload_url),
html.mark_safe(download_url)))
if upload_url
else html.format_html(
profile_view._FORM_SUBMITTED_NO_UPLOAD_FORM_OPTION % (
filename, html.mark_safe(download_url))))
def _formNotSubmittedValue(upload_url=None):
"""Returns a value to be displayed for a form which has not been submitted.
Args:
upload_url: A string containing URL to upload the form. A link is not
included, if this parameter is set to None.
Returns:
A string to be displayed for the form.
"""
return (
html.format_html(
profile_view._NO_FORM_SUBMITTED_UPLOAD_FORM_OPTION %
html.mark_safe(upload_url))
if upload_url
else profile_view._NO_FORM_SUBMITTED)
def _formNotRequired():
"""Returns a value to be displayed for a form when it is not required
at this time.
Returns:
A string to be displayed for the form.
"""
return profile_view._NO_FORM_REQUIRED