mirror of
https://github.com/wagtail/wagtail.git
synced 2024-12-01 11:41:20 +01:00
Move FilteredSelect to wagtail.admin.widgets
This commit is contained in:
parent
35c55091af
commit
36780a9f56
@ -1,10 +1,8 @@
|
||||
import django_filters
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_filters.widgets import SuffixedMultiWidget
|
||||
|
||||
from wagtail.admin.staticfiles import versioned_static
|
||||
from wagtail.admin.widgets import AdminDateInput, BooleanButtonSelect, ButtonSelect
|
||||
from wagtail.admin.widgets import AdminDateInput, BooleanButtonSelect, ButtonSelect, FilteredSelect
|
||||
from wagtail.core.models import Page, Task, TaskState, Workflow, WorkflowState
|
||||
|
||||
|
||||
@ -25,88 +23,6 @@ class DateRangePickerWidget(SuffixedMultiWidget):
|
||||
return [None, None]
|
||||
|
||||
|
||||
class FilteredSelect(forms.Select):
|
||||
"""
|
||||
A select box variant that adds 'data-' attributes to the <select> and <option> elements
|
||||
to allow the options to be dynamically filtered by another select box.
|
||||
See wagtailadmin/js/filtered-select.js for an example of how these attributes are configured.
|
||||
"""
|
||||
|
||||
def __init__(self, attrs=None, choices=(), filter_field=''):
|
||||
super().__init__(attrs, choices)
|
||||
self.filter_field = filter_field
|
||||
|
||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||
my_attrs = {
|
||||
'data-widget': 'filtered-select',
|
||||
'data-filter-field': self.filter_field,
|
||||
}
|
||||
if extra_attrs:
|
||||
my_attrs.update(extra_attrs)
|
||||
|
||||
return super().build_attrs(base_attrs, my_attrs)
|
||||
|
||||
def optgroups(self, name, value, attrs=None):
|
||||
# copy of Django's Select.optgroups, modified to accept filter_value as a
|
||||
# third item in the tuple and expose that as a data-filter-value attribute
|
||||
# on the final <option>
|
||||
groups = []
|
||||
has_selected = False
|
||||
|
||||
for index, choice in enumerate(self.choices):
|
||||
try:
|
||||
(option_value, option_label, filter_value) = choice
|
||||
except ValueError:
|
||||
# *ChoiceField will still output blank options as a 2-tuple,
|
||||
# so need to handle that too
|
||||
(option_value, option_label) = choice
|
||||
filter_value = None
|
||||
|
||||
if option_value is None:
|
||||
option_value = ''
|
||||
|
||||
subgroup = []
|
||||
if isinstance(option_label, (list, tuple)):
|
||||
group_name = option_value
|
||||
subindex = 0
|
||||
choices = option_label
|
||||
else:
|
||||
group_name = None
|
||||
subindex = None
|
||||
choices = [(option_value, option_label)]
|
||||
groups.append((group_name, subgroup, index))
|
||||
|
||||
for subvalue, sublabel in choices:
|
||||
selected = (
|
||||
str(subvalue) in value
|
||||
and (not has_selected or self.allow_multiple_selected)
|
||||
)
|
||||
has_selected |= selected
|
||||
|
||||
subgroup.append(self.create_option(
|
||||
name, subvalue, sublabel, selected, index, subindex=subindex,
|
||||
filter_value=filter_value
|
||||
))
|
||||
if subindex is not None:
|
||||
subindex += 1
|
||||
return groups
|
||||
|
||||
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None, filter_value=None):
|
||||
option = super().create_option(
|
||||
name, value, label, selected, index, subindex=subindex, attrs=attrs
|
||||
)
|
||||
if filter_value is not None:
|
||||
option['attrs']['data-filter-value'] = filter_value
|
||||
|
||||
return option
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
return forms.Media(js=[
|
||||
versioned_static('wagtailadmin/js/filtered-select.js'),
|
||||
])
|
||||
|
||||
|
||||
class FilteredModelChoiceIterator(django_filters.fields.ModelChoiceIterator):
|
||||
"""
|
||||
A variant of Django's ModelChoiceIterator that, instead of yielding (value, label) tuples,
|
||||
|
@ -3,4 +3,5 @@ from wagtail.admin.widgets.button import * # NOQA
|
||||
from wagtail.admin.widgets.button_select import * # NOQA
|
||||
from wagtail.admin.widgets.chooser import * # NOQA
|
||||
from wagtail.admin.widgets.datetime import * # NOQA
|
||||
from wagtail.admin.widgets.filtered_select import * # NOQA
|
||||
from wagtail.admin.widgets.tags import * # NOQA
|
||||
|
85
wagtail/admin/widgets/filtered_select.py
Normal file
85
wagtail/admin/widgets/filtered_select.py
Normal file
@ -0,0 +1,85 @@
|
||||
from django import forms
|
||||
|
||||
from wagtail.admin.staticfiles import versioned_static
|
||||
|
||||
|
||||
class FilteredSelect(forms.Select):
|
||||
"""
|
||||
A select box variant that adds 'data-' attributes to the <select> and <option> elements
|
||||
to allow the options to be dynamically filtered by another select box.
|
||||
See wagtailadmin/js/filtered-select.js for an example of how these attributes are configured.
|
||||
"""
|
||||
|
||||
def __init__(self, attrs=None, choices=(), filter_field=''):
|
||||
super().__init__(attrs, choices)
|
||||
self.filter_field = filter_field
|
||||
|
||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||
my_attrs = {
|
||||
'data-widget': 'filtered-select',
|
||||
'data-filter-field': self.filter_field,
|
||||
}
|
||||
if extra_attrs:
|
||||
my_attrs.update(extra_attrs)
|
||||
|
||||
return super().build_attrs(base_attrs, my_attrs)
|
||||
|
||||
def optgroups(self, name, value, attrs=None):
|
||||
# copy of Django's Select.optgroups, modified to accept filter_value as a
|
||||
# third item in the tuple and expose that as a data-filter-value attribute
|
||||
# on the final <option>
|
||||
groups = []
|
||||
has_selected = False
|
||||
|
||||
for index, choice in enumerate(self.choices):
|
||||
try:
|
||||
(option_value, option_label, filter_value) = choice
|
||||
except ValueError:
|
||||
# *ChoiceField will still output blank options as a 2-tuple,
|
||||
# so need to handle that too
|
||||
(option_value, option_label) = choice
|
||||
filter_value = None
|
||||
|
||||
if option_value is None:
|
||||
option_value = ''
|
||||
|
||||
subgroup = []
|
||||
if isinstance(option_label, (list, tuple)):
|
||||
group_name = option_value
|
||||
subindex = 0
|
||||
choices = option_label
|
||||
else:
|
||||
group_name = None
|
||||
subindex = None
|
||||
choices = [(option_value, option_label)]
|
||||
groups.append((group_name, subgroup, index))
|
||||
|
||||
for subvalue, sublabel in choices:
|
||||
selected = (
|
||||
str(subvalue) in value
|
||||
and (not has_selected or self.allow_multiple_selected)
|
||||
)
|
||||
has_selected |= selected
|
||||
|
||||
subgroup.append(self.create_option(
|
||||
name, subvalue, sublabel, selected, index, subindex=subindex,
|
||||
filter_value=filter_value
|
||||
))
|
||||
if subindex is not None:
|
||||
subindex += 1
|
||||
return groups
|
||||
|
||||
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None, filter_value=None):
|
||||
option = super().create_option(
|
||||
name, value, label, selected, index, subindex=subindex, attrs=attrs
|
||||
)
|
||||
if filter_value is not None:
|
||||
option['attrs']['data-filter-value'] = filter_value
|
||||
|
||||
return option
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
return forms.Media(js=[
|
||||
versioned_static('wagtailadmin/js/filtered-select.js'),
|
||||
])
|
Loading…
Reference in New Issue
Block a user