blob: dd7d7930c690f78796faf56ef7354191848ff92a [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 GCI participant dashboard."""
import enum
import json
import logging
from google.appengine.ext import ndb
from django import http
from django.utils.translation import ugettext
from codein.logic import task as task_logic
from codein.logic import timeline as timeline_logic
from codein.views.helper import urls
from melange.logic import organization as org_logic
from melange.logic import profile as profile_logic
from melange.models import organization as org_model
from melange.request import exception
from melange.request import links
from soc.logic import document as document_logic
from soc.views import dashboard as dashboard_view
from soc.views.dashboard import Component
from soc.views.dashboard import Dashboard
from soc.views.helper import lists
from soc.views.helper import url_patterns
from soc.modules.gci.logic import document as gsoc_document_logic
from soc.modules.gci.logic import task as gci_task_logic
from soc.modules.gci.models import task as task_model
from soc.modules.gci.models.task import GCITask
from soc.modules.gci.views.base import GCIRequestHandler
from soc.modules.gci.views.helper import url_names as gci_url_names
from soc.modules.gci.views.helper.url_patterns import url
BACKLINKS_TO_MAIN = {'to': 'main', 'title': 'Main dashboard'}
class MainDashboard(Dashboard):
"""Dashboard for user's main-dashboard
"""
def __init__(self, data, url_names):
"""Initializes the dashboard.
Args:
data: The RequestData object
url_names: Instance of url_names.UrlNames.
"""
super(MainDashboard, self).__init__(data)
self.subpages = dashboard_view._initMainDashboardSubpages(data, url_names)
def context(self):
"""Returns the context of main dashboard."""
return {
'title': 'Participant dashboard',
'name': 'main',
'subpages': self._divideSubPages(self.subpages),
'enabled': True
}
def addSubpages(self, subpage):
self.subpages.append(subpage)
class ComponentsDashboard(Dashboard):
"""Dashboard that holds component list."""
def __init__(self, data, component_property):
"""Initializes the dashboard.
Args:
data: The RequestData object
component_property: Component property
"""
super(ComponentsDashboard, self).__init__(data)
self.name = component_property.get('name')
self.title = component_property.get('title')
self.components = (component_property.get('component'),)
self.backlinks = (component_property.get('backlinks'),)
def context(self):
"""Returns the context of components dashboard.
"""
return {
'title': self.title,
'name': self.name,
'backlinks': self.backlinks,
'components': self.components,
}
# TODO(nathaniel): Make all attributes of this class private except
# those that fulfill the RequestHandler type.
class DashboardPage(GCIRequestHandler):
"""View for the participant dashboard."""
def djangoURLPatterns(self):
"""The URL pattern for the dashboard."""
return [
url(r'dashboard/%s$' % url_patterns.PROGRAM, self,
name='gci_dashboard')]
def checkAccess(self, data, check, mutator):
"""Denies access if you are not logged in."""
check.isProfileActive()
def templatePath(self):
"""Returns the path to the template."""
return 'modules/gci/dashboard/base.html'
def populateDashboards(self, data):
"""Populates the various dashboard subpages and components for each subpage.
"""
# dashboard container, will hold each component list
dashboards = []
# main container that contains all component list
main = MainDashboard(data, urls.UrlNames)
# retrieve active links and add it to the main dashboard
for link in self.links(data):
main.addSubpages(link)
# retrieve active component(s) for currently logged-in user
components = self.components(data)
# add components as children of main dashboard and treat the component
# as dashboard element
for component in components:
c = {
'name': component.context().get('name'),
'description': component.context().get('description'),
'title': component.context().get('title'),
'component_link': True,
}
main.addSubpages(c)
dashboards.append(ComponentsDashboard(data, {
'name': component.context().get('name'),
'title': component.context().get('title'),
'component': component,
'backlinks': BACKLINKS_TO_MAIN,
}))
dashboards.append(main)
return dashboards
def formsValidated(self, data):
"""Checks if the current user has all forms validated.
Args:
data: A RequestData describing the current request.
Returns:
A boolean which indicates whether or not both of a
students forms have been validated.
"""
if data.ndb_profile.is_student:
return (data.ndb_profile.student_data.is_enrollment_form_verified and
data.ndb_profile.student_data.is_consent_form_verified)
else:
return False
def context(self, data, check, mutator):
"""Handler for default HTTP GET request."""
context = {
'page_name': data.program.name,
'user_name': data.ndb_user.user_id if data.ndb_user else None,
}
# Check if the student should submit either of the forms
context['forms_validated'] = self.formsValidated(data)
context['is_student'] = data.ndb_profile.is_student
context['dashboards'] = self.populateDashboards(data)
return context
def jsonContext(self, data, check, mutator):
"""Handler for JSON requests."""
for component in self.components(data):
list_content = component.getListData()
if list_content:
return list_content.content()
else:
raise exception.Forbidden(message='You do not have access to this data')
def post(self, data, check, mutator):
"""Handler for POST requests for each component."""
for component in self.components(data):
if component.post():
return http.HttpResponse()
else:
raise exception.Forbidden(message='You cannot change this data')
def components(self, data):
"""Returns the list components that are active on the page.
Args:
data: A RequestData describing the current request.
Returns:
The list components that are active on the page.
"""
components = []
if data.ndb_profile.is_student:
components += self._getStudentComponents(data)
elif data.is_org_admin:
components += self._getOrgAdminComponents(data)
components += self._getMentorComponents(data)
elif data.is_mentor:
components += self._getMentorComponents(data)
return components
def _getStudentComponents(self, data):
"""Get the dashboard components for a student."""
return [DocumentComponent(data)]
def _getMentorComponents(self, data):
"""Get the dashboard components for Organization members."""
components = []
components.append(DocumentComponent(data))
if data.timeline.orgsAnnounced():
components.append(MyOrgsTaskList(data))
components.append(MyOrgsListBeforeCreateTask(data))
return components
def _getOrgAdminComponents(self, data):
"""Get the dashboard components for org admins."""
components = []
component = self._getManagedOrganizationsComponent(data)
if component:
components.append(component)
# add list of mentors component
components.append(MyOrgsMentorsList(data))
# add bulk create tasks component
if data.timeline.orgsAnnounced():
components.append(MyOrgsListBeforeBulkCreateTask(data))
# add org scores component
components.append(MyOrgsScoresList(data))
return components
def links(self, data):
"""Returns additional links of main dashboard that are active on the page.
Args:
data: A RequestData describing the current request.
Returns:
Additional links of the main dashboard that are active on the page.
"""
dashboard_links = []
# TODO(nathaniel): Does there have to be so much control flow here? Must
# this function be responsible for enforcing students-cannot-also-be-
# any-other-role or might enforcement of that rule elsewhere be enough?
if data.ndb_profile.is_student:
dashboard_links += self._getStudentLinks(data)
else:
dashboard_links.extend(self._getNonStudentLinks(data))
return dashboard_links
def _getStudentLinks(self, data):
"""Get the main dashboard links for student."""
dashboard_links = [
self._getStudentFormsLink(data),
self._getMyTasksLink(data),
self._getMySubscribedTasksLink(data)
]
current_task = (
gci_task_logic.queryCurrentTaskForStudent(data.ndb_profile).get())
if current_task:
dashboard_links.append(self._getCurrentTaskLink(data, current_task))
return dashboard_links
def _getNonStudentLinks(self, data):
"""Gets the main dashboard links for users with non-student profile.
Args:
data: RequestData object for the current request.
Returns:
A list of dicts, each of which describes a single link.
"""
dashboard_links = []
if data.ndb_profile:
if data.is_org_admin:
dashboard_links.extend(self._getOrgAdminLinks(data))
if data.is_mentor:
dashboard_links.extend(self._getMentorLinks(data))
return dashboard_links
def _getOrgAdminLinks(self, data):
"""Get the main dashboard links for org-admin."""
dashboard_links = []
# add propose winners component
if timeline_logic.isAfterWorkReviewDeadline(data.program_timeline):
dashboard_links.append(self._getNominateWinnersLink(data))
return dashboard_links
def _getMentorLinks(self, data):
"""Get the main dashboard links for mentor."""
return []
def _getStudentFormsLink(self, data):
"""Get the link for uploading student forms."""
# TODO(nathaniel): Eliminate this state-setting call.
data.redirect.program()
return {
'name': 'form_uploads',
'description': ugettext(
'Upload student id and parental consent forms.'),
'title': 'Form uploads',
'link': data.redirect.urlOf(gci_url_names.GCI_STUDENT_FORM_UPLOAD)
}
def _getMyTasksLink(self, data):
"""Get the link to the list of all the tasks for the student
who is currently logged in.
"""
# TODO(nathaniel): Eliminate this state-setting call.
data.redirect.profile(data.ndb_user.user_id)
return {
'name': 'student_tasks',
'description': ugettext(
'List of the tasks that you have completed so far in the program'),
'title': 'My completed tasks',
'link': data.redirect.urlOf(gci_url_names.GCI_STUDENT_TASKS)
}
def _getCurrentTaskLink(self, data, current_task):
"""Get the link to the task that the student is currently working on.
"""
# TODO(nathaniel): Eliminate this state-setting call.
data.redirect.id(current_task.key().id())
return {
'name': 'current_task',
'description': ugettext(
'The task you are currently working on'),
'title': 'My current task',
'link': data.redirect.urlOf('gci_view_task')
}
def _getMySubscribedTasksLink(self, data):
"""Get the link to the list of all the tasks the current logged in user
is subscribed to.
"""
# TODO(nathaniel): make this .profile call unnecessary.
data.redirect.profile(data.ndb_user.user_id)
return {
'name': 'subscribed_tasks',
'description': ugettext(
'List of the tasks that you have subscribed to'),
'title': 'My subscribed tasks',
'link': data.redirect.urlOf(gci_url_names.GCI_SUBSCRIBED_TASKS)
}
def _getNominateWinnersLink(self, data):
"""Get the link to the list of organization to nominate winners for."""
return {
'name': 'nominate_winners',
'description': ugettext(
'Nominate the Grand Prize Winners'),
'title': 'Nominate the Grand Prize Winners',
'link': links.LINKER.program(
data.program, urls.UrlNames.ORG_NOMINATE_WINNERS_PICK_ORG),
}
def _getManagedOrganizationsComponent(self, data):
"""Returns ManagedOrganizationsComponent, if this user is an administrator
for at least one organization.
Args:
data: request_data.RequestData object for the current request.
Returns:
An instance of ManagedOrganizationsComponent class, if the user is an
organization administrator; None otherwise.
"""
if data.ndb_profile.is_admin:
# add a component showing organizations managed by the current user
return ManagedOrganizationsComponent(data)
else:
return None
class ComponentID(enum.Enum):
(
MY_ORGS_TASK_LIST,
MANAGED_ORGANIZATIONS,
MY_ORGS_LIST,
MY_ORGS_LIST_BEFORE_CREATE_TASK,
MY_ORGS_LIST_BEFORE_BULK_CREATE_TASK,
MY_ORGS_SCORES_LIST,
MY_ORGS_MENTORS_LIST,
DOCUMENT
) = range(8)
class MyOrgsTaskList(Component):
"""Component for listing the tasks of the orgs of the current user.
"""
IDX = ComponentID.MY_ORGS_TASK_LIST
PUBLISH_BUTTON_ID = 'publish'
UNPUBLISH_BUTTON_ID = 'unpublish'
def __init__(self, data):
"""Initializes the component.
Args:
data: The RequestData object
"""
super(MyOrgsTaskList, self).__init__(data)
list_config = lists.ListConfiguration()
list_config.addSimpleColumn('title', 'Title')
list_config.addPlainTextColumn(
'org', 'Organization',
lambda entity, *args: task_logic.getOrganizationKey(entity).get().name)
list_config.addPlainTextColumn(
'type', 'Type', lambda entity, *args: ", ".join(entity.types))
list_config.addPlainTextColumn(
'is_beginner', 'Beginner',
lambda entity, *args: 'Yes' if entity.is_beginner else 'No')
list_config.addPlainTextColumn(
'tags', 'Tags', lambda entity, *args: ", ".join(entity.tags))
list_config.addPlainTextColumn(
'time_to_complete', 'Time to complete',
lambda entity, *args: entity.taskTimeToComplete())
def getMentors(entity, *args):
"""Helper function to get value for mentors column."""
mentor_keys = map(ndb.Key.from_old_key, entity.mentors)
mentors = ndb.get_multi(mentor_keys)
return ', '.join(mentor.public_name for mentor in mentors)
list_config.addPlainTextColumn(
'mentors', 'Mentors', getMentors)
list_config.addSimpleColumn('description', 'Description', hidden=True)
def getStudent(entity, *args):
"""Helper function to get value for student column."""
student_key = task_model.GCITask.student.get_value_for_datastore(entity)
if not student_key:
return ''
else:
student = ndb.Key.from_old_key(student_key).get()
return student.public_name
list_config.addPlainTextColumn(
'student', 'Student', getStudent, hidden=True)
def getCreatedBy(entity, *args):
"""Helper function to get value for created_by column."""
profile_key = (
task_model.GCITask.created_by.get_value_for_datastore(entity))
if not profile_key:
return ''
else:
profile = ndb.Key.from_old_key(profile_key).get()
return profile.public_name
list_config.addPlainTextColumn(
'created_by', 'Created by', getCreatedBy, hidden=True)
def getModifiedBy(entity, *args):
"""Helper function to get value for modified_by column."""
profile_key = (
task_model.GCITask.modified_by.get_value_for_datastore(entity))
if not profile_key:
return ''
else:
profile = ndb.Key.from_old_key(profile_key).get()
return profile.public_name
list_config.addPlainTextColumn(
'modified_by', 'Modified by', getModifiedBy, hidden=True)
list_config.addSimpleColumn('created_on', 'Created on',
column_type=lists.DATE, hidden=True)
list_config.addSimpleColumn('modified_on', 'Modified on',
column_type=lists.DATE, hidden=True)
list_config.addSimpleColumn('closed_on', 'Closed on',
column_type=lists.DATE, hidden=True)
list_config.addSimpleColumn('status', 'Status')
# TODO (madhu): Super temporary solution until the pretty lists are up.
list_config.addHtmlColumn(
'edit', 'Edit',
lambda entity, *args: (
'<a href="%s" style="color:#0000ff;text-decoration:underline;">'
'Edit</a>' % (data.redirect.id(entity.key().id()).urlOf(
'gci_edit_task'))))
list_config.setRowAction(
lambda entity, *args: (
data.redirect.id(entity.key().id()).urlOf('gci_view_task')))
# Add publish/unpublish buttons to the list and enable per-row checkboxes.
#
# It is very important to note that the setRowAction should go before
# addPostButton call for the checkbox to be present on the list.
# setRowAction sets multiselect attribute to False which is set to True
# by addPostButton method and should be True for the checkbox to be
# present on the list.
if data.is_org_admin:
# publish/unpublish tasks
bounds = [1, 'all']
# GCITask is keyed based solely on the entity ID, because it is very
# difficult to group it with either organizations or profiles, so to
# make the querying easier across entity groups we only use entity ids
# as keys.
keys = ['key']
list_config.addPostButton(
self.PUBLISH_BUTTON_ID, 'Publish', '', bounds, keys)
list_config.addPostButton(
self.UNPUBLISH_BUTTON_ID, 'Unpublish', '', bounds, keys)
self._list_config = list_config
def templatePath(self):
"""Returns the path to the template that should be used in render().
"""
return '_list.html'
def post(self):
"""Processes the form post data by checking what buttons were pressed."""
idx = lists.getListIndex(self.data.request)
if idx != self.IDX.value:
return None
data = self.data.POST.get('data')
if not data:
raise exception.BadRequest(message='Missing data')
parsed = json.loads(data)
button_id = self.data.POST.get('button_id')
if not button_id:
raise exception.BadRequest(message='Missing button_id')
if button_id == self.PUBLISH_BUTTON_ID:
return self.postPublish(parsed, True)
if button_id == self.UNPUBLISH_BUTTON_ID:
return self.postPublish(parsed, False)
raise exception.BadRequest(message="Unknown button_id")
def postPublish(self, data, publish):
"""Publish or unpublish tasks based on the value in the publish parameter.
Args:
data: Parsed post data containing the list of of task keys
publish: True if the task is to be published, False to unpublish
"""
for properties in data:
task_key = properties.get('key')
if not task_key:
logging.warning("Missing key in '%s'", properties)
continue
if not task_key.isdigit():
logging.warning("Invalid task id in '%s'", properties)
continue
task = GCITask.get_by_id(int(task_key))
if not task:
logging.warning("Task with task_id '%s' does not exist", task_key)
return
org_key = ndb.Key.from_old_key(
GCITask.org.get_value_for_datastore(task))
if not org_key in self.data.ndb_profile.admin_for:
logging.warning('Not an org admin')
return
if publish:
gci_task_logic.publishTask(task)
else:
gci_task_logic.unpublishTask(task)
return True
def context(self):
"""Returns the context of this component."""
task_list = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'all_org_tasks',
'title': 'All tasks for my organizations',
'lists': [task_list],
'description': ugettext('List of all tasks for my organization'),
}
def getListData(self):
"""Returns the list data as requested by the current request.
If the lists as requested is not supported by this component None is
returned.
"""
if lists.getListIndex(self.data.request) != self.IDX.value:
return None
q = GCITask.all()
q.filter('program', self.data.program)
q.filter(
'org IN',
map(lambda org_key: org_key.to_old_key(),
self.data.ndb_profile.mentor_for))
starter = lists.keyStarter
# TODO(daniel): enable prefetching
#prefetcher = lists.ListModelPrefetcher(
# GCITask, ['org', 'student', 'created_by', 'modified_by'], ['mentors'])
response_builder = lists.RawQueryContentResponseBuilder(
self.data.request, self._list_config, q, starter,
prefetcher=None)
return response_builder.build()
class ManagedOrganizationsComponent(Component):
"""Component for listing the organizations that are managed by
the current user.
"""
IDX = ComponentID.MANAGED_ORGANIZATIONS
def __init__(self, data):
"""Initializes the component.
Args:
data: request_data.RequestData object for the current request.
"""
self.data = data
list_config = lists.ListConfiguration()
list_config.addSimpleColumn('name', 'Name')
list_config.addSimpleColumn('org_id', 'Organization ID')
def getSurveyResponseCreatedOn(entity, *args):
"""Helper function to get a value for Created On column."""
app_response = org_logic.getApplicationResponse(entity.key)
return app_response.created_on if app_response else ''
list_config.addDateColumn(
'app_response_created_on', 'Questionnaire Submitted On',
getSurveyResponseCreatedOn)
def getSurveyResponseManage(entity, *args):
"""Helper function to get a value for Manage Questionnaire column."""
app_response = org_logic.getApplicationResponse(entity.key)
if app_response:
if self.data.timeline.beforeOrgSignupEnd():
return '<a href="%s">Update</a>' % (
links.ABSOLUTE_LINKER.organization(
entity.key,
urls.UrlNames.ORG_APPLICATION_SUBMIT,
secure=True))
else:
return '<a href="%s">View</a>' % (
links.ABSOLUTE_LINKER.organization(
entity.key,
urls.UrlNames.ORG_APPLICATION_RESPONSE_SHOW,
secure=True))
elif self.data.timeline.beforeOrgSignupEnd():
return '<a href="%s">Submit</a>' % (
links.ABSOLUTE_LINKER.organization(
entity.key,
urls.UrlNames.ORG_APPLICATION_SUBMIT,
secure=True))
else:
return 'Not submitted'
list_config.addHtmlColumn(
'app_response_manage', 'Manage Questionnaire',
getSurveyResponseManage)
def getLogoImage(entity, *args):
"""Helper function to get a value for Logo Image column."""
return '<a href="%s">Upload</a>' % (
links.LINKER.organization(entity.key, urls.UrlNames.ORG_LOGO_EDIT))
list_config.addHtmlColumn('logo_image', 'Logo', getLogoImage)
if self.data.timeline.orgsAnnounced():
def getPreferences(entity, *args):
"""Helper function to get a value for Preferences column."""
return '<a href="%s">Edit</a>' % (
links.LINKER.organization(
entity.key, urls.UrlNames.ORG_PREFERENCES_EDIT))
list_config.addHtmlColumn('preferences', 'Preferences', getPreferences)
list_config.setRowAction(
lambda entity, *args: links.LINKER.organization(
entity.key, urls.UrlNames.ORG_PROFILE_EDIT))
self._list_config = list_config
super(ManagedOrganizationsComponent, self).__init__(data)
def templatePath(self):
"""Returns the path to the template that should be used in render()."""
return '_list.html'
def context(self):
"""Returns the context of this component."""
list_configuration_response = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'org_app',
'title': 'Managed organizations',
'lists': [list_configuration_response],
'description': ugettext(
'Organizations for which you are an administrator.'),
}
def getListData(self):
"""Returns the list data as requested by the current request.
If the lists as requested is not supported by this component None is
returned.
"""
if lists.getListIndex(self.data.request) != self.IDX.value:
return None
orgs = ndb.get_multi(self.data.ndb_profile.admin_for)
response = lists.ListContentResponse(self.data.request, self._list_config)
for org in orgs:
response.addRow(org)
response.next = 'done'
return response
class MyOrgsList(Component):
"""Component for listing the orgs of the current user.
Since mentor_for is a list of orgs, we need to give org selection first
"""
IDX = ComponentID.MY_ORGS_LIST
def __init__(self, data):
"""Initializes the component.
Args:
data: The RequestData object
"""
super(MyOrgsList, self).__init__(data)
list_config = lists.ListConfiguration()
list_config.addSimpleColumn('name', 'Organization Name')
self._list_config = list_config
self._setRowAction(data.request, data)
# TODO(nathaniel): Drop the "request" parameter of this method.
def _setRowAction(self, request, data):
"""Since setRowAction can be vary, it must be implemented individually.
"""
raise NotImplementedError
def _getContext(self):
raise NotImplementedError
def templatePath(self):
"""Returns the path to the template that should be used in render().
"""
return '_list.html'
def context(self):
"""Returns the context of this component.
"""
return self._getContext()
def getListData(self):
"""Returns the list data as requested by the current request.
If the lists as requested is not supported by this component None is
returned.
"""
if lists.getListIndex(self.data.request) != self.IDX.value:
return None
response = lists.ListContentResponse(self.data.request, self._list_config)
for org_key in self.data.ndb_profile.mentor_for:
org = org_key.get()
if org.status == org_model.Status.ACCEPTED:
response.addRow(org)
response.next = 'done'
return response
class MyOrgsListBeforeCreateTask(MyOrgsList):
"""Component for listing the orgs of the current user, just before creating
task.
"""
IDX = ComponentID.MY_ORGS_LIST_BEFORE_CREATE_TASK
def _getContext(self):
org_list = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'create_tasks',
'title': 'Create Task',
'lists': [org_list],
'description': ugettext(
'Create task for students. Since you may '
'belong to more than one organization, you need to choose the '
'organization you will create the task for.')}
def _setRowAction(self, request, data):
self._list_config.setRowAction(
lambda entity, *args: (
links.LINKER.organization(entity.key, 'gci_create_task')))
class MyOrgsListBeforeBulkCreateTask(MyOrgsList):
"""Component for listing the orgs of the current user, just before creating
task.
"""
IDX = ComponentID.MY_ORGS_LIST_BEFORE_BULK_CREATE_TASK
def _getContext(self):
org_list = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'bulk_create_tasks',
'title': 'Bulk Upload Tasks',
'lists': [org_list],
'description': ugettext(
'Bulk upload tasks. Since you may '
'belong to more than one organization, you need to choose the '
'organization you will upload the tasks for.')}
def _setRowAction(self, request, data):
self._list_config.setRowAction(
lambda entity, *args: links.LINKER.organization(
entity.key, gci_url_names.GCI_TASK_BULK_CREATE))
class MyOrgsScoresList(MyOrgsList):
"""Component for listing all organizations for which the current user may
see scores of the students.
"""
IDX = ComponentID.MY_ORGS_SCORES_LIST
def _setRowAction(self, request, data):
self._list_config.setRowAction(
lambda entity, *args: (
links.LINKER.organization(
entity.key, gci_url_names.GCI_ORG_SCORES)))
def getListData(self):
if lists.getListIndex(self.data.request) != self.IDX.value:
return None
orgs = ndb.get_multi(self.data.ndb_profile.admin_for)
response = lists.ListContentResponse(self.data.request, self._list_config)
for org in orgs:
response.addRow(org)
response.next = 'done'
return response
def _getContext(self):
org_list = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'orgs_scores',
'title': 'Student scores for my organizations',
'lists': [org_list],
'description': ugettext('See the students who have completed '
'at least one task for your organizations.')}
class MyOrgsMentorsList(Component):
"""Component for listing the mentors of the orgs of the current user.
"""
IDX = ComponentID.MY_ORGS_MENTORS_LIST
def __init__(self, data):
"""Initializes the component.
Args:
data: The RequestData object
"""
super(MyOrgsMentorsList, self).__init__(data)
list_config = lists.ListConfiguration()
list_config.addSimpleColumn('public_name', 'Name')
list_config.addSimpleColumn('profile_id', 'Username')
list_config.addPlainTextColumn(
'email', 'Email', lambda entity, *args: entity.contact.email)
self._list_config = list_config
def templatePath(self):
"""Returns the path to the template that should be used in render().
"""
return '_list.html'
def context(self):
"""Returns the context of this component."""
list_configuration_response = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'all_orgs_mentors',
'title': 'All mentors for my organizations',
'lists': [list_configuration_response],
'description': ugettext('List of all mentors for my organizations'),
}
def getListData(self):
"""Returns the list data as requested by the current request.
If the lists as requested is not supported by this component None is
returned.
"""
if lists.getListIndex(self.data.request) != self.IDX.value:
return None
query = profile_logic.queryAllMentorsForOrg(
*self.data.ndb_profile.admin_for)
starter = lists.keyStarter
response_builder = lists.RawQueryContentResponseBuilder(
self.data.request, self._list_config, query, starter)
return response_builder.buildNDB()
class DocumentComponent(Component):
"""Component listing all the documents for the current user.
"""
IDX = ComponentID.DOCUMENT
def __init__(self, data):
"""Initializes this component.
"""
self.data = data
list_config = lists.ListConfiguration()
list_config.addPlainTextColumn(
'title', 'Title', lambda entity, *args: entity.name())
list_config.setRowAction(
lambda entity, *args: self.data.redirect.document(entity).urlOf(
'show_gci_document'))
self._list_config = list_config
super(DocumentComponent, self).__init__(data)
def templatePath(self):
return '_list.html'
def getListData(self):
idx = lists.getListIndex(self.data.request)
if idx != self.IDX.value:
return None
visibilities = gsoc_document_logic.getVisibilities(self.data.ndb_profile)
q = document_logic.getDocumentQueryForRoles(self.data, visibilities)
response_builder = lists.RawQueryContentResponseBuilder(
self.data.request, self._list_config, q, lists.keyStarter)
return response_builder.build()
def context(self):
list_config = lists.ListConfigurationResponse(
self.data, self._list_config, idx=self.IDX.value, preload_list=False)
return {
'name': 'documents',
'title': 'Important documents',
'lists': [list_config],
'description': ugettext('List of important documents'),
}