summaryrefslogtreecommitdiffstats
path: root/src/workflow/forms.py
diff options
context:
space:
mode:
authorParker Berberian <pberberian@iol.unh.edu>2019-06-18 14:58:27 -0400
committerParker Berberian <pberberian@iol.unh.edu>2019-06-21 10:56:34 -0400
commit46ab5d82161a4a6ee368dc2adf6e0ca0dea38799 (patch)
tree5f660380f3947599e3cba7714c2192509f6e2045 /src/workflow/forms.py
parent5c83c9af403d38218206a0f1370b966f768ad62e (diff)
Redesigns Multiple Select Filter Widget
Makes the filter widget work as it should so that it can be integrated with the rest of the Django form handling nicely. Also fixes a lot of ugly code tangential to the widget. Change-Id: Ib92db8e584f3d2162c6c43a18b75a57273bb18f5 Signed-off-by: Parker Berberian <pberberian@iol.unh.edu>
Diffstat (limited to 'src/workflow/forms.py')
-rw-r--r--src/workflow/forms.py169
1 files changed, 71 insertions, 98 deletions
diff --git a/src/workflow/forms.py b/src/workflow/forms.py
index 0fb45d6..ee44ecd 100644
--- a/src/workflow/forms.py
+++ b/src/workflow/forms.py
@@ -242,124 +242,101 @@ class BookingMetaForm(forms.Form):
class MultipleSelectFilterWidget(forms.Widget):
- def __init__(self, attrs=None):
- super(MultipleSelectFilterWidget, self).__init__(attrs)
- self.attrs = attrs
+ def __init__(self, *args, display_objects=None, filter_items=None, neighbors=None, **kwargs):
+ super(MultipleSelectFilterWidget, self).__init__(*args, **kwargs)
+ self.display_objects = display_objects
+ self.filter_items = filter_items
+ self.neighbors = neighbors
self.template_name = "dashboard/multiple_select_filter_widget.html"
def render(self, name, value, attrs=None, renderer=None):
- attrs = self.attrs
- self.context = self.get_context(name, value, attrs)
- html = render_to_string(self.template_name, context=self.context)
+ context = self.get_context(name, value, attrs)
+ html = render_to_string(self.template_name, context=context)
return mark_safe(html)
def get_context(self, name, value, attrs):
- return attrs
+ return {
+ 'display_objects': self.display_objects,
+ 'neighbors': self.neighbors,
+ 'filter_items': self.filter_items,
+ 'initial_value': value
+ }
class MultipleSelectFilterField(forms.Field):
- def __init__(self, required=True, widget=None, label=None, initial=None,
- help_text='', error_messages=None, show_hidden_initial=False,
- validators=(), localize=False, disabled=False, label_suffix=None):
- """from the documentation:
- # required -- Boolean that specifies whether the field is required.
- # True by default.
- # widget -- A Widget class, or instance of a Widget class, that should
- # be used for this Field when displaying it. Each Field has a
- # default Widget that it'll use if you don't specify this. In
- # most cases, the default widget is TextInput.
- # label -- A verbose name for this field, for use in displaying this
- # field in a form. By default, Django will use a "pretty"
- # version of the form field name, if the Field is part of a
- # Form.
- # initial -- A value to use in this Field's initial display. This value
- # is *not* used as a fallback if data isn't given.
- # help_text -- An optional string to use as "help; text" for this Field.
- # error_messages -- An optional dictionary to override the default
- # messages that the field will raise.
- # show_hidden_initial -- Boolean that specifies if it is needed to render a
- # hidden widget with initial value after widget.
- # validators -- List of additional validators to use
- # localize -- Boolean that specifies if the field should be localized.
- # disabled -- Boolean that specifies whether the field is disabled, that
- # is its widget is shown in the form but not editable.
- # label_suffix -- Suffix to be added to the label. Overrides
- # form's label_suffix.
- """
- # this is bad, but django forms are annoying
- self.widget = widget
- if self.widget is None:
- self.widget = MultipleSelectFilterWidget()
- super(MultipleSelectFilterField, self).__init__(
- required=required,
- widget=self.widget,
- label=label,
- initial=None,
- help_text=help_text,
- error_messages=error_messages,
- show_hidden_initial=show_hidden_initial,
- validators=validators,
- localize=localize,
- disabled=disabled,
- label_suffix=label_suffix
- )
+ def __init__(self, **kwargs):
+ self.initial = kwargs.get("initial")
+ super().__init__(**kwargs)
- def clean(data):
- """
- This method will raise a django.forms.ValidationError or return clean data
- """
- return data
+ def to_python(self, value):
+ return json.loads(value)
class FormUtils:
@staticmethod
- def getLabData(multiple_selectable_hosts):
+ def getLabData(multiple_hosts=False):
"""
Gets all labs and thier host profiles and returns a serialized version the form can understand.
Should be rewritten with a related query to make it faster
- Should be moved outside of global scope
"""
+ # javascript truthy variables
+ true = 1
+ false = 0
+ if multiple_hosts:
+ multiple_hosts = true
+ else:
+ multiple_hosts = false
labs = {}
hosts = {}
items = {}
- mapping = {}
+ neighbors = {}
for lab in Lab.objects.all():
- slab = {}
- slab['id'] = "lab_" + str(lab.lab_user.id)
- slab['name'] = lab.name
- slab['description'] = lab.description
- slab['selected'] = 0
- slab['selectable'] = 1
- slab['follow'] = 1
- if not multiple_selectable_hosts:
- slab['follow'] = 0
- slab['multiple'] = 0
- items[slab['id']] = slab
- mapping[slab['id']] = []
- labs[slab['id']] = slab
+ lab_node = {
+ 'id': "lab_" + str(lab.lab_user.id),
+ 'model_id': lab.lab_user.id,
+ 'name': lab.name,
+ 'description': lab.description,
+ 'selected': false,
+ 'selectable': true,
+ 'follow': false,
+ 'multiple': false,
+ 'class': 'lab'
+ }
+ if multiple_hosts:
+ # "follow" this lab node to discover more hosts if allowed
+ lab_node['follow'] = true
+ items[lab_node['id']] = lab_node
+ neighbors[lab_node['id']] = []
+ labs[lab_node['id']] = lab_node
+
for host in lab.hostprofiles.all():
- shost = {}
- shost['forms'] = [{"name": "host_name", "type": "text", "placeholder": "hostname"}]
- shost['id'] = "host_" + str(host.id)
- shost['name'] = host.name
- shost['description'] = host.description
- shost['selected'] = 0
- shost['selectable'] = 1
- shost['follow'] = 0
- shost['multiple'] = multiple_selectable_hosts
- items[shost['id']] = shost
- mapping[slab['id']].append(shost['id'])
- if shost['id'] not in mapping:
- mapping[shost['id']] = []
- mapping[shost['id']].append(slab['id'])
- hosts[shost['id']] = shost
-
- filter_objects = [("labs", labs.values()), ("hosts", hosts.values())]
+ host_node = {
+ 'form': {"name": "host_name", "type": "text", "placeholder": "hostname"},
+ 'id': "host_" + str(host.id),
+ 'model_id': host.id,
+ 'name': host.name,
+ 'description': host.description,
+ 'selected': false,
+ 'selectable': true,
+ 'follow': false,
+ 'multiple': multiple_hosts,
+ 'class': 'host'
+ }
+ if multiple_hosts:
+ host_node['values'] = [] # place to store multiple values
+ items[host_node['id']] = host_node
+ neighbors[lab_node['id']].append(host_node['id'])
+ if host_node['id'] not in neighbors:
+ neighbors[host_node['id']] = []
+ neighbors[host_node['id']].append(lab_node['id'])
+ hosts[host_node['id']] = host_node
+
+ display_objects = [("lab", labs.values()), ("host", hosts.values())]
context = {
- 'filter_objects': filter_objects,
- 'mapping': mapping,
+ 'display_objects': display_objects,
+ 'neighbors': neighbors,
'filter_items': items
}
return context
@@ -368,14 +345,10 @@ class FormUtils:
class HardwareDefinitionForm(forms.Form):
def __init__(self, *args, **kwargs):
- selection_data = kwargs.pop("selection_data", False)
super(HardwareDefinitionForm, self).__init__(*args, **kwargs)
- attrs = FormUtils.getLabData(1)
- attrs['selection_data'] = selection_data
+ attrs = FormUtils.getLabData(multiple_hosts=True)
self.fields['filter_field'] = MultipleSelectFilterField(
- widget=MultipleSelectFilterWidget(
- attrs=attrs
- )
+ widget=MultipleSelectFilterWidget(**attrs)
)