murano-dashboard/muranodashboard/common/widgets.py
Andrew Pashkin e096fbfa3c Tri-state checkbox widget
Tri-state checkbox is the kind of checkbox which has three states
instead of two, as the regular checkbox has.

Third state is "indeterminate", which means, that the element is in
undefined state. Common example of such situation is some parent
element, which has some of child elements selected and some not - and
so it means that parent element is not selected nor unselect - which
in terminology of this changeset called "indeterminate" state.

Partially implements bp assign-category-button
Depends-On: Ie65a77eab29aa191420fbd630b1d242b59c9ff9f
Change-Id: I98116fce362af5eb4c64941f4c442dd81120e762
2017-04-11 00:02:11 +01:00

97 lines
3.0 KiB
Python

# Copyright (c) 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import itertools as it
import floppyforms as floppy
class TriStateCheckboxSelectMultiple(floppy.widgets.Input):
"""Renders tri-state multi-selectable checkbox.
.. note:: Subclassed from ``CheckboxSelectMultiple`` and not from
``SelectMultiple`` only to make
``horizon.templatetags.form_helpers.is_checkbox`` able to recognize
this widget.
Otherwise template ``horizon/common/_form_field.html`` would render
this widget slightly incorrectly.
"""
template_name = 'common/tri_state_checkbox/base.html'
VALUES_MAP = {
'True': True,
'False': False,
'None': None
}
def get_context(self, name, value, attrs=None, choices=()):
"""Renders html and JavaScript.
:param value: Dictionary of form
Choice => Value (Checked|Uncheckec|Indeterminate)
:type value: dict
"""
context = super(TriStateCheckboxSelectMultiple, self).get_context(
name, value, attrs
)
choices = dict(it.chain(self.choices, choices))
if value is None:
value = dict.fromkeys(choices, False)
else:
value = dict(dict.fromkeys(choices, False).items() +
value.items())
context['values'] = [
(choice, label, value[choice])
for choice, label in choices.iteritems()
]
return context
@classmethod
def parse_value(cls, value):
"""Converts encoded string with value to Python values."""
choice, value = value.split('=')
value = cls.VALUES_MAP[value]
return choice, value
def value_from_datadict(self, data, files, name):
"""Expects values in ``"key=False/True/None"`` form."""
try:
values = data.getlist(name)
except AttributeError:
if name in data:
values = [data[name]]
else:
values = []
return dict(map(self.parse_value, values))
class ExtraContextWidgetMixin(object):
def __init__(self, *args, **kwargs):
super(ExtraContextWidgetMixin, self).__init__(*args, **kwargs)
self.extra_context = kwargs.pop('extra_context', {})
def get_context(self, *args, **kwargs):
context = super(ExtraContextWidgetMixin, self).get_context(
*args, **kwargs
)
context.update(self.extra_context)
return context