From d659e62fda35fdf6b7a845373d6f2a86fca13cd3 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 8 Jan 2019 12:18:48 -0600 Subject: [PATCH] Add custom widget for "percent" field so that storage can use "traditional" (0.3612) format but UI can use "human-friendly" format (36.12 %) --- tailbone/forms/widgets.py | 34 +++++++++++++++++++++-- tailbone/templates/deform/percentinput.pt | 25 +++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 tailbone/templates/deform/percentinput.pt diff --git a/tailbone/forms/widgets.py b/tailbone/forms/widgets.py index 9374021d..7c89fa7d 100644 --- a/tailbone/forms/widgets.py +++ b/tailbone/forms/widgets.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2018 Lance Edgar +# Copyright © 2010-2019 Lance Edgar # # This file is part of Rattail. # @@ -24,10 +24,11 @@ Form Widgets """ -from __future__ import unicode_literals, absolute_import +from __future__ import unicode_literals, absolute_import, division import json import datetime +import decimal import six @@ -55,6 +56,35 @@ class NumberInputWidget(dfwidget.TextInputWidget): autocomplete = 'off' +class PercentInputWidget(dfwidget.TextInputWidget): + """ + Custom text input widget, used for "percent" type fields. This widget + assumes that the underlying storage for the value is a "traditional" + percent value, e.g. ``0.36135`` - but the UI should represent this as a + "human-friendly" value, e.g. ``36.135 %``. + """ + template = 'percentinput' + autocomplete = 'off' + + def serialize(self, field, cstruct, **kw): + if cstruct not in (colander.null, None): + # convert "traditional" value to "human-friendly" + value = decimal.Decimal(cstruct) * 100 + value = value.quantize(decimal.Decimal('0.001')) + cstruct = six.text_type(value) + return super(PercentInputWidget, self).serialize(field, cstruct, **kw) + + def deserialize(self, field, pstruct): + pstruct = super(PercentInputWidget, self).deserialize(field, pstruct) + if pstruct is colander.null: + return colander.null + # convert "human-friendly" value to "traditional" + value = decimal.Decimal(pstruct) + value = value.quantize(decimal.Decimal('0.00001')) + value /= 100 + return six.text_type(value) + + class PlainSelectWidget(dfwidget.SelectWidget): template = 'select_plain' diff --git a/tailbone/templates/deform/percentinput.pt b/tailbone/templates/deform/percentinput.pt new file mode 100644 index 00000000..59b15341 --- /dev/null +++ b/tailbone/templates/deform/percentinput.pt @@ -0,0 +1,25 @@ + + + % + +