Add custom widget for "percent" field

so that storage can use "traditional" (0.3612) format but UI can use
"human-friendly" format (36.12 %)
This commit is contained in:
Lance Edgar 2019-01-08 12:18:48 -06:00
parent 7bf509097f
commit d659e62fda
2 changed files with 57 additions and 2 deletions

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2018 Lance Edgar # Copyright © 2010-2019 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -24,10 +24,11 @@
Form Widgets Form Widgets
""" """
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import, division
import json import json
import datetime import datetime
import decimal
import six import six
@ -55,6 +56,35 @@ class NumberInputWidget(dfwidget.TextInputWidget):
autocomplete = 'off' 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): class PlainSelectWidget(dfwidget.SelectWidget):
template = 'select_plain' template = 'select_plain'

View file

@ -0,0 +1,25 @@
<span tal:define="name name|field.name;
css_class css_class|field.widget.css_class;
oid oid|field.oid;
mask mask|field.widget.mask;
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
style style|field.widget.style;
autocomplete autocomplete|field.widget.autocomplete|'off';
"
tal:omit-tag="">
<input type="text" name="${name}" value="${cstruct}"
tal:attributes="class string: form-control ${css_class or ''};
style style;
autocomplete autocomplete;
"
id="${oid}"/>
%
<script tal:condition="mask" type="text/javascript">
deform.addCallback(
'${oid}',
function (oid) {
$("#" + oid).mask("${mask}",
{placeholder:"${mask_placeholder}"});
});
</script>
</span>