blob: 603fdf4aaac6bd1977a1b8b270efcfe12023d9c8 [file] [log] [blame]
# 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 a template to display read-only sets of data."""
import collections
from django.template import loader
from soc.views import template
from soc.views.helper import surveys
class Group(template.Template):
"""Class that forms different fields together into a group.
Attributes:
title: Title of the group.
fields: Fields that belong to the group.
"""
def __init__(self, data, template_path, title, fields):
"""Initializes a new group for the specified attributes.
Args:
data: request_data.RequestData object for the current request.
template_path: Path to the HTML template to use for rendering.
title: Title of the group.
fields: A dict containing label-value pairs that belong to the group.
"""
super(Group, self).__init__(data)
self._template_path = template_path
self.title = title
self.fields = fields
def render(self):
"""Renders the template as HTML.
Returns:
A string containing HTML form of the template.
"""
context = {
'title': self.title,
'fields': self.fields,
}
return loader.render_to_string(self._template_path, dictionary=context)
class Readonly(template.Template):
"""Template to list items in read-only manner."""
def __init__(self, data, template_path, groups):
"""Initializes a new instance of this class.
Args:
data: request_data.RequestData object for the current request.
template_path: Path to the HTML template to use for rendering.
groups: List of groups to include in the template.
"""
super(Readonly, self).__init__(data)
self._template_path = template_path
self._groups = groups
def render(self):
"""Renders the template as HTML.
Returns:
A string containing HTML form of the template.
"""
context = {'groups': self._groups}
return loader.render_to_string(self._template_path, dictionary=context)
class ReadonlyBuilder(object):
"""Builder to construct instances of Readonly class."""
def __init__(self):
"""Initializes a new builder."""
self._group_descriptors = []
self._values = {}
self._fields_to_remove = set()
self._template_path = None
self._group_template_path = None
self._group_template_path_map = {}
def addGroupDescriptor(self, group_descriptor):
"""Updates the builder by adding a new group descriptor to the end of the
read-only template which is being built.
Args:
group_descriptor: A GroupDescriptor to be added.
"""
self._group_descriptors.append(group_descriptor)
def setGroupTemplatePath(self, template_path, group_id=None):
"""Updates the builder by setting template path to render the groups.
Args:
template_path: Path to the HTML template to use for rendering.
group_id: Optional string identifier of the group to which the template
path applies.
"""
if not group_id:
self._group_template_path = template_path
else:
self._group_template_path_map[group_id] = template_path
def setTemplatePath(self, template_path):
"""Updates the builder by setting template path for the read-only template.
Args:
template_path: Path to the HTML template to use for rendering.
"""
self._template_path = template_path
def setValue(self, field_id, value):
"""Updates the builder by setting the specified value for the field with
the specified identifier.
Args:
field_id: A string identifier of the field to set the value for.
value: The value to set for the field.
"""
self._values[field_id] = value
def setValues(self, values):
"""Updates the builder by setting the specified values.
Args:
values: A dict mapping field identifiers to the corresponding values.
"""
self._values.update(values)
def removeField(self, field_id):
"""Removes the field with the specified identifier from the template
which is being built.
Args:
field_id: A string identifier of the field to remove.
"""
self._fields_to_remove.add(field_id)
def build(self, data):
"""Builds Readonly template.
Args:
data: request_data.RequestData object for the current request.
Returns:
Newly created Readonly object.
"""
if not self._template_path:
raise ValueError('No template path set for the template')
groups = []
for group_descriptor in self._group_descriptors:
if group_descriptor.group_id:
group_template_path = self._group_template_path_map.get(
group_descriptor.group_id, self._group_template_path)
elif self._group_template_path:
group_template_path = self._group_template_path
else:
raise ValueError('No template path set for at least one group')
fields = collections.OrderedDict()
for field_descriptor in group_descriptor.field_descriptors:
# skip the field if it has been removed
if field_descriptor.field_id in self._fields_to_remove:
continue
# include the field only if the value has been set explicitly
if field_descriptor.field_id in self._values:
fields[field_descriptor.label] = (
self._values[field_descriptor.field_id])
groups.append(
Group(data, group_template_path, group_descriptor.title, fields))
return Readonly(data, self._template_path, groups)
class GroupDescriptor(object):
"""Descriptor of a single group to be included in Readonly template.
Attributes:
title: A string containing title of the group.
field_descriptors: A list of FieldDescriptors to be included in the group.
group_id: A string containing an identifier of the group or None
if not specified.
"""
def __init__(self, title, field_descriptors, group_id=None):
"""Initializes a new descriptor based on the specified arguments.
Args:
title: A string containing title of the group.
field_descriptors: A list of FieldDescriptors to be included in the group.
group_id: An optional string containing an identifier of the group.
"""
self.title = title
self.field_descriptors = field_descriptors
self.group_id = group_id
class SurveyGroupDescriptor(GroupDescriptor):
"""Group descriptor for a survey."""
def __init__(self, title, survey, group_id=None):
"""Initializes a new descriptor based on the specified survey.
Args:
title: A string containing title of the group.
survey: A survey entity.
group_id: A string containing an optional identifier of the group.
"""
schema = surveys.SurveySchema(survey) if survey else None
field_descriptors = ([
FieldDescriptor(question.getPropertyName(), question.getLabel())
for question in schema]
if schema
else [])
super(SurveyGroupDescriptor, self).__init__(
title, field_descriptors, group_id=group_id)
FieldDescriptor = collections.namedtuple(
'FieldDescriptor', ['field_id', 'label'])