Skip to content
This repository has been archived by the owner on Sep 5, 2019. It is now read-only.

Commit

Permalink
Adds an ordered multi checkbox field
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Krienbühl committed Sep 23, 2016
1 parent e6ded6f commit 85192e3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
4 changes: 4 additions & 0 deletions HISTORY.rst
@@ -1,5 +1,9 @@
Changelog
---------

- Adds an ordered multi checkbox field.
[href]

0.14.0 (2016-09-09)
~~~~~~~~~~~~~~~~~~~

Expand Down
8 changes: 7 additions & 1 deletion onegov/form/fields.py
Expand Up @@ -3,7 +3,9 @@
import magic

from io import BytesIO
from onegov.form.widgets import MultiCheckboxWidget, UploadWidget
from onegov.form.widgets import MultiCheckboxWidget
from onegov.form.widgets import OrderedMultiCheckboxWidget
from onegov.form.widgets import UploadWidget
from wtforms import FileField, SelectMultipleField, widgets


Expand All @@ -17,6 +19,10 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)


class OrderedMultiCheckboxField(MultiCheckboxField):
widget = OrderedMultiCheckboxWidget()


class UploadField(FileField):
""" A custom file field that turns the uploaded file into a compressed
base64 string together with the filename, size and mimetype.
Expand Down
32 changes: 32 additions & 0 deletions onegov/form/tests/test_fields.py
@@ -1,10 +1,13 @@
import base64
import re
import tempfile

from cgi import FieldStorage
from gzip import GzipFile
from io import BytesIO
from onegov.form import Form
from onegov.form.fields import MultiCheckboxField
from onegov.form.fields import OrderedMultiCheckboxField
from onegov.form.fields import UploadField


Expand Down Expand Up @@ -35,3 +38,32 @@ def decompress(data):
return f.read()

assert decompress(base64.b64decode(data['data'])) == b'foobar'


def test_ordered_multi_checkbox_field():
ordinary = MultiCheckboxField(choices=[
('c', 'C'),
('b', 'B'),
('a', 'A')
])
ordered = OrderedMultiCheckboxField(choices=[
('c', 'C'),
('b', 'B'),
('a', 'A')
])
ordinary = ordinary.bind(Form(), 'choices')
ordered = ordered.bind(Form(), 'choices')

ordinary.data = ordered.data = []

assert re.findall(r'value="((a|b|c){1})"', ordinary()) == [
('c', 'c'),
('b', 'b'),
('a', 'a'),
]

assert re.findall(r'value="((a|b|c){1})"', ordered()) == [
('a', 'a'),
('b', 'b'),
('c', 'c'),
]
38 changes: 37 additions & 1 deletion onegov/form/widgets.py
Expand Up @@ -6,14 +6,50 @@
from wtforms.widgets.core import HTMLString


class OrderedListWidget(ListWidget):
""" Extends the default list widget with automated ordering using the
translated text of each element.
"""

def __call__(self, field, **kwargs):

# ListWidget expects a field internally, but it will only use
# its id property and __iter__ method, so we can get away
# with passing a fake field with an id and an iterator.
#
# It's not great, since we have to assume internal knowledge,
# but builting a new field or changing the existing one would
# require even more knowledge, so this is the better approach
#
# We also need to call each field once so it gets hooked up with
# our translation machinary
ordered = [subfield for subfield in field]
ordered.sort(key=lambda f: (f(), str(f.label.text))[1])

class FakeField(object):

id = field.id

def __iter__(self):
return iter(ordered)

return super().__call__(FakeField(), **kwargs)


class MultiCheckboxWidget(ListWidget):
""" The default wtforms ListWidget, extended different default values. """
""" The default list widget with the label behind the checkbox. """

def __init__(self, *args, **kwargs):
kwargs['prefix_label'] = False
super().__init__(*args, **kwargs)


class OrderedMultiCheckboxWidget(MultiCheckboxWidget, OrderedListWidget):
""" The sorted list widget with the label behind the checkbox. """
pass


class CoordinateWidget(TextInput):
""" Widget containing the coordinates for the
:class:`onegov.form.fields.CoordinateField` class.
Expand Down

0 comments on commit 85192e3

Please sign in to comment.