diff --git a/netbox/circuits/forms.py b/netbox/circuits/forms.py
index 261bb8bd693..126b2a47b15 100644
--- a/netbox/circuits/forms.py
+++ b/netbox/circuits/forms.py
@@ -107,9 +107,15 @@ class ProviderBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBu
class ProviderFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = Provider
field_groups = [
+ ['q'],
['region_id', 'site_id'],
['asn', 'tag'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -196,7 +202,12 @@ class ProviderNetworkBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomField
class ProviderNetworkFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = ProviderNetwork
- field_order = ['provider_id']
+ field_order = ['q', 'provider_id', 'tag']
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
provider_id = DynamicModelMultipleChoiceField(
queryset=Provider.objects.all(),
required=False,
@@ -358,16 +369,22 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBul
class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterForm):
model = Circuit
field_order = [
- 'type_id', 'provider_id', 'provider_network_id', 'status', 'region_id', 'site_id', 'tenant_group_id', 'tenant_id',
- 'commit_rate',
+ 'q', 'type_id', 'provider_id', 'provider_network_id', 'status', 'region_id', 'site_id', 'tenant_group_id',
+ 'tenant_id', 'commit_rate',
]
field_groups = [
+ ['q'],
['type_id', 'status', 'commit_rate'],
['provider_id', 'provider_network_id'],
['region_id', 'site_id'],
['tenant_group_id', 'tenant_id'],
['tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
type_id = DynamicModelMultipleChoiceField(
queryset=CircuitType.objects.all(),
required=False,
diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py
index da9030ca998..348cb3b62b3 100644
--- a/netbox/dcim/forms.py
+++ b/netbox/dcim/forms.py
@@ -56,12 +56,18 @@ def get_device_by_name_or_pk(name):
class DeviceComponentFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
field_order = [
- 'name', 'label', 'region_id', 'site_group_id', 'site_id',
+ 'q', 'name', 'label', 'region_id', 'site_group_id', 'site_id',
]
field_groups = [
+ ['q'],
['name', 'label'],
['region_id', 'site_group_id', 'site_id'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
name = forms.CharField(
required=False
)
@@ -452,12 +458,18 @@ class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEd
class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterForm):
model = Site
- field_order = ['status', 'region_id', 'tenant_group_id', 'tenant_id']
+ field_order = ['q', 'status', 'region_id', 'tenant_group_id', 'tenant_id']
field_groups = [
+ ['q'],
['status', 'region_id'],
['tenant_group_id', 'tenant_id'],
['tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
status = forms.MultipleChoiceField(
choices=SiteStatusChoices,
required=False,
@@ -568,6 +580,11 @@ class LocationBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
class LocationFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = Location
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -862,12 +879,18 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEd
class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterForm):
model = Rack
- field_order = ['region_id', 'site_id', 'location_id', 'status', 'role_id', 'tenant_group_id', 'tenant_id']
+ field_order = ['q', 'region_id', 'site_id', 'location_id', 'status', 'role_id', 'tenant_group_id', 'tenant_id']
field_groups = [
+ ['q'],
['status', 'role_id'],
['region_id', 'site_id', 'location_id'],
['tenant_group_id', 'tenant_id'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -927,7 +950,8 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo
class RackElevationFilterForm(RackFilterForm):
field_order = [
- 'region_id', 'site_id', 'location_id', 'id', 'status', 'role_id', 'tenant_group_id', 'tenant_id',
+ 'q', 'region_id', 'site_id', 'location_id', 'id', 'status', 'role_id', 'tenant_group_id',
+ 'tenant_id',
]
id = DynamicModelMultipleChoiceField(
queryset=Rack.objects.all(),
@@ -1092,11 +1116,17 @@ class RackReservationBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomField
class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterForm):
model = RackReservation
- field_order = ['region_id', 'site_id', 'location_id', 'user_id', 'tenant_group_id', 'tenant_id']
+ field_order = ['q', 'region_id', 'site_id', 'location_id', 'user_id', 'tenant_group_id', 'tenant_id']
field_groups = [
+ ['q'],
['region_id', 'site_id', 'location_id'],
['user_id', 'tenant_group_id', 'tenant_id'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -1246,12 +1276,18 @@ class DeviceTypeBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModel
class DeviceTypeFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = DeviceType
field_groups = [
+ ['q'],
['manufacturer_id', 'subdevice_role'],
['console_ports', 'console_server_ports'],
['power_ports', 'power_outlets'],
['interfaces', 'pass_through_ports'],
['tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
manufacturer_id = DynamicModelMultipleChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
@@ -2058,6 +2094,11 @@ class PlatformBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
class PlatformFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = Platform
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
manufacturer_id = DynamicModelMultipleChoiceField(
queryset=Manufacturer.objects.all(),
required=False,
@@ -2465,16 +2506,23 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulk
class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilterForm, CustomFieldModelFilterForm):
model = Device
field_order = [
- 'region_id', 'site_id', 'location_id', 'rack_id', 'status', 'role_id', 'tenant_group_id', 'tenant_id',
- 'manufacturer_id', 'device_type_id', 'asset_tag', 'mac_address', 'has_primary_ip',
+ 'q', 'region_id', 'site_id', 'location_id', 'rack_id', 'status', 'role_id',
+ 'tenant_group_id', 'tenant_id', 'manufacturer_id', 'device_type_id', 'asset_tag',
+ 'mac_address', 'has_primary_ip',
]
field_groups = [
+ ['q'],
['region_id', 'site_id', 'location_id', 'rack_id'],
['status', 'role_id', 'asset_tag'],
['tenant_group_id', 'tenant_id'],
['manufacturer_id', 'device_type_id'],
['mac_address', 'has_primary_ip'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -2654,6 +2702,7 @@ class DeviceBulkAddComponentForm(BootstrapMixin, CustomFieldsMixin, ComponentFor
class ConsolePortFilterForm(DeviceComponentFilterForm):
model = ConsolePort
field_groups = [
+ ['q'],
['name', 'label'],
['type', 'speed'],
['region_id', 'site_group_id', 'site_id'],
@@ -2761,6 +2810,7 @@ class ConsolePortCSVForm(CustomFieldModelCSVForm):
class ConsoleServerPortFilterForm(DeviceComponentFilterForm):
model = ConsoleServerPort
field_groups = [
+ ['q'],
['name', 'label'],
['type', 'speed'],
['region_id', 'site_group_id', 'site_id'],
@@ -2868,6 +2918,7 @@ class ConsoleServerPortCSVForm(CustomFieldModelCSVForm):
class PowerPortFilterForm(DeviceComponentFilterForm):
model = PowerPort
field_groups = [
+ ['q'],
['name', 'label', 'type'],
['region_id', 'site_group_id', 'site_id'],
['tag'],
@@ -2973,6 +3024,7 @@ class PowerPortCSVForm(CustomFieldModelCSVForm):
class PowerOutletFilterForm(DeviceComponentFilterForm):
model = PowerOutlet
field_groups = [
+ ['q'],
['name', 'label', 'type'],
['region_id', 'site_group_id', 'site_id'],
['tag'],
@@ -3145,6 +3197,7 @@ class PowerOutletCSVForm(CustomFieldModelCSVForm):
class InterfaceFilterForm(DeviceComponentFilterForm):
model = Interface
field_groups = [
+ ['q'],
['name', 'label', 'type', 'enabled'],
['mgmt_only', 'mac_address'],
['region_id', 'site_group_id', 'site_id'],
@@ -3493,6 +3546,7 @@ class InterfaceCSVForm(CustomFieldModelCSVForm):
class FrontPortFilterForm(DeviceComponentFilterForm):
field_groups = [
+ ['q'],
['name', 'label', 'type', 'color'],
['region_id', 'site_group_id', 'site_id'],
['tag']
@@ -3682,6 +3736,7 @@ class FrontPortCSVForm(CustomFieldModelCSVForm):
class RearPortFilterForm(DeviceComponentFilterForm):
model = RearPort
field_groups = [
+ ['q'],
['name', 'label', 'type', 'color'],
['region_id', 'site_group_id', 'site_id'],
['tag']
@@ -3783,6 +3838,7 @@ class RearPortCSVForm(CustomFieldModelCSVForm):
class DeviceBayFilterForm(DeviceComponentFilterForm):
model = DeviceBay
field_groups = [
+ ['q'],
['name', 'label'],
['region_id', 'site_group_id', 'site_id'],
['tag']
@@ -4013,6 +4069,7 @@ class InventoryItemBulkEditForm(
class InventoryItemFilterForm(DeviceComponentFilterForm):
model = InventoryItem
field_groups = [
+ ['q'],
['name', 'label', 'manufacturer_id'],
['serial', 'asset_tag', 'discovered'],
['region_id', 'site_group_id', 'site_id'],
@@ -4488,11 +4545,17 @@ class CableBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkE
class CableFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = Cable
field_groups = [
+ ['q'],
['type', 'status', 'color'],
['device_id', 'rack_id'],
['region_id', 'site_id', 'tenant_id'],
['tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -4556,6 +4619,11 @@ class CableFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
#
class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -4583,6 +4651,11 @@ class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -4610,6 +4683,11 @@ class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form):
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -4877,12 +4955,18 @@ class VirtualChassisCSVForm(CustomFieldModelCSVForm):
class VirtualChassisFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterForm):
model = VirtualChassis
- field_order = ['region_id', 'site_group_id', 'site_id', 'tenant_group_id', 'tenant_id']
+ field_order = ['q', 'region_id', 'site_group_id', 'site_id', 'tenant_group_id', 'tenant_id']
field_groups = [
+ ['q'],
['region_id', 'site_group_id', 'site_id'],
['tenant_group_id', 'tenant_id'],
['tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -5022,6 +5106,11 @@ class PowerPanelBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModel
class PowerPanelFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = PowerPanel
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -5260,12 +5349,18 @@ class PowerFeedBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelB
class PowerFeedFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = PowerFeed
field_groups = [
+ ['q'],
['region_id', 'site_group_id', 'site_id'],
['power_panel_id', 'rack_id'],
['type', 'supply', 'max_utilization'],
['phase', 'voltage', 'amperage'],
['status', 'tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py
index 86860b0bca5..4452b5aad70 100644
--- a/netbox/extras/choices.py
+++ b/netbox/extras/choices.py
@@ -46,28 +46,40 @@ class CustomFieldFilterLogicChoices(ChoiceSet):
class CustomLinkButtonClassChoices(ChoiceSet):
CLASS_DEFAULT = 'outline-dark'
- CLASS_PRIMARY = 'primary'
- CLASS_SUCCESS = 'success'
- CLASS_INFO = 'info'
- CLASS_WARNING = 'warning'
- CLASS_DANGER = 'danger'
- CLASS_LINK = 'link'
+ CLASS_LINK = 'ghost-dark'
+ CLASS_BLUE = 'blue'
+ CLASS_INDIGO = 'indigo'
+ CLASS_PURPLE = 'purple'
+ CLASS_PINK = 'pink'
+ CLASS_RED = 'red'
+ CLASS_ORANGE = 'orange'
+ CLASS_YELLOW = 'yellow'
+ CLASS_GREEN = 'green'
+ CLASS_TEAL = 'teal'
+ CLASS_CYAN = 'cyan'
+ CLASS_GRAY = 'secondary'
CHOICES = (
(CLASS_DEFAULT, 'Default'),
- (CLASS_PRIMARY, 'Primary (blue)'),
- (CLASS_SUCCESS, 'Success (green)'),
- (CLASS_INFO, 'Info (aqua)'),
- (CLASS_WARNING, 'Warning (orange)'),
- (CLASS_DANGER, 'Danger (red)'),
- (CLASS_LINK, 'None (link)'),
+ (CLASS_LINK, 'Link'),
+ (CLASS_BLUE, 'Blue'),
+ (CLASS_INDIGO, 'Indigo'),
+ (CLASS_PURPLE, 'Purple'),
+ (CLASS_PINK, 'Pink'),
+ (CLASS_RED, 'Red'),
+ (CLASS_ORANGE, 'Orange'),
+ (CLASS_YELLOW, 'Yellow'),
+ (CLASS_GREEN, 'Green'),
+ (CLASS_TEAL, 'Teal'),
+ (CLASS_CYAN, 'Cyan'),
+ (CLASS_GRAY, 'Gray'),
)
-
#
# ObjectChanges
#
+
class ObjectChangeActionChoices(ChoiceSet):
ACTION_CREATE = 'create'
diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py
index 16091885c07..98f34dfa96f 100644
--- a/netbox/extras/forms.py
+++ b/netbox/extras/forms.py
@@ -77,9 +77,15 @@ class CustomFieldBulkEditForm(BootstrapMixin, BulkEditForm):
class CustomFieldFilterForm(BootstrapMixin, forms.Form):
field_groups = [
+ ['q'],
['type', 'content_types'],
['weight', 'required'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields')
@@ -167,9 +173,15 @@ class CustomLinkBulkEditForm(BootstrapMixin, BulkEditForm):
class CustomLinkFilterForm(BootstrapMixin, forms.Form):
field_groups = [
+ ['q'],
['content_type'],
['weight', 'new_window'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
content_type = ContentTypeChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields')
@@ -252,9 +264,15 @@ class ExportTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
class ExportTemplateFilterForm(BootstrapMixin, forms.Form):
field_groups = [
+ ['q'],
['content_type', 'mime_type'],
['file_extension', 'as_attachment'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
content_type = ContentTypeChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields')
@@ -358,9 +376,15 @@ class WebhookBulkEditForm(BootstrapMixin, BulkEditForm):
class WebhookFilterForm(BootstrapMixin, forms.Form):
field_groups = [
+ ['q'],
['content_types', 'http_method'],
['enabled', 'type_create', 'type_update', 'type_delete'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields')
@@ -664,15 +688,21 @@ class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm):
class ConfigContextFilterForm(BootstrapMixin, forms.Form):
field_order = [
- 'region_id', 'site_group_id', 'site_id', 'role_id', 'platform_id', 'cluster_group_id', 'cluster_id',
- 'tenant_group_id', 'tenant_id',
+ 'q', 'region_id', 'site_group_id', 'site_id', 'role_id', 'platform_id', 'cluster_group_id',
+ 'cluster_id', 'tenant_group_id', 'tenant_id',
]
field_groups = [
+ ['q'],
['region_id', 'site_group_id', 'site_id'],
['device_type_id', 'role_id', 'platform_id'],
['cluster_group_id', 'cluster_id'],
['tenant_group_id', 'tenant_id', 'tag']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
region_id = DynamicModelMultipleChoiceField(
queryset=Region.objects.all(),
required=False,
@@ -812,9 +842,15 @@ class JournalEntryBulkEditForm(BootstrapMixin, BulkEditForm):
class JournalEntryFilterForm(BootstrapMixin, forms.Form):
model = JournalEntry
field_groups = [
+ ['q'],
['created_before', 'created_after', 'created_by_id'],
['assigned_object_type_id', 'kind']
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
created_after = forms.DateTimeField(
required=False,
label=_('After'),
@@ -857,9 +893,15 @@ class JournalEntryFilterForm(BootstrapMixin, forms.Form):
class ObjectChangeFilterForm(BootstrapMixin, forms.Form):
model = ObjectChange
field_groups = [
+ ['q'],
['time_before', 'time_after', 'action'],
['user_id', 'changed_object_type_id'],
]
+ q = forms.CharField(
+ required=False,
+ widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
+ label=_('Search')
+ )
time_after = forms.DateTimeField(
required=False,
label=_('After'),
diff --git a/netbox/extras/templatetags/custom_links.py b/netbox/extras/templatetags/custom_links.py
index 814acbbcb96..fec5cf65ac3 100644
--- a/netbox/extras/templatetags/custom_links.py
+++ b/netbox/extras/templatetags/custom_links.py
@@ -10,10 +10,10 @@ from utilities.utils import render_jinja2
register = template.Library()
-LINK_BUTTON = '{}\n'
+LINK_BUTTON = '{}\n'
GROUP_BUTTON = """
-
+