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:
		
							parent
							
								
									7bf509097f
								
							
						
					
					
						commit
						d659e62fda
					
				
					 2 changed files with 57 additions and 2 deletions
				
			
		|  | @ -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' | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								tailbone/templates/deform/percentinput.pt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tailbone/templates/deform/percentinput.pt
									
										
									
									
									
										Normal 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> | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar