import uuid
from typing import List
from q2_sdk.core.exceptions import GridSizeError, RowTooLargeError
from q2_sdk.tools import jinja
[docs]
class BaseField:
def __init__(self):
self.required = False
self.template_name = "base_field.html"
[docs]
def serialize(self):
"""Generates Q2 compliant html"""
return jinja.jinja_generate(self.template_name, {"this": self})
[docs]
class CheckboxField(InputField):
"""Q2 Styled Checkbox field"""
def __init__(self, name: str, label: str, checked: bool = False):
"""
:param name: Will be the key on POST calls in self.form_fields
:param label: What the OnlineUser will see
:param checked: If True, Checkbox will start already checked
"""
super().__init__(name=name, label=label)
self.checked = checked
self.type = "checkbox"
[docs]
class PhoneField(InputField):
"""Q2 Styled Phone field"""
def __init__(self, name: str, label: str, required: bool = False, value: str = ""):
"""
:param name: Will be the key on POST calls in self.form_fields
:param label: What the OnlineUser will see
:param required: Adds validation and styling
:param value: Starting text
"""
super().__init__(name=name, label=label, required=required, value=value)
self.classes.append("phone")
[docs]
class SpanField(BaseField):
"""Q2 styled Span field"""
def __init__(self, text: str, span_id=None):
"""
:param text: What the OnlineUser will see
:param span_id: (Optional) Hardcode the span ID instead of generating one
"""
super().__init__()
self.template_name = "span_field.html"
text = str(text)
if span_id:
self.id = span_id
else:
self.id = "span_" + str(uuid.uuid1())[:6]
self.text = text
[docs]
class SelectOption:
"""To be provided as a list to Instances of SelectField"""
def __init__(self, key, value, selected: bool = False):
self.key = key
self.value = value
self.selected = selected
[docs]
class SelectField(BaseField):
"""Q2 styled Select field"""
def __init__(
self,
name: str,
label: str,
list_of_options: List[SelectOption],
required: bool = False,
):
"""
:param name: Will be the key on POST calls in self.form_fields
:param label: What the OnlineUser will see
:param list_of_options: Select box Options
:param required: Adds validation and styling
"""
super().__init__()
self.template_name = "select_field.html"
self.required = required
self.id = "select_" + name
self.name = name
self.label = label
self.list_of_options = list_of_options
[docs]
class CalendarPickerField(BaseField):
"""Q2 styled Calendar field"""
def __init__(self, name: str, label: str, required=False):
"""
:param name: Will be the key on POST calls in self.form_fields
:param label: What the OnlineUser will see
:param required: Adds validation and styling
"""
super().__init__()
self.template_name = "calendar_field.html"
self.id = "calendar_" + name
self.name = name
self.label = label
self.required = required
[docs]
class InternalLink(BaseField):
"""An anchor tag for navigating to a different route within the extension"""
def __init__(self, routing_key: str, label: str, target=None):
"""
:param routing_key: Routing key for internal link route target, fills href attribute
:param label: Link text
:param target: Anchor tag target attribute
"""
super().__init__()
self.template_name = "anchor_tag.html.jinja2"
self.routing_key = routing_key
self.label = label
self.target = target
if self.routing_key and self.routing_key[0] != "#":
self.routing_key = "#" + self.routing_key
[docs]
class ExternalLink(BaseField):
"""An anchor tag for navigating to an external location"""
def __init__(self, href: str, label: str, target="_blank"):
"""
:param href: Anchor tag href attribute, should be an external URL
:param label: Link text
:param target: Anchor tag target attribute
"""
super().__init__()
self.template_name = "anchor_tag.html.jinja2"
self.href = href
self.label = label
self.target = target
[docs]
class Row(BaseField):
"""
Takes a dynamic list of fields and renders appropriate grid using Javascript
Bootstrap (http://getbootstrap.com/javascript/#modals-grid-system)
"""
def __init__(self, list_of_fields: List[BaseField], grid_size: str = None):
"""
:param list_of_fields: List of instantiated BaseField elements
:param grid_size: Can be either None, XS, S, M, L
"""
super().__init__()
self.template_name = "row.html"
if len(list_of_fields) > 4:
raise RowTooLargeError("Only allowed to provide rows of 4 fields or less")
self.fields = list_of_fields
dynamic_size = int(12 / len(list_of_fields))
self.lg_grid_size = dynamic_size
self.md_grid_size = dynamic_size
self.sm_grid_size = dynamic_size
self.xs_grid_size = dynamic_size
if grid_size is None:
pass
elif grid_size == "L":
self.lg_grid_size = 12
self.md_grid_size = 12
self.sm_grid_size = 12
self.xs_grid_size = 12
elif grid_size == "M":
self.lg_grid_size = 6
self.md_grid_size = 6
self.sm_grid_size = 12
self.xs_grid_size = 12
elif grid_size == "S":
self.lg_grid_size = 3
self.md_grid_size = 4
self.sm_grid_size = 6
self.xs_grid_size = 12
elif grid_size == "XS":
self.lg_grid_size = 3
self.md_grid_size = 3
self.sm_grid_size = 6
self.xs_grid_size = 6
else:
raise GridSizeError("grid_size must be one of ['L', 'M', 'S', 'XS', None]")