| # Copyright 2014 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 ActionsRequired template.""" |
| |
| from google.appengine.ext import ndb |
| |
| from django.utils import translation |
| |
| from melange.logic import organization as org_logic |
| from melange.logic import profile as profile_logic |
| from melange.request import links |
| from melange.templates.helper import links as links_helper |
| |
| from soc.views import template |
| |
| |
| _BACKUP_ADMIN_NEEDED_ID_PREFIX = 'backup-admin-needed-action-' |
| |
| _BACKUP_ADMIN_NEEDED_TITLE = translation.ugettext( |
| '%s needs backup administrator') |
| |
| _BACKUP_ADMIN_NEEDED_DETAILS = translation.ugettext( |
| 'Your organization needs at least one other organization administrator. ' |
| 'The program requires two organization administrator per organization.<br>' |
| 'Please use the link below to start a connection with another member of ' |
| 'your community it order to assign the role.<br>' |
| 'Please note that the backup administrator will be assigned only if the ' |
| 'connected user explicitly accepts the role.<br>' |
| 'If you fail to provide another administrator, the organization will not ' |
| 'be eligible to participate in the program and will be rejected.') |
| |
| _LOGO_NEEDED_TITLE = translation.ugettext('%s needs logo') |
| |
| _LOGO_NEEDED_DETAILS = translation.ugettext( |
| 'Your organization still needs to upload a logo image. ' |
| 'Should the organization be accepted, the logo will be displayed on ' |
| 'the list of all accepted organizations.') |
| |
| _APP_RESPONSE_NEEDED_ID_PREFIX = 'app-response-needed-action-' |
| |
| _APP_RESPONSE_NEEDED_TITLE = translation.ugettext( |
| 'No questionnaire submitted for %s') |
| |
| _APP_RESPONSE_DETAILS = translation.ugettext( |
| 'Your organization has not completed the required organization ' |
| 'application questionnaire. If it is not completed before the deadline, ' |
| 'your organization will not be eligible to participate in the program.') |
| |
| |
| class ActionItem(object): |
| """Interface that describes a single action which is currently required.""" |
| |
| @property |
| def identifier(self): |
| """Returns a string identifier of the item. |
| |
| All identifiers returned by implementations of this interface should be |
| unique across one page. |
| """ |
| raise NotImplementedError |
| |
| @property |
| def title(self): |
| """Returns a title of this item.""" |
| raise NotImplementedError |
| |
| @property |
| def details(self): |
| """Returns more details for this item.""" |
| raise NotImplementedError |
| |
| @property |
| def deadline(self): |
| """Returns deadline for the item or None if there is no deadline.""" |
| raise NotImplementedError |
| |
| @property |
| def link(self): |
| """Returns a link associated with this item.""" |
| raise NotImplementedError |
| |
| |
| class BackupAdminNeededActionItem(ActionItem): |
| """Implementation of ActionItem that states that backup administrator is |
| needed for the specified organization. |
| """ |
| |
| def __init__(self, organization, deadline, url_names): |
| """Initializes a new instance of this action item. |
| |
| Args: |
| organization: org_model.Organization entity. |
| deadline: datetime.datetime object telling by when the action has to |
| be completed. |
| url_names: |
| """ |
| self._organization = organization |
| self._deadline = deadline |
| self._url_names = url_names |
| |
| @property |
| def identifier(self): |
| """See ActionItem.identifier for specification.""" |
| return _BACKUP_ADMIN_NEEDED_ID_PREFIX + self._organization.org_id |
| |
| @property |
| def title(self): |
| """See ActionItem.title for specification.""" |
| return _BACKUP_ADMIN_NEEDED_TITLE % self._organization.name |
| |
| @property |
| def details(self): |
| """See ActionItem.details for specification.""" |
| return _BACKUP_ADMIN_NEEDED_DETAILS |
| |
| @property |
| def deadline(self): |
| """See ActionItem.deadline for specification.""" |
| return self._deadline |
| |
| @property |
| def link(self): |
| """See ActionItem.link for specification.""" |
| return links_helper.Link( |
| links.LINKER.organization( |
| self._organization.key, self._url_names.CONNECTION_START_AS_ORG), |
| 'Start connection') |
| |
| |
| def createBackupAdminNeededActionItem(data, url_names): |
| """Factory function for BackupAdminNeededActionItem class. |
| |
| Args: |
| data: request_data.RequestData for the current request. |
| url_names: Instance of url_names.UrlNames. |
| |
| Returns: |
| A list of created BackupAdminNeededActionItem instances. |
| """ |
| if not data.ndb_profile or not data.ndb_profile.is_admin: |
| # this action makes sense to organization administrators only |
| return [] |
| elif data.timeline.orgsAnnounced(): |
| # this action is applicable only during organization application period |
| return [] |
| else: |
| items = [] |
| |
| organizations = ndb.get_multi(data.ndb_profile.admin_for) |
| for organization in organizations: |
| admin_keys = profile_logic.getOrgAdmins(organization, keys_only=True) |
| |
| if len(admin_keys) > 1: |
| # there are more organization admins, so everything is fine |
| continue |
| |
| items.append( |
| BackupAdminNeededActionItem( |
| organization, data.timeline.orgSignupEnd(), url_names)) |
| |
| return items |
| |
| |
| class LogoNeededActionItem(ActionItem): |
| """Implementation of ActionItem that states that logo image still needs to |
| be uploaded for the specified organization. |
| """ |
| |
| def __init__(self, organization, deadline, url_names): |
| """Initializes a new instance of this action item. |
| |
| Args: |
| organization: org_model.Organization entity. |
| deadline: datetime.datetime object telling by when the action has to |
| be completed. |
| url_names: Instance of url_names.UrlNames. |
| """ |
| self._organization = organization |
| self._deadline = deadline |
| self._url_names = url_names |
| |
| @property |
| def identifier(self): |
| """See ActionItem.identifier for specification.""" |
| return 'logo-needed-action-' + self._organization.org_id |
| |
| @property |
| def title(self): |
| """See ActionItem.title for specification.""" |
| return _LOGO_NEEDED_TITLE % self._organization.name |
| |
| @property |
| def details(self): |
| """See ActionItem.details for specification.""" |
| return _LOGO_NEEDED_DETAILS |
| |
| @property |
| def deadline(self): |
| """See ActionItem.deadline for specification.""" |
| return self._deadline |
| |
| @property |
| def link(self): |
| """See ActionItem.link for specification.""" |
| return links_helper.Link( |
| links.LINKER.organization( |
| self._organization.key, self._url_names.ORG_LOGO_EDIT), |
| 'Upload logo') |
| |
| |
| def createLogoNeededActionItem(data, url_names): |
| """Factory function for LogoNeededActionItem class. |
| |
| Args: |
| data: request_data.RequestData for the current request. |
| url_names: Instance of url_names.UrlNames. |
| |
| Returns: |
| A newly created LogoNeededActionItem instance. |
| """ |
| if not data.ndb_profile or not data.ndb_profile.is_admin: |
| # this action makes sense to organization administrators only |
| return [] |
| else: |
| items = [] |
| |
| organizations = ndb.get_multi(data.ndb_profile.admin_for) |
| for organization in organizations: |
| if not organization.logo_path: |
| items.append( |
| LogoNeededActionItem( |
| organization, data.timeline.orgSignupEnd(), url_names)) |
| |
| return items |
| |
| |
| class AppResponseNeededAction(ActionItem): |
| """Implementation of ActionItem that states that application response has |
| yet to be submitted for the specified organization. |
| """ |
| |
| def __init__(self, organization, deadline, url_names): |
| """Initializes a new instance of this action item. |
| |
| Args: |
| organization: org_model.Organization entity. |
| deadline: datetime.datetime object telling by when the action has to |
| be completed. |
| url_names: Instance of url_names.UrlNames. |
| """ |
| self._organization = organization |
| self._deadline = deadline |
| self._url_names = url_names |
| |
| @property |
| def identifier(self): |
| """See ActionItem.identifier for specification.""" |
| return _APP_RESPONSE_NEEDED_ID_PREFIX + self._organization.org_id |
| |
| @property |
| def title(self): |
| """See ActionItem.title for specification.""" |
| return _APP_RESPONSE_NEEDED_TITLE % self._organization.name |
| |
| @property |
| def details(self): |
| """See ActionItem.details for specification.""" |
| return _APP_RESPONSE_DETAILS |
| |
| @property |
| def deadline(self): |
| """See ActionItem.deadline for specification.""" |
| return self._deadline |
| |
| @property |
| def link(self): |
| """See ActionItem.link for specification.""" |
| return links_helper.Link( |
| links.LINKER.organization( |
| self._organization.key, self._url_names.ORG_APPLICATION_SUBMIT), |
| 'Questionnaire') |
| |
| |
| def createAppResponseNeededActionItems(data, url_names): |
| """Factory function for AppResponseNeededAction class. |
| |
| Args: |
| data: request_data.RequestData for the current request. |
| url_names: Instance of url_names.UrlNames. |
| |
| Returns: |
| A list of created BackupAdminNeededActionItem instances. |
| """ |
| if not data.ndb_profile or not data.ndb_profile.is_admin: |
| # this action makes sense to organization administrators only |
| return [] |
| elif not data.timeline.beforeOrgSignupEnd(): |
| # this action is applicable only when org application survey is open |
| return [] |
| else: |
| # check for any organizations this profile is an admin for |
| # that are missing the application questionnaire response |
| items = [] |
| |
| organizations = ndb.get_multi(data.ndb_profile.admin_for) |
| for organization in organizations: |
| if not org_logic.hasApplicationResponse(organization.key): |
| items.append( |
| AppResponseNeededAction( |
| organization, data.timeline.orgSignupEnd(), url_names)) |
| |
| return items |
| |
| |
| class ActionsRequired(template.Template): |
| """Action Required template.""" |
| |
| def __init__(self, data, items, template_path): |
| """Initializes a new instance of this template. |
| |
| Args: |
| data: request_data.RequestData for the current request. |
| items: A list of ActionItem instances to be displayed by the template. |
| template_path: Path to the HTML template to use for rendering. |
| """ |
| super(ActionsRequired, self).__init__(data) |
| self._items = items |
| self._template_path = template_path |
| |
| def context(self): |
| """See template.Template.context for specification.""" |
| return {'items': self._items} |
| |
| def templatePath(self): |
| """See template.Template.templatePath for specification.""" |
| return 'modules/gsoc/homepage/_action_required.html' |