1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

211 lines
6.1 KiB
Python
Raw Normal View History

import json
from django import forms
from django.conf import settings
from django.contrib.postgres.forms import SimpleArrayField
from utilities.choices import ColorChoices
from .utils import add_blank_choice, parse_numeric_range
__all__ = (
'APISelect',
'APISelectMultiple',
'BulkEditNullBooleanSelect',
'ColorSelect',
'ContentTypeSelect',
'DatePicker',
'DateTimePicker',
'NumericArrayField',
'SelectWithDisabled',
'SelectWithPK',
'SlugWidget',
'SmallTextarea',
'StaticSelect2',
'StaticSelect2Multiple',
'TimePicker',
)
class SmallTextarea(forms.Textarea):
"""
Subclass used for rendering a smaller textarea element.
"""
pass
class SlugWidget(forms.TextInput):
"""
Subclass TextInput and add a slug regeneration button next to the form field.
"""
template_name = 'widgets/sluginput.html'
class ColorSelect(forms.Select):
"""
Extends the built-in Select widget to colorize each <option>.
"""
option_template_name = 'widgets/colorselect_option.html'
def __init__(self, *args, **kwargs):
kwargs['choices'] = add_blank_choice(ColorChoices)
super().__init__(*args, **kwargs)
self.attrs['class'] = 'netbox-select2-color-picker'
class BulkEditNullBooleanSelect(forms.NullBooleanSelect):
"""
A Select widget for NullBooleanFields
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Override the built-in choice labels
self.choices = (
('1', '---------'),
('2', 'Yes'),
('3', 'No'),
)
self.attrs['class'] = 'netbox-select2-static'
class SelectWithDisabled(forms.Select):
"""
Modified the stock Select widget to accept choices using a dict() for a label. The dict for each option must include
'label' (string) and 'disabled' (boolean).
"""
option_template_name = 'widgets/selectwithdisabled_option.html'
class StaticSelect2(SelectWithDisabled):
"""
A static <select> form widget using the Select2 library.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attrs['class'] = 'netbox-select2-static'
class StaticSelect2Multiple(StaticSelect2, forms.SelectMultiple):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attrs['data-multiple'] = 1
class SelectWithPK(StaticSelect2):
"""
Include the primary key of each option in the option label (e.g. "Router7 (4721)").
"""
option_template_name = 'widgets/select_option_with_pk.html'
class ContentTypeSelect(StaticSelect2):
"""
Appends an `api-value` attribute equal to the slugified model name for each ContentType. For example:
<option value="37" api-value="console-server-port">console server port</option>
This attribute can be used to reference the relevant API endpoint for a particular ContentType.
"""
option_template_name = 'widgets/select_contenttype.html'
class NumericArrayField(SimpleArrayField):
def to_python(self, value):
value = ','.join([str(n) for n in parse_numeric_range(value)])
return super().to_python(value)
class APISelect(SelectWithDisabled):
"""
A select widget populated via an API call
:param api_url: API endpoint URL. Required if not set automatically by the parent field.
:param display_field: (Optional) Field to display for child in selection list. Defaults to `name`.
:param disabled_indicator: (Optional) Mark option as disabled if this field equates true.
:param additional_query_params: Optional) A dict of query params to append to the API request. The key is the
name of the query param and the value if the query param's value.
"""
def __init__(
self,
api_url=None,
display_field=None,
disabled_indicator=None,
additional_query_params=None,
full=False,
*args,
**kwargs
):
super().__init__(*args, **kwargs)
self.attrs['class'] = 'netbox-select2-api'
if api_url:
self.attrs['data-url'] = '/{}{}'.format(settings.BASE_PATH, api_url.lstrip('/')) # Inject BASE_PATH
if full:
self.attrs['data-full'] = full
if display_field:
self.attrs['display-field'] = display_field
if disabled_indicator:
self.attrs['disabled-indicator'] = disabled_indicator
if additional_query_params:
for key, value in additional_query_params.items():
self.add_additional_query_param(key, value)
def add_additional_query_param(self, name, value):
"""
Add details for an additional query param in the form of a data-* JSON-encoded list attribute.
:param name: The name of the query param
:param value: The value of the query param
"""
key = f'data-additional-query-param-{name}'
values = json.loads(self.attrs.get(key, '[]'))
if type(value) is list:
values.extend(value)
else:
values.append(value)
self.attrs[key] = json.dumps(values)
class APISelectMultiple(APISelect, forms.SelectMultiple):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attrs['data-multiple'] = 1
class DatePicker(forms.TextInput):
"""
Date picker using Flatpickr.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attrs['class'] = 'date-picker'
self.attrs['placeholder'] = 'YYYY-MM-DD'
class DateTimePicker(forms.TextInput):
"""
DateTime picker using Flatpickr.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attrs['class'] = 'datetime-picker'
self.attrs['placeholder'] = 'YYYY-MM-DD hh:mm:ss'
class TimePicker(forms.TextInput):
"""
Time picker using Flatpickr.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attrs['class'] = 'time-picker'
self.attrs['placeholder'] = 'hh:mm:ss'