From 89b7f3f19d46349b1118cee682d51225fe16cadf Mon Sep 17 00:00:00 2001 From: thatmattlove Date: Thu, 26 Aug 2021 00:14:26 -0700 Subject: [PATCH] Fixes #7035: Refactor APISelect query_param logic --- netbox/circuits/forms.py | 30 +- netbox/dcim/forms.py | 596 +++++++++--------- netbox/ipam/forms.py | 154 ++--- netbox/project-static/dist/config.js | Bin 108078 -> 108108 bytes netbox/project-static/dist/config.js.map | Bin 412865 -> 412970 bytes netbox/project-static/dist/jobs.js | Bin 108384 -> 108414 bytes netbox/project-static/dist/jobs.js.map | Bin 414933 -> 415038 bytes netbox/project-static/dist/lldp.js | Bin 108775 -> 108805 bytes netbox/project-static/dist/lldp.js.map | Bin 415371 -> 415476 bytes netbox/project-static/dist/netbox.js | Bin 317974 -> 318496 bytes netbox/project-static/dist/netbox.js.map | Bin 1145072 -> 1148931 bytes netbox/project-static/dist/status.js | Bin 128189 -> 128219 bytes netbox/project-static/dist/status.js.map | Bin 463700 -> 463805 bytes .../src/select/{api.ts => api/apiSelect.ts} | 258 +++----- .../src/select/api/filterFields.ts | 87 +++ netbox/project-static/src/select/api/index.ts | 10 + netbox/project-static/src/select/api/types.ts | 111 ++++ netbox/project-static/src/util.ts | 2 + netbox/tenancy/forms.py | 12 +- netbox/utilities/forms/fields.py | 11 +- netbox/utilities/forms/widgets.py | 86 ++- netbox/virtualization/forms.py | 104 +-- 22 files changed, 825 insertions(+), 636 deletions(-) rename netbox/project-static/src/select/{api.ts => api/apiSelect.ts} (80%) create mode 100644 netbox/project-static/src/select/api/filterFields.ts create mode 100644 netbox/project-static/src/select/api/index.ts create mode 100644 netbox/project-static/src/select/api/types.ts diff --git a/netbox/circuits/forms.py b/netbox/circuits/forms.py index 56cd46d4a..201d1b203 100644 --- a/netbox/circuits/forms.py +++ b/netbox/circuits/forms.py @@ -131,10 +131,10 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldModelFilterForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'site_group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'site_group_id', 'field_name': 'site_group_id'} + ], label=_('Site'), fetch_trigger='open' ) @@ -405,9 +405,9 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilte provider_network_id = DynamicModelMultipleChoiceField( queryset=ProviderNetwork.objects.all(), required=False, - query_params={ - 'provider_id': '$provider_id' - }, + filter_fields=[ + {'accessor': 'provider_id', 'field_name': 'provider_id'} + ], label=_('Provider network'), fetch_trigger='open' ) @@ -431,10 +431,10 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilte site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'site_group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'site_group_id', 'field_name': 'site_group_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -467,10 +467,10 @@ class CircuitTerminationForm(BootstrapMixin, forms.ModelForm): ) site = DynamicModelChoiceField( queryset=Site.objects.all(), - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'site_group_id', 'field_name': 'site_group'}, + ], required=False ) provider_network = DynamicModelChoiceField( diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 3456eee35..47109c233 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -84,29 +84,29 @@ class DeviceComponentFilterForm(BootstrapMixin, CustomFieldModelFilterForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'group_id', 'field_name': 'site_group_id'}, + ], label=_('Site'), fetch_trigger='open' ) location_id = DynamicModelMultipleChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site_id', - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Location'), fetch_trigger='open' ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - query_params={ - 'site_id': '$site_id', - 'location_id': '$location_id', - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + {'accessor': 'location_id', 'field_name': 'location_id'}, + ], label=_('Device'), fetch_trigger='open' ) @@ -546,17 +546,17 @@ class LocationForm(BootstrapMixin, CustomFieldModelForm): ) site = DynamicModelChoiceField( queryset=Site.objects.all(), - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ] ) parent = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) slug = SlugField() @@ -600,9 +600,9 @@ class LocationBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm): parent = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) description = forms.CharField( max_length=200, @@ -635,20 +635,20 @@ class LocationFilterForm(BootstrapMixin, CustomFieldModelFilterForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'group_id', 'field_name': 'site_group_id'}, + ], label=_('Site'), fetch_trigger='open' ) parent_id = DynamicModelMultipleChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'site_id': '$site_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Parent'), fetch_trigger='open' ) @@ -717,17 +717,17 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): ) site = DynamicModelChoiceField( queryset=Site.objects.all(), - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], ) location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], ) role = DynamicModelChoiceField( queryset=RackRole.objects.all(), @@ -841,17 +841,17 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEd site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ] ) location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), @@ -943,9 +943,9 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -953,9 +953,9 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo queryset=Location.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Location'), fetch_trigger='open' ) @@ -1000,10 +1000,10 @@ class RackElevationFilterForm(RackFilterForm): queryset=Rack.objects.all(), label=_('Rack'), required=False, - query_params={ - 'site_id': '$site_id', - 'location_id': '$location_id', - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + {'accessor': 'location_id', 'field_name': 'location_id'}, + ], fetch_trigger='open' ) @@ -1032,26 +1032,26 @@ class RackReservationForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], fetch_trigger='open' ) location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], fetch_trigger='open' ) rack = DynamicModelChoiceField( queryset=Rack.objects.all(), - query_params={ - 'site_id': '$site', - 'location_id': '$location', - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'location_id', 'field_name': 'location'}, + ], fetch_trigger='open' ) units = NumericArrayField( @@ -1180,9 +1180,9 @@ class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldMo site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -1402,9 +1402,9 @@ class ComponentTemplateCreateForm(BootstrapMixin, ComponentForm): ) device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all(), - query_params={ - 'manufacturer_id': '$manufacturer' - } + filter_fields=[ + {'accessor': 'manufacturer_id', 'field_name': 'manufacturer'}, + ] ) description = forms.CharField( required=False @@ -2169,17 +2169,17 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): ) site = DynamicModelChoiceField( queryset=Site.objects.all(), - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ] ) location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], initial_params={ 'racks': '$rack' } @@ -2187,10 +2187,10 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): rack = DynamicModelChoiceField( queryset=Rack.objects.all(), required=False, - query_params={ - 'site_id': '$site', - 'location_id': '$location', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'location_id', 'field_name': 'location'}, + ], ) position = forms.IntegerField( required=False, @@ -2214,9 +2214,9 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): ) device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all(), - query_params={ - 'manufacturer_id': '$manufacturer' - } + filter_fields=[ + {'accessor': 'manufacturer_id', 'field_name': 'manufacturer'}, + ], ) device_role = DynamicModelChoiceField( queryset=DeviceRole.objects.all() @@ -2224,9 +2224,13 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): platform = DynamicModelChoiceField( queryset=Platform.objects.all(), required=False, - query_params={ - 'manufacturer_id': ['$manufacturer', 'null'] - } + filter_fields=[ + { + 'accessor': 'manufacturer_id', + 'field_name': 'manufacturer', + 'include_null': True + } + ] ) cluster_group = DynamicModelChoiceField( queryset=ClusterGroup.objects.all(), @@ -2239,9 +2243,9 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): cluster = DynamicModelChoiceField( queryset=Cluster.objects.all(), required=False, - query_params={ - 'group_id': '$cluster_group' - } + filter_fields=[ + {'accessor': 'group_id', 'field_name': 'cluster_group'}, + ], ) comments = CommentField() local_context_data = JSONField( @@ -2500,9 +2504,9 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulk device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all(), required=False, - query_params={ - 'manufacturer_id': '$manufacturer' - } + filter_fields=[ + {'accessor': 'manufacturer_id', 'field_name': 'manufacturer'}, + ] ) device_role = DynamicModelChoiceField( queryset=DeviceRole.objects.all(), @@ -2515,9 +2519,9 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulk location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), @@ -2581,10 +2585,10 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'group_id', 'field_name': 'site_group_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -2592,9 +2596,9 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt queryset=Location.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Location'), fetch_trigger='open' ) @@ -2602,10 +2606,10 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt queryset=Rack.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site_id', - 'location_id': '$location_id', - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + {'accessor': 'location_id', 'field_name': 'location_id'}, + ], label=_('Rack'), fetch_trigger='open' ) @@ -2624,9 +2628,9 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt device_type_id = DynamicModelMultipleChoiceField( queryset=DeviceType.objects.all(), required=False, - query_params={ - 'manufacturer_id': '$manufacturer_id' - }, + filter_fields=[ + {'accessor': 'manufacturer_id', 'field_name': 'manufacturer_id'}, + ], label=_('Model'), fetch_trigger='open' ) @@ -3279,9 +3283,9 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm): queryset=Interface.objects.all(), required=False, label='LAG interface', - query_params={ - 'type': 'lag', - } + filter_fields=[ + {'accessor': 'type', 'field_name': 'type', 'default_value': 'lag'}, + ] ) vlan_group = DynamicModelChoiceField( queryset=VLANGroup.objects.all(), @@ -3292,17 +3296,17 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm): queryset=VLAN.objects.all(), required=False, label='Untagged VLAN', - query_params={ - 'group_id': '$vlan_group', - } + filter_fields=[ + {'accessor': 'group_id', 'field_name': 'vlan_group'}, + ], ) tagged_vlans = DynamicModelMultipleChoiceField( queryset=VLAN.objects.all(), required=False, label='Tagged VLANs', - query_params={ - 'group_id': '$vlan_group', - } + filter_fields=[ + {'accessor': 'group_id', 'field_name': 'vlan_group'}, + ], ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -3358,17 +3362,17 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm): parent = DynamicModelChoiceField( queryset=Interface.objects.all(), required=False, - query_params={ - 'device_id': '$device', - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'device'}, + ], ) lag = DynamicModelChoiceField( queryset=Interface.objects.all(), required=False, - query_params={ - 'device_id': '$device', - 'type': 'lag', - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'device'}, + {'accessor': 'type', 'field_name': 'type', 'default_value': 'lag'}, + ] ) mac_address = forms.CharField( required=False, @@ -3445,9 +3449,9 @@ class InterfaceBulkEditForm( lag = DynamicModelChoiceField( queryset=Interface.objects.all(), required=False, - query_params={ - 'type': 'lag', - } + filter_fields=[ + {'accessor': 'type', 'field_name': 'type', 'default_value': 'lag'}, + ], ) mgmt_only = forms.NullBooleanField( required=False, @@ -4015,9 +4019,9 @@ class InventoryItemForm(BootstrapMixin, CustomFieldModelForm): parent = DynamicModelChoiceField( queryset=InventoryItem.objects.all(), required=False, - query_params={ - 'device_id': '$device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'device'}, + ], ) manufacturer = DynamicModelChoiceField( queryset=Manufacturer.objects.all(), @@ -4045,9 +4049,9 @@ class InventoryItemCreateForm(ComponentCreateForm): parent = DynamicModelChoiceField( queryset=InventoryItem.objects.all(), required=False, - query_params={ - 'device_id': '$device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'device'}, + ] ) part_id = forms.CharField( max_length=50, @@ -4187,39 +4191,39 @@ class ConnectCableToDeviceForm(BootstrapMixin, CustomFieldModelForm): queryset=Site.objects.all(), label='Site', required=False, - query_params={ - 'region_id': '$termination_b_region', - 'group_id': '$termination_b_site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'termination_b_region'}, + {'accessor': 'group_id', 'field_name': 'termination_b_site_group'}, + ], ) termination_b_location = DynamicModelChoiceField( queryset=Location.objects.all(), label='Location', required=False, null_option='None', - query_params={ - 'site_id': '$termination_b_site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'termination_b_site'}, + ] ) termination_b_rack = DynamicModelChoiceField( queryset=Rack.objects.all(), label='Rack', required=False, null_option='None', - query_params={ - 'site_id': '$termination_b_site', - 'location_id': '$termination_b_location', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'termination_b_site'}, + {'accessor': 'location_id', 'field_name': 'termination_b_location'}, + ] ) termination_b_device = DynamicModelChoiceField( queryset=Device.objects.all(), label='Device', required=False, - query_params={ - 'site_id': '$termination_b_site', - 'location_id': '$termination_b_location', - 'rack_id': '$termination_b_rack', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'termination_b_site'}, + {'accessor': 'location_id', 'field_name': 'termination_b_location'}, + {'accessor': 'rack_id', 'field_name': 'termination_b_rack'} + ] ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -4248,9 +4252,9 @@ class ConnectCableToConsolePortForm(ConnectCableToDeviceForm): queryset=ConsolePort.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + ], ) @@ -4259,9 +4263,9 @@ class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm): queryset=ConsoleServerPort.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + ], ) @@ -4270,9 +4274,9 @@ class ConnectCableToPowerPortForm(ConnectCableToDeviceForm): queryset=PowerPort.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + ], ) @@ -4281,9 +4285,9 @@ class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm): queryset=PowerOutlet.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + ] ) @@ -4292,10 +4296,10 @@ class ConnectCableToInterfaceForm(ConnectCableToDeviceForm): queryset=Interface.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device', - 'kind': 'physical', - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + {'accessor': 'kind', 'field_name': 'kind', 'default_value': 'physical'} + ] ) @@ -4304,9 +4308,9 @@ class ConnectCableToFrontPortForm(ConnectCableToDeviceForm): queryset=FrontPort.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + ], ) @@ -4315,9 +4319,9 @@ class ConnectCableToRearPortForm(ConnectCableToDeviceForm): queryset=RearPort.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'device_id': '$termination_b_device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'termination_b_device'}, + ], ) @@ -4341,26 +4345,26 @@ class ConnectCableToCircuitTerminationForm(BootstrapMixin, CustomFieldModelForm) queryset=Site.objects.all(), label='Site', required=False, - query_params={ - 'region_id': '$termination_b_region', - 'group_id': '$termination_b_site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'termination_b_region'}, + {'accessor': 'group_id', 'field_name': 'termination_b_site_group'}, + ], ) termination_b_circuit = DynamicModelChoiceField( queryset=Circuit.objects.all(), label='Circuit', - query_params={ - 'provider_id': '$termination_b_provider', - 'site_id': '$termination_b_site', - } + filter_fields=[ + {'accessor': 'provider_id', 'field_name': 'termination_b_provider'}, + {'accessor': 'site_id', 'field_name': 'termination_b_site'}, + ] ) termination_b_id = DynamicModelChoiceField( queryset=CircuitTermination.objects.all(), label='Side', disabled_indicator='_occupied', - query_params={ - 'circuit_id': '$termination_b_circuit' - } + filter_fields=[ + {'accessor': 'circuit_id', 'field_name': 'termination_b_circuit'}, + ] ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -4394,35 +4398,35 @@ class ConnectCableToPowerFeedForm(BootstrapMixin, CustomFieldModelForm): queryset=Site.objects.all(), label='Site', required=False, - query_params={ - 'region_id': '$termination_b_region', - 'group_id': '$termination_b_site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'termination_b_region'}, + {'accessor': 'group_id', 'field_name': 'termination_b_site_group'}, + ], ) termination_b_location = DynamicModelChoiceField( queryset=Location.objects.all(), label='Location', required=False, - query_params={ - 'site_id': '$termination_b_site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'termination_b_site'}, + ] ) termination_b_powerpanel = DynamicModelChoiceField( queryset=PowerPanel.objects.all(), label='Power Panel', required=False, - query_params={ - 'site_id': '$termination_b_site', - 'location_id': '$termination_b_location', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'termination_b_site'}, + {'accessor': 'location_id', 'field_name': 'termination_b_location'}, + ] ) termination_b_id = DynamicModelChoiceField( queryset=PowerFeed.objects.all(), label='Name', disabled_indicator='_occupied', - query_params={ - 'power_panel_id': '$termination_b_powerpanel' - } + filter_fields=[ + {'accessor': 'power_panel_id', 'field_name': 'termination_b_powerpanel'}, + ] ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -4633,9 +4637,9 @@ class CableFilterForm(BootstrapMixin, CustomFieldModelFilterForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -4650,9 +4654,9 @@ class CableFilterForm(BootstrapMixin, CustomFieldModelFilterForm): required=False, label=_('Rack'), null_option='None', - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], fetch_trigger='open' ) type = forms.MultipleChoiceField( @@ -4671,11 +4675,11 @@ class CableFilterForm(BootstrapMixin, CustomFieldModelFilterForm): device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - query_params={ - 'site_id': '$site_id', - 'tenant_id': '$tenant_id', - 'rack_id': '$rack_id', - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + {'accessor': 'tenant_id', 'field_name': 'tenant_id'}, + {'accessor': 'rack_id', 'field_name': 'rack_id'}, + ], label=_('Device'), fetch_trigger='open' ) @@ -4696,18 +4700,18 @@ class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Device'), fetch_trigger='open' ) @@ -4723,18 +4727,18 @@ class PowerConnectionFilterForm(BootstrapMixin, forms.Form): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Device'), fetch_trigger='open' ) @@ -4750,18 +4754,18 @@ class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site_id'}, + ], label=_('Device'), fetch_trigger='open' ) @@ -4796,26 +4800,26 @@ class VirtualChassisCreateForm(BootstrapMixin, CustomFieldModelForm): site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], ) rack = DynamicModelChoiceField( queryset=Rack.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) members = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - query_params={ - 'site_id': '$site', - 'rack_id': '$rack', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'rack_id', 'field_name': 'rack'}, + ], ) initial_position = forms.IntegerField( initial=1, @@ -4948,26 +4952,30 @@ class VCMemberSelectForm(BootstrapMixin, forms.Form): site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ] ) rack = DynamicModelChoiceField( queryset=Rack.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) device = DynamicModelChoiceField( queryset=Device.objects.all(), - query_params={ - 'site_id': '$site', - 'rack_id': '$rack', - 'virtual_chassis_id': 'null', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'rack_id', 'field_name': 'rack'}, + { + 'accessor': 'virtual_chassis_id', + 'field_name': 'virtual_chassis_id', + 'default_value': None + }, + ] ) def clean_device(self): @@ -5034,10 +5042,10 @@ class VirtualChassisFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldMod site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'group_id', 'field_name': 'site_group_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -5065,17 +5073,17 @@ class PowerPanelForm(BootstrapMixin, CustomFieldModelForm): ) site = DynamicModelChoiceField( queryset=Site.objects.all(), - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], ) location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -5140,17 +5148,17 @@ class PowerPanelBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModel site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], ) location = DynamicModelChoiceField( queryset=Location.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) class Meta: @@ -5183,10 +5191,10 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldModelFilterForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'group_id': '$site_group_id', - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + {'accessor': 'group_id', 'field_name': 'site_group_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -5194,9 +5202,9 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldModelFilterForm): queryset=Location.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], label=_('Location'), fetch_trigger='open' ) @@ -5228,23 +5236,23 @@ class PowerFeedForm(BootstrapMixin, CustomFieldModelForm): initial_params={ 'powerpanel': '$power_panel' }, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], ) power_panel = DynamicModelChoiceField( queryset=PowerPanel.objects.all(), - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], ) rack = DynamicModelChoiceField( queryset=Rack.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], ) comments = CommentField() tags = DynamicModelMultipleChoiceField( @@ -5432,9 +5440,9 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldModelFilterForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -5442,9 +5450,9 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldModelFilterForm): queryset=PowerPanel.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], label=_('Power panel'), fetch_trigger='open' ) @@ -5452,9 +5460,9 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldModelFilterForm): queryset=Rack.objects.all(), required=False, null_option='None', - query_params={ - 'site_id': '$site_id' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], label=_('Rack'), fetch_trigger='open' ) diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 376e4b919..a34ce5c53 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -437,19 +437,19 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=Site.objects.all(), required=False, null_option='None', - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ] ) vlan_group = DynamicModelChoiceField( queryset=VLANGroup.objects.all(), required=False, label='VLAN group', null_option='None', - query_params={ - 'site_id': '$site' - }, + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], initial_params={ 'vlans': '$vlan' } @@ -458,10 +458,10 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=VLAN.objects.all(), required=False, label='VLAN', - query_params={ - 'site_id': '$site', - 'group_id': '$vlan_group', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'group_id', 'field_name': 'vlan_group'}, + ] ) role = DynamicModelChoiceField( queryset=Role.objects.all(), @@ -573,10 +573,10 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulk site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ], ) vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), @@ -695,9 +695,9 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilter queryset=Site.objects.all(), required=False, null_option='None', - query_params={ - 'region_id': '$region_id' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region_id'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -883,9 +883,9 @@ class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): interface = DynamicModelChoiceField( queryset=Interface.objects.all(), required=False, - query_params={ - 'device_id': '$device' - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'device'}, + ], ) virtual_machine = DynamicModelChoiceField( queryset=VirtualMachine.objects.all(), @@ -898,9 +898,9 @@ class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=VMInterface.objects.all(), required=False, label='Interface', - query_params={ - 'virtual_machine_id': '$virtual_machine' - } + filter_fields=[ + {'accessor': 'virtual_machine_id', 'field_name': 'virtual_machine'}, + ] ) vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), @@ -927,28 +927,28 @@ class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=Site.objects.all(), required=False, label='Site', - query_params={ - 'region_id': '$nat_region', - 'group_id': '$nat_site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'nat_region'}, + {'accessor': 'group_id', 'field_name': 'nat_site_group'}, + ], ) nat_rack = DynamicModelChoiceField( queryset=Rack.objects.all(), required=False, label='Rack', null_option='None', - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ], ) nat_device = DynamicModelChoiceField( queryset=Device.objects.all(), required=False, label='Device', - query_params={ - 'site_id': '$site', - 'rack_id': '$nat_rack', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'rack_id', 'field_name': 'nat_rack'}, + ] ) nat_cluster = DynamicModelChoiceField( queryset=Cluster.objects.all(), @@ -959,9 +959,9 @@ class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=VirtualMachine.objects.all(), required=False, label='Virtual Machine', - query_params={ - 'cluster_id': '$nat_cluster', - } + filter_fields=[ + {'accessor': 'cluster_id', 'field_name': 'nat_cluster'}, + ] ) nat_vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), @@ -972,11 +972,11 @@ class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=IPAddress.objects.all(), required=False, label='IP Address', - query_params={ - 'device_id': '$nat_device', - 'virtual_machine_id': '$nat_virtual_machine', - 'vrf_id': '$nat_vrf', - } + filter_fields=[ + {'accessor': 'device_id', 'field_name': 'nat_device'}, + {'accessor': 'virtual_machine_id', 'field_name': 'nat_virtual_machine'}, + {'accessor': 'vrf_id', 'field_name': 'nat_vrf'}, + ], ) primary_for_parent = forms.BooleanField( required=False, @@ -1365,10 +1365,10 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm): initial_params={ 'locations': '$location' }, - query_params={ - 'region_id': '$region', - 'group_id': '$sitegroup', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'sitegroup'}, + ], ) location = DynamicModelChoiceField( queryset=Location.objects.all(), @@ -1376,17 +1376,17 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm): initial_params={ 'racks': '$rack' }, - query_params={ - 'site_id': '$site', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) rack = DynamicModelChoiceField( queryset=Rack.objects.all(), required=False, - query_params={ - 'site_id': '$site', - 'location_id': '$location', - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + {'accessor': 'location_id', 'field_name': 'location'}, + ], ) clustergroup = DynamicModelChoiceField( queryset=ClusterGroup.objects.all(), @@ -1399,9 +1399,9 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm): cluster = DynamicModelChoiceField( queryset=Cluster.objects.all(), required=False, - query_params={ - 'group_id': '$clustergroup', - } + filter_fields=[ + {'accessor': 'group_id', 'field_name': 'clustergroup'}, + ], ) slug = SlugField() @@ -1541,9 +1541,9 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): group = DynamicModelChoiceField( queryset=VLANGroup.objects.all(), required=False, - query_params={ - 'scope_type': '$scope_type', - }, + filter_fields=[ + {'accessor': 'scope_type', 'field_name': 'scope_type'}, + ], label='VLAN Group' ) @@ -1568,10 +1568,10 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): queryset=Site.objects.all(), required=False, null_option='None', - query_params={ - 'region_id': '$region', - 'group_id': '$sitegroup', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'sitegroup'}, + ] ) # Other fields @@ -1657,17 +1657,17 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEd site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + {'accessor': 'group_id', 'field_name': 'site_group'}, + ] ) group = DynamicModelChoiceField( queryset=VLANGroup.objects.all(), required=False, - query_params={ - 'site_id': '$site' - } + filter_fields=[ + {'accessor': 'site_id', 'field_name': 'site'}, + ] ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), @@ -1722,9 +1722,9 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo queryset=Site.objects.all(), required=False, null_option='None', - query_params={ - 'region': '$region' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + ], label=_('Site'), fetch_trigger='open' ) @@ -1732,9 +1732,9 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo queryset=VLANGroup.objects.all(), required=False, null_option='None', - query_params={ - 'region': '$region' - }, + filter_fields=[ + {'accessor': 'region_id', 'field_name': 'region'}, + ], label=_('VLAN group'), fetch_trigger='open' ) diff --git a/netbox/project-static/dist/config.js b/netbox/project-static/dist/config.js index 0f5723b02ca556af0bcf43703b53670b3ae3a45d..15ff8261ba8348fa91eba53c1215a0f6b5ce26fc 100644 GIT binary patch delta 71 zcmZ2?hV9H5wuUW?SEifR)Ra^fq~@n7WZK#)CFSSmq$cJm*((}YAqnRvWu+#UD5rzvFG+A1aG=jWs*<|%FGoWbbK2LN8B4+sDN diff --git a/netbox/project-static/dist/config.js.map b/netbox/project-static/dist/config.js.map index 62f1744f8b4751e82f8481f0b2e5f2d85220b3ed..09e9cbec5dc347e8362aedfdee71ec06742d7318 100644 GIT binary patch delta 129 zcmX>&Q*zZT$%Yoj7N!>FEiBh2PLH0*A|sTal$DxXqOPE(rcjocQ<|!vIK3{AQEYm^ zL>BJ$YZFFEiBh2wyREJ*{(W?wP&Mru%kQ&Kmjv delta 41 xcmex&j_tuYwuUW?SEh^GD;ijpR2HP>rzvFG+A1aG=jWs*<|%FGoWWSi4*+ix52FA8 diff --git a/netbox/project-static/dist/jobs.js.map b/netbox/project-static/dist/jobs.js.map index 9e9ea06b949672af5e03c1f2943f529fe1dd2edc..bbf27ef7a84f4812af5e31a85ba467b73e5d9a2f 100644 GIT binary patch delta 128 zcmcb*QgYua$%Yoj7N!>FEi7jzPVb+{A|sTal$DxXqOPE(rcjocQ<|!vINec}QGA*& z6HEK?i7eZXPh|bH!!*>MbI%4BJJ&1>SFG^ S{fZZxDKlfyb}m1*(`*10SSc<5 delta 69 zcmV-L0J{Iasu|U(8GwWVgaU*Ev;@tOha8dww;YlM?6@0KK}2psEJr~{MJ!E0K~F46 bK|xh4RY7$`c0#v3O9nLq0dBW*P6o>cd+8T% diff --git a/netbox/project-static/dist/lldp.js b/netbox/project-static/dist/lldp.js index c5c9584a7d970dc314f2b14ecea68ab78e02245e..fee331fa1bb169abae5a92ba348f539ee0e28ae1 100644 GIT binary patch delta 71 zcmaEUk*)O-Tf-K{E7MJDYDy{#QuEUkGHq>@lJfI&QWNu(>=g~Hkc9J-vQm>vl+@HR S6>V+vN^^3yzn;$cM*sl!c^el1 delta 41 xcmZp@#P<9mTf-K{E7Qg86%DLPDhpEc(-bmoZIzPp^K()Y^OUx8&S3l_003Uu55NEb diff --git a/netbox/project-static/dist/lldp.js.map b/netbox/project-static/dist/lldp.js.map index d42cb302505ad87581050f1ae4eaafb0f6971f04..cd9eceee7e5080c85c86b5467870020861477887 100644 GIT binary patch delta 117 zcmeBPEBR%uWJ3#M3sVd87M3d$r$9^RD-&6^Uzx~y zc86)GqidFvj<2JmzmBJ)W2jE3qeq^Tj=Q6`D~h0FBt+WVvDC%fdHWtOHhmVxvh8pD I*yghX0HEn7I{*Lx delta 69 zcmeyeR z5=tluB*We0u+#t>0xS? zPm=j-Z#+)=uYIgV*S{#r`)+P*5EfD*^TirksIVY6l6TOBl>AF_v?&oY_NPp-Y~ILg z%(P}>t^FyZWHK$tzaZvao<(C(7+vH5!6h5%Y2uJa=!KoGMG+q)-V>L6KfQ?<aI}geJ&7G$J?M(`01nWaiDn=ckb zw0rBWGxEP|K6lh%^p;RuUn)qgg*4A5))sqz5^{jSv zaKds>9LN|=!bDKi>&=B+Dp9n$*9UBuKeKgs-*V7cG>M{KtykYOA)nl4Y(SMG@~-VI za%S5=8xo^QVYpuZcu-tQpx&vV7()HlVcwUv@t|>v*JWDMhPN#7;ms$70j1;s&n2%m z?T{~S?*fXA{YfENuQQMrmpMU_3KE{&+i?A@+jkM3Z6PUm>exgXJX-@V9RU!@rK`kLuAA`TZ z$6!bb^Yz*$gJK#z6-G-+kA+}CoD7^Wx+pR9nxkZ1^ zg1l#U<3Qf8;6lv$jTxb>i{~~K^GhpvsaVQqS{F)2iDN1fDn{bQglT0B+Ms|k0GhNs z3BR!|2nHft8WA&P*N-Ec+ z{bB+&S;sU!-`be=8>dPFSBDxZGp3a(`4@YeuA+{iq|jHdW6rPEvFH~ooT@`5Q6CIO zvU#a?zbY6-6Ut1=&+IeU(5=a&;HwvLYTXL@MK5Qj!IJ3onG z#ycxTl}=lYMfrmVxC-5|U5d^WF@B>Im4CP2PWkT=->@|{i2&c6H&3^H|mqp zQbBLB=FyAhtE~yG3(8aU`ZwyvV1nzFqDROob!MaWX=tUUK1&&%CF2ny^=54tFUPP$ z!?;@&AfZ=fD#1}u#o7%b4)cBu`^8@V9Po=lF8_t7sP~5FrAVZB8f^MXGi4CDomU;e?igYu=uLv+M1Uu!*15IJ%Wdg zEox@yEtT=+i|7n`A*7;0Bx8-p?>ub0>hTNcTT#lpvU$shzebU$LXm_=h}9`Fs!^g8 zRm57D*A#2NCZY?POhlt%iBCZ;zZi`w12-sdQU=CTL=x=K^vc9;#6uoFa)`tfR?c4B zEZ=@)(K63LnL6z*-GKxhQADyhn)F2feHg+8STy+U1%`Nh%_i z^$2tI?85~y7v)S?&{SYltZ8ZaXWMqbBxsS}eykB6 zYsS=;EEqFoS$D!pi)H!JiBsHAk9vfP(q2W*pSay-<4EvEHCrZ87Cl_qEC4*8Cj(>=Wk zx^o`ET_0|tEGBs~p|WV>Xik;I5#D^HtXLdY_c~4s@{e22>Ox+!UVk2+4ZIxw7KI2x)n1TgQpT^2{7Z|7@MzL~*Iy)7E9lh+q0XS6@oW>A?WmRwb%VLx> zdAY2bHi5D@z_C>UmSmgZn0)rN+vP?5t)whp*AEb<{Ac|MQjwcadPzV|ooqfIEE}VO z9yU-~uh^>ovN0q?gs8xkfYzmcg~`JnVMOWD2rz$0zWCeS@>3^=IeM2o!f3s--m=&a zI$1{*`uxSejd-s|4NauEU!k$nBh1(H+R$6{9=81(P6?uo;~5^6EuRl9>1&OBIJw0NZz^}?J?$y;>>9PU4cEZa+gN zBISH#v@Fv88vf00s4rf!sD5SUC<4st+iS~AH!dy-iS~*DQvQ|kMC&9*1*n%pdnyUcN1~ViwW#l-a;NFID8)E~dp*K* zz5nxN)g|;r#eUwuesDAQRu;fZ=w~4(MG$I%qMFup=C*A$arMdXGhI0C!^F<%s%kWo zsV5^YW)soYF3WrwGdzfv5i>Ij@~$&|+#+XT16kS|^Qo;=|{l(?7F;|~d;?U<|F}=DvA)oJf zH%0O9cXac|enC$%@{PjM4!goM4p_)B`Oa52ZX4G)B`@17hakFJ<=+bX$hf?vvu7*1 z?S|Q_WV~^zEY5?q%$O*gp-5a9D~onMhM}@J283x~AS@fJ8^}ZQ>pNTNRQUmq?g%q^ zbS--)l;(#$LP$YI=sGcPrbiVY~-r&#~>>0~f^`yTMS!fc$hIbzXS$91;;0k#YjL`Sn3GNCj={uqo;!7VPN~1&Bc$u~rvu7dXicxzla{ZY zGmU_F3$Rh@8RxWy7XxCB^VVWaovXtE)!$eG<~ZCLPy!i3FrfM);h3nuh^a*0enVS> zGbRS*vp1Ze!5DWlx|d=deT9y2tfSb0SN&PNnp_k7fx6*{nQo?SdQ$h1dKd#%Jp-Z^Jm1gGF_NKey-Nqx@z-N zQZbPYu*j4~E9<1Md!#m{Uv`h+t@q2OiiXv@p1sW$FtT6w=#I!gziB24j#-A8RWINO zXfA3%)lR({M+^r<8|M^9OzeeB4LE}%quzj*`*;CSby?RHqt(6M+;E_Whp6SpZ$7l& z9pDD21AkGE3I2{l{?D6JO#=Z7$3ShQ`4Cs!6R@QeB{Z1S#Je{pN+EQ?6HslE5v{AE z8t&)OMUH#eMWg507!RdSk|3x#_~`qx?&k>S+$d z#5kzVd$PKkl&3G8>mGa#(-(%(z^-Tr+HkbS-araG*gjlS+fY+v=I+Zw+V9$&C z#ZamQi$WL!6yfDOH!p-C`O?KE(g$oD*#T5$g@O<=t@z~IFP_JW!S#!$bW<^ld^U7c zUhUZ~|K;L#ojw1;^w@^)xApk-js#+9sTuvHOLeXXAlu%an#s-z;BkZe)t(zs`L;_p zT{Xmvi>5YF428hm_E?V{X$;zA(c*uLGpMdj)YpOl`u6r^p2d+6hGKB0rUOWnKz@Y- z3cQwy*i30woU0wq~H<)wX8NN0TrN6+Vh(Dyjn=35fyDN0S;q493)$P@*EH zI6wJ7L&axktx1?($XCR{n7M#JSyp+ghoy|Z7|h6ZHJFf1_7hF{iW1HdRye9Hz8G{! z9z`sfiX5_^CRzDa_RsI0jG1luIc2p1OBZs`aejLu&Q;f!CGH-EQuxg zZ=54kipxKCp7UWK(;lG^ui3>hO&sGDF$Ph3f&LS+aVTGFHa-)t%!>MDy|u93RV^Tw zl@qRG7g4J;B82L-<|^VcS8)@0b&V~pwK7)`(|^^thR4lyyC!QW4{vF~^~3X7nAE z3a?D?R>VjmqC1xZ!GA>05S0$kqGi0Diek<;K9{n2dm?v=EQ09i75_ zSTW~9`GPcnrMTXTc=ooLj?UShu9?Zo>{(&BB2MLv@py;6>lQs%QMatF)&Q06n-tKw zbJm=O%m%Cq56kxr9wKh};lVbzyk8h>;j>C;LLOwmTf4fIP z1r%0Nb_{*i9bTu=N+cVVY(>jr+}PHQ7!#Imv{YB!?w?br6&VqN^`;io8O9on%b&XU zu$*%5BMb8F?h~f6f~eAn;IHR(sj_SJueaLfs>tH5Ci(mBo4AxjM}$B~=5~ z$M0fDwbPbCZA^j?y@`tIgpXsqz`T&lh!f!Sv{Vd%_)~Ih_!3!`A0BQoO;v<4R)2a! z#gGNYBSHhh7|2yy4(Cf{;{#K3yj zS4N$_v4K%%uLXudEL12CNlTWo3J=rsg(jt`p^A{rxbl*;ELr+0YgR*LCYMo6T-5;c zDoBcr2$lM%2Q{hnRn#eZ8cJ53ZkuYho#e$VjzG@3^(kK(IUlbszPP$7d1t1fQSe@;r$cEzJ|fua%@@6j^a>fT+I+&RS`K-ynDB0#^{uwJJhHV> zo*X&o$a^vM7GFFUXS_2-FOUD#?4(|$x!j20t~ZzUYN1T|kr4|fgP)BY=Zksi5n-U7 zr=aE$LSE6!shmO=xr&c?)#yUWD>^uQI4<_`r(5p#ndyMakgXG2W#$`!!v0U+4LgS8 zJi@@2eB5&TXd5ZW{i7}fGw&Vk+aK~8qbAb|cd}B5FQgGa{m;?vBkn|PUEKw{jP8RQ}sQI}F&z14njqDBLE&ADZ#RXBC_OFM)GgN8^B4=Xq0&^6=Pp z>`<8;J4rn9>e$pNgVJnxL~zxcjd@i`TZk*>q}5f!;g%gjwl?|&`Q-RnIO_iKlgAd~ zu#91<)=l9FrP8GlVVTbf;kZ||S94xfMcU)yC=aHjy{cV0=M~5Jl(py;om{Ply<(6* z%OSNRfsi`eFL}j&PFkl|wc>+b(SWpdxz@n}l9T5rZXxOG@0hR=VwazuEFYQknrku& z^r$8gUwoH~Q+;s3|6ywBY}jiI!?44W2;Zw<6N6qOCtXMYv_50_)r~&w?Td1B`tL|w z-Zpa_@!r!j?b`>H@j6FftYf^0CuL@iUG-}WThT^Q)KrW$J!7LhG( zdB<(X5z#i?W*}bKbK7YwTrb{c!B9VVTaJv$`rzW8u{bQxs5uek+%AmE4+p=rBa`Fy zTW~}u=6C>Z*cVq>pw}zTaS{(}q#y8#6P&cuadD78C)Hgy!eCxOin+ENnS|2gtmE;D zZ9e&_D<@lgalx0bS$Bzovr?2Yg+w?d3B3tH%3)FXxZD%EB|732i@CbBHvoCkHUj98 z3+=**^}^P}KVxq~oR0IgPzOTR#e69OXWEEN>m|4cIQ#;>5=JuOi2R+<$wo&=9LXpv zscz+s+sM80fv{n>FAqJahJYk-P;kGm*}X z-xK2C>!Ro7H%E5M_UJJf1Gh!ZZH|!O4rwvNl7jy7h!Dxutj*(Pw7l(F*XS%v)0Zj-7C7qq=>bzM6*u7%iq*?Zg z@{^ld)-hcwnL z`{b>$RyyvL|2cgK+-ZwVZYkv8&_EwQ7(3T6M+VvGBth?Qu!{6Mxv-WUHNps&xh;_t_D_hS3gLkR~a zgr6pSXw^DjrarHH-$DnOmYzM zb;eX0=Q(@>6J(Y21|}%j)|nt=t1|&f$;Z={tr43TvcW@_gX!a4CEH)KK-4CdZ0jr# zv#qm0Tz+r56;t+?(}$tgpH5G1k!+j;VsdZhTtm!ejJ=oxj{m=KK-?yOV6ORvEO7mS zEFl}{|8u>wodJsLhU)8sYdOn+?~JUYR0yK+Ifub zuc)1^1A7W6|5wybtbdOx)Q+!HJ7?3VT~?@Ffo)x<_F|3NH>Y!a3sx!{4He=+>|%)r zOPDAycW67YkZ~rfZn$x2_AgwhC3&UL(&Pk3LbvY7j8rs&6n zFS|=eXc)@st^@K?X>@!kC)zeJ%0ft7%<=6x8@5ae4jTv79BILA+vpH3?0< zFZzPX1MAG+sw7+IZHP$lEivX`kS~D;gV@Tj&W!!&(GmHXr5*AsmTrVY_{pUv?t&>W zGvcT%%K}0`?&T|id7E|gf9X^Ii@>~33on8J-JsFGmwo)sn+lIjhquBDJ zh6ya(jGBYrT<3{p`THw}yER1Mw@kyeO16Nlo{L$mK zS%S8jZkAN>os=)HorOzy&zj|C@Q30m@}e0rfHE+dYWdM#2Fs%sb$N7s;6pY!Gk;V* zbo+!s>A{NXBeb=JbM5Wn91rLf*K@;=yuBIL>HBZDfq2i{?k0<}c=g@wu8`S*^+?QL zi$HQ_t(F!SGwX6UDDS+ZqemH%Vp&L{GV~rtU6EPz`dWV_?7{%e@L1ZQ+k!dt);i!{ zS39nnO|h(~ozYRjUROJzE@exCkm^#yZjmlE>{jYheKZ3%!}M+N5mrK7K#zj-f|%-p z@q@iVkuGBajvS(8;+@~TYF}@2B_+j*7DG;nMdTB6aW%0XiWpb=GCwLz)cX?cQsZ8+ zF2&NcPOMiK?J~x?xcR|%C-7L7_NvzuY9Fs{v(Ysw3@O&?sdAUS{v%=ex|e zBvBa_q>A{L$0C1k*XrtUmo?c11ARIq*6C0`!@zYTHYmB}^RHOin@1ErgFT;#NOB2# z2)x%n`HJ5WsPGTJssuCo%&WyC+4Yf6*H}A~5*_l@S0CQz=~6w`LRu_k;bD5@hhJ@u z71C?M3h%!KZ?$bDd6dDH>QSMjAom4FGcqZZ<@61uRZn*W$U=QWDy=d|B(26(M!U3K znq6Wc4r(ScM6Le@)h$;l#+YiBj>t$ABdkAPgcJC4S z>fUXer4D1Jr(gc=YmT*`K;NhktFz03CR8r9|MEYe$l2F^2s6wNUpwx0b!i6DhJAx+ zh35uGgf&cWv>+_Z{+Hd`+BDfEp1o`^&KTNHUzuIK99`)a z&aIiw&RKKl>_r&nf4=v~uBk4*JXR9>;EN5(`un~IH~JLF&Aeo%fSxmCXL zb%Fgk2d6*+(>E`$x{4~^__}wVSaiVQE%0+CwRq3E0-wXCUb&UV9oO%a2O8+2L;e!G zfu9OmNDGVdrH5>C-|J&!;rjbuzfZ@(o_Qh6!PmFEY3pW~q*fbSc;$nHQX>^WgQ{-|%undSf8kd9oOIe z%pP)lQmJHWUg-O48S0b2{_BMu#W_XF<^^evYo%KU)1v;=47?QhDzhu+*7Slet!(1f zRsaUmf_^Rm^KJSCV7*b_F(|+NH~-u)>Od&uvEQ`G_dk1__~h%)-f+~Hu215KWYrW* z>%2pL{#iR5K>KrcI_i+`daebDcRqI~MPGRA^WtwG73NVL_&}RT5=w7}=7r20SGX_K z33GDm?|ytDt7Pe$7xI6dB|oQx>R#KrQ+EFMU7O=P>wx@~|8Bg{?+_6`<$Ztzxcfy}vPWv5l z-(ST23w#Wg4Ms>xe&8<`pmCo3%MjeK=I5Ps!XZbV@7q>V$`_%lu0L-hQTeyeKSg5q ze}k+vpk_&a@=u3%VJix3qh$x5;S+3+)NoXOD7lZlgOE8=U^^)J>7nSHu`m;w<+hWu zPMN@xtr%t7b>zb&#XhAYhGPQ~=8IxJ6e)_OIV)01yg`iNo&7~eD)si*wFc5i4G#9M z26CF(9o4Tiklj%D?5Rz}iUylE6R{ySXDqQ)DzV`%Yj1md!029|dWBxZ%@i0i3GTHuOipz! zj~D|2q?)gO7y~dyagZSs;fG?Nitazm4xS+fHqlJrK(k^q#^$cx-%R2=|NrYi{Qt89 z-Du2phDZ@Nw4kNh|xOZgN8B5?$=+Zenb9t*y;+iW}4B(1y-< zIWm~(9BFHEb646{#G+-mgq>@>^@xU>MbD9&cJwLS8b}G1lx%ybi3Hf==g7f*l@!od z4=m_=D(vZVdFsu~&DUC*Rpl z?ChtQ)Q{Q`r>b@FU_{MC#4x*XE*kQi2BQy^*svIXcxSakT+TS`3?^S-p`W5Wd5qwJU(lJWJd5Jvk!+usSJk&VG{LFq{S_bU^^z4b z$R78Sj@=$fbV@T(X;yF{D8l~WCC87tioD72jEB>tt%A8LQ0x$qW@kspi34_%HJAZg zrHXt{TYLK;K3o}rlJc-SN66tlF06YRc?o`~z&gkt9wF!LK5 z{D;jn>|P)F9%MT+O1|63nYAckYor<)=X-yQMRvtcPIVWh8Lu>pZV8iE+p&uk>*THW z+J?``jt-S>SxL0dOwL-Tj9K=mpNPc8p7WEJ9v&3(=3uRLS3aBOSQnG*wE<$^nOnry zNGe;9#5DW&0BM<=;}EQ#WI|Xu!DjX%lJli>E|68qdBE^yoJ-D#OFScvbLMdzC7HrI zkGBLl5HCtzKTj01b8{(hJHztm(|etZuuTTw3<&}LR%ZRE_8Cm##8=%jL%yja$?8vTBgY%SdYdAo7mvXR z)b1d=7QsydlEiL|lE;vIE=t-OE9kj4&ntRPLAw{M6N_a zIUJ0ZELa@o@Rc}e-Rwfp8t-q5lM$5qO`OE>m`RY6q{yx&$YJ8CvIKc0;b>@05(j@q zlW5shy*o+XNJx~OPLpvGXSb)xdx(RXGUSg9F(8TU`8+vVwPneNV8KlGW2oaK=}3uX z?Ae| zF@)fGew`)V)yV6>Qk&xI_5D#M->6~i@Rnu1^9*SF)%~Q66UAbeMpHvOMo;uWia?sDAVPq*X`4?Droemq;(W@F9{W zOYGqfkw-bl+;*M3lRr0om_Wc-;=|-kWVpKdBgDaZVDM4W(E=?{#<6*9<>A8ssta{o zL!~F#-#kh_OPtl2DtQ|rqwLQg1)Gnum5)J;UFLlx%0e`~rR=r&Nyad7K=BnLhJ4!C@ozs>jKlcrk{nrO77e|k}}Rg z=RQA9&anMoBcAOZ&N9F|rX-3c^3RBY2lc=`cqKMQGMf2K`}TXU-%h0rQ4NV zH{7xkyY_o>gdO-LY1w0kk%_sH?~~!C7PI}5m_hyAFUjGnc5^V63Kh9$2DZZrT|T=6 zjBEtgEU6a)Jum<(tE<==FHD(pr9vEL+Im&ByApVpAhd;S3NCCuj|~KX)FU-h=IZ8O zk)s6s)%pxsJ?KIYVxdxs?>K;*^W%*!_JL=Jq0?nfWpRrOPQkDH6+zPqz};P$Lamrs zG%7{NugQUgOPPw*`U)>9^}=Se{b~ zg}7b#S`UY&@_gT_Ytfj>3oD@*cH|F3Z(59qgG{Ax4hjH1xhsHW4KTq^%P5dOrhAt7 z+b2>&SVDVJJ*%MxSjeo5TA_SV>Es}5`7Jrs zH<%C>6H=Mq(W8KU89_Prqa=n>S|}(ZaVt5e7hnzP!`Wgni*ul`yYx!sdLhK_{w+Cv z01bp7--Gy|G^EGe{0V$8`!d)|uQj6=>_seEDC5)%t}H64bs6~+V!Fs?en*UZI`o|g zb4h}vzA*83WcccOI)l)#Faw9skV2R0ct-6=^Sc-H!ZP0Kw9*R`^^BaDdSM)Cj!wNW zRm-S;7^`Pg=!6~r04P{Fs~7red9`l_9L5G+fq5_jNIsrIb;4K*g@nH9E&q*KhpWur zldJdNO?Or={sAhEE-$iQpQZ<^(f=WnbccOWkYX|18ev&xpZgOTCJU_b&*ULIKJjPr zXO#ZfU&!k~V)ygpUy1Mj7OE$c_uJ_J`_^W<^COIYh3Lm59t#7rDK|w)VuGh}3ThIe z9g`Jqg`K^c(vxJ8y`Rz%GQpmww11aNTHmMOU;!PyVY3Sb1qXYLj$S9@%+^4!ktz1o z2D;n;<|{DYCW`G+?4C{3un&MmvBVvyC4EmyvJ}`8n`nfLu~VCA6t2OmH`C4|Zb33f z5R;bj-dK!V+3wB&53sZU*+I?h&ztEtc1+cWKgPbdh4zsl*1nbYkUkdMO4H!|uWhBT zK249d|g^rLwE{t#WG5Wa%UR?# zSr#P(C3~bWOCF)eb`>{N;AZj>>H>RaCj7=d$>LuBPsN9kd! zqiBqp6;Z||7s?Z>US?I!MdhRVUI+5ed{q+_>}#S2!J_R=^fo+x^(V~4Z)u`Fyg$=K z--w{)J;%UzA@+e|^rb-g`DT!2kX>%3pFs#q&LNj6ZU>k+Ob%q+NyY-+02VFc#zlD~L7-(mcOZ3k4&k8{?E*UW+ zR76zh!Xm3U$btrnRc!V)1HExOrsSSVPeHPT*i#02$OpeRV?=yJ;S4ylN(wO?Y;NE_ zKaPVJ5kBR!?Bq;v_Er&#J&}ztJBJCAGg(RfSY&;tsNs+c+rY56ABH+huDSVyXmlYo zapx&|6i(n9Pto>$gDNs`jfA!LFGfeKXDq8;t*&v+hL@yY@JTw z_&*RG74gP5TVmxqC898PB&YGLUN=HdoX&?gn0HyQDDH2<^-EksOyv`xuBNUsAe{s<*V2mm%ATd24%aLq6@eM=Y-b##Lc}81)7d+N;|=F5 zxOf9$B+d*{j~gHhhjS`xFeRU*)6KqrmL36tet(wgsZV5=y68#P(?!o+1`&KSXaR95 zAFmzpr|}}9D!evCaPSv+EQ&Uz`m^Uc?VTm5Gbwd?5cI3P3WNCG$xEC)*J1A{NgYn9 z!(%D3FLy!tjj>;J(N{Jh{=~=7kt%iuik*=n4?`({L3VF9J=6%Ho)SC=CQb=?A=d+~ zKM7my0AG9)5rJA+3-HL2rj$7&Z122f~^Pr#TX6+)q84P=y z2rOl)pA~7A^dur;ADl|1{Zd$*31kEtEVPW^2L`KDu$01@*%oER z9(wbhXe}KJi#G^{>c@L%kdRol$wv2(t?{tfE!`yKShpQ&CC!HH)Pp$I8|?HH;v$dR z=~+^!K4Ygk0>OOFK`-KQLodX1j)i;a&o<}6FvLP^)Jb29sKXDOkV6A&cF`-SYt2P} zk0CGiVX8~9v;Fjoc>J-S-iSr3?g1*1MaBl`tG75LksGM&2fK7fnQf3B*s~ZmatQX$ z6tS@hBpjsgMNnk#5bZ?67l-Kb&QJt1;2O5$tO-%}PeYVh!eMOryUjd%#@HiXHk;3w zE}K`)XU+;sfb;ZO!HGAE<#H5TfrUhYdnmDp*ewLv{chR~SMzgjdV<8OKX%g_D9N!V zFKs#-i*$6XUBSYPxs-@H7h%j`?VQ8v>mg}HYpPw%v51%60!Q;rUYf)T!`2b{GxYe` z5&CwF_5mLib}#YlHO`K+Cw;J8!t6Ib%rAa+ew0>EFJfrQ1$)>Tpi~Y`TbhaBWQvhL z&~L79=h%Kfy`?=DfijkAn-7fPFyFU{n{dQJPk`&(3^cW+%yNEuFPVEFK&MEBO$X?` zZAw2hW#3v9i}fm&lq!Ig?PK)Vi7>j$6*m_C_!$tK0^&BJ+P{@BbBxjc#`O+I#1H~J zxMBf8*$2m9u~nFU944oe6~-w$5{bY)&5CFm(Y=Dm7ay|NJQc6%C+KfrlT{n1xY6Wg zFPWx>lMa5nr+_;({nCxLF#LrSuC3Gy4!nj7W-XO1 zh*!*p6-RjOir~f<<@TP=P%fbtdfDnMJ>eb>i&vE3m0=}YK(2vWI;sJZ3IJ}pk~XZk zd0n3M21oE3!)+D9Ja4_e<8ePSaI=Ug#`QcEHv&sn+VZ>&JZ^7PV}%}gs5Yi zJuEmQ0@m@_z7Ob{*;ttF+3bv%tSFQ_rfXzZ!;rLK^(|rgEFnSmx+p!jH3&}QRt$T8 z1a`?!qx2(J{Si?g3FUbRIR%eS9m6_cR8mH<%)3)Y)(xYWKwcaf%a+|RRN?K_lB0YF z9(=yAcw<+WFcuci9)rReVnZ?dGU(IM*m-R@Dzurey4GnI&%){=wxti{tchz}4YGOjpB8gRM> zOi7`|T2<1Lc%_&vMdFH2ZMdp7P^>{Ye{01vHJFqE-zoh_0F=urW8-0V4VqtvmU0>_ z3m6te=G0cy(gna$*^pY9VWk|w$PVEU9(Y}0Wi+8dQ*39P9^DyPg6q%GpchK4J5CQZ zMFFYNs}o_3bf*>?h_O(d9&U)^JKL9_2M^}(rggPb;%Zheq}kua>FLHfe8J`{l?#+g z_@cy9D9&THaoTxo>4iBm(FCqB%jR)f-^nf|Xd^gmJOKgnV_ATn*y#nUC@9qnw(7eR zbT`>$P>v*dq1%?01UAwN7X8*d{RA|)uL}Fv&pwz$H9q#aBwcG=&m3ODDQv!-SyN1W zVK@|FUX-scrJ(*W8U8U%8PuSh!NlrgKg>`E4MbQ-ue-pmWa;+J{s^?`5X)t$71qRi zv-CbFCNW2`#KT^ZgTFM*9?8*%8*LF>3Siby6u<&1Oi?dOF3=zSUp__i^sBn5aK{5n zv~d@9cv;nc8yA<@``%BF?95_<9meXrF)L)*9R+INmRN#vz9?ZC?n#60(DuBNOkj%| z`$~)M#HQR5JWuxi0==L^AtevZEU|Erj_m3S&q!wQ_$&`MFyF)UAp2^O_HNbMoMSB| zIF+rxGT?Np@n9rgyGmH@(E(GEa}NM;57Vn^uuigY7HR|5QsK zt2S0(rPQhlF40`054T#1(Vpm%rL+W>B-#^Ovc#)DS^^J%6uVaFD2&c4D|Ci5IWSf9 za9m26p6Q~+SF~seAN%?$J$VpSO&4czF`s(VA9uSQ)tzf}4}~$)e3gE`A+&_K^7*T@ z{ZL^^sGBX=QLgZm(a)@R(4gSpsw|sIg>qON5!^^Y9j^mY2}PB;xr~+BXYT;r1MHV~ z(6b{I2pkWq8&*;YeDrEb2(yy5AstsVkCJq#$*5HO?gl`US7d;^vhpDv&ZkGw@|ml&TiG6W5P=iN-(g(OK7l0fKq}z{&m{M{`3-h2%+u+FNL?i z!x33iS4**U_LW!Aqip1mZX3JyGWwDl0}QicFNg7LVE^akRD@Bu^)Bk6l_hquMc2gg zcfn(Fv%Bx2ZQHepJu0}XkKTn6n4YCq(jQZsmbbM{x4D{r72QM|97~8K-T5kT$ZPMW zZ`kbMf)rrpd#JdzH)87PjaYhF;T|f$Fn#bI7T%-D{BX!axi=gc22GS{j zc>q+(E6IK>3Cb$z1*A2~D(NI9o%OU~CBjV+4}kTl2iY{R3uW1#uF+#A1E|ltUqXD> zuDxRd!ECD~G=)9EF1?Ok+CL5`oSemQDBp<(W>WS#z@uYJq9RE=P~6GOTa-7g@X*Gu zDop*ZwA5Gos>YeL;#xwhVG?=RO)_n5802r$GHq$_@wYX+K}Eh4k<7Kp2+V8mkR& zq5-mL6loJP@6?^BuDqF6xQ=@6Ei}B#4n?YMw;Nny;#)CwF0X@p?3Hh&`Td3^9Kq-r z!b$ukOQvUX$Twdk)#Hqp2#dTMhU;kc4ethWko>}X z=y@dn@*ZkJ&^f~X@Ls@2tCR1e!yFOsd_NtgMJN01`)M!DIGObknjDFJ7nTY%X+7>9}6VqQB^omYP=$)~pkfS-_VK z2CD&OoCR!ifUdB!iywyn9b(ZBQ^(bmv!>zaxosKIk|TM=Op;)pDez@r0ZgiBeg!ZA zfT})}WC`VX66!-qFXqK7FCy&+F6Yz?x(_`{--2+nV$iu* zx(Y#0T_1zZ7iFf8(f^?-C!eEQne*fH?G1eqtT!)Q z2dg~)ae7!c2IAj$H;4~cYRRqGQxR5QeS{t+^{T)pQXxl)K@KMH%_?$flHMwB5nRn7kd z7jrjP+c>X+Jz?;(9qi&~sh+*{vvdh?F)?CAfY z-=&ig_PrB2?8oOEW@nRMq-Ut#$$nL(1~$^7+g*M1i!gw;O~V=HIyu39xeTO%-Z>gj z>B1iVGMyyTkNz{=MjDEUKQdnsJoeT$-ClO?U+6sbZD6b&lbo@FPVCZIV~;|M=f0`#3<1xxm_AL3)+|2EGqehbSEZ+;&0Vn2(13-;nd^?`5Ef8uL+Gv9%c;b1G@p~ge1nWHX! zTX0o2!V7B%tA6Y|G)E4PIJMBRx)DLW8WH;Z(s$`E5mr6>J=pcjY~p*=v~vQTQ&
(D_3^b@f0{~q3U^xev_d5+;8c*>f{drgY&WSABd}FtLJ}& zNFzdL4?ay>H^Dl1;%D@0WP^@bW)J=x;aCSFzksUCRNu@Wa4|3ZiiS|^jlZH(I`&Y5 zuAMbK3m@0Tx}K$p z(wlUi>c9ONy2~Pl(R0>(j8x zOjNg<9eWC4Z)|1+V(Fxl-Sc12t8b;c+c#h=#4hV}O-(_>qCiI6#eo<+Za1ih2vYp} zZ5!kvRAO)YIVOc~>vW+58}gN4{=s+@SliF&fd-#bm}XLg?h-=i?`+V0mJC&awk~XN z3$nLv)*Wt?g1|}s;ftDyo zY${PGcFrLHlhdFPrIU51r?fE%k>dMi^+FU-Xk~5eTa8*rl^KAggDeuH$&AWa=@llcE$966*d!Tv`!f5A4%j>N4;R zLLhDd_rr#QFLe0u4dxXhBUcP7;li5GYFLS~&HHtyn(ALt8;TU*2N;-hzs?WQ_}l%u z6X@zk_v^aJ-fU0}31~X9!2WPR*M2ny)D%Nu7(0038j8QqsUd(kr&mtFC?}K>XHJ8p z>TET~V*qn%QZe-uz#``XB}Skm!&(xPoswQcTAS67HmqFD@iv@jqvp7FBCK9QSS_(0 z`;CM0s+i^QrivMkh=4ikbocWlctvR4z#_2DIM38V$a6?o3K7_LtruHU3H&jK*zrc) z7A%sSYSaxM4s5Km&O8^-7Zlig-vA5cKM(7g5GT|f(Oo^J5n-+bp|luqdNh%W zf&=hl5oz}3BRT_Cy#DbBG)AtZ*>%lFbwe8zLxts!>b`#{UP7D?8(UIX-*ZDW%%N!1 zm}7HIx=Ac_Jl>=`xF;AytQ*(Ht0AC3^*@?)CrQIn5V4)@&AI^?3jzEN+s;KGryljD_Zx0h&bWz=C(8OBW zbO!d+$FZWn#GY)?Sz!X~Y=v?Nv%ywfw{EFMEm%lK_K8-YcYqf@#tM zc)tM-F&@p;x1Pcv_V?ijJ1{K>g_yX^Zw2qe5jdl+js2lrx6@aM;gGc!Ke8a928t%N z3-|}|qZR!Ar}2VPRPd=k(@?(@d%Dbz8x59Ch&4>%64CO^G#fvyI}4NYuG6}UeG%Mq zYO=oIKqikvWwjf13%F4iH<5w!QdrUuLIE+#FGfuT#1L*MR-rgTlEq#Q@Fdn{jk*)G z5UAhy-jcbb6a1>OD0|qbJ9jQ0#~{@eZVTSkyg}{iOuu$r zZ@D5Ogod*%*lp@(J50J0r^*#!rIaazV(MmoC5ASjH8F>)wRrXc=0VopIo?F=dL|1} z|I4sPaA)QEQE*{NyMb&}yZ6<}K48)vbkE}wRrNx$e&r2QJCNhTjyY!>KSNRBzYGLk z6>7iKC)8GV`HqD77hL@6WP8tm82#+h866LMyylGVoF}B*>i8m`mQk-l#<$W>D-^=yxOeuSjIF|%+{Lnqz#u-6pp_N+d z?*)jJm;FS*jA~EA@|=b*B#wVKtaL z4fS(FIFZTTYK9~J*Uc(Y1cb2lp6-=#%m$Bb3 zbOh{6o!w#oPD2G*sx}E&rf|zn$TnaeI6X^MmyLYOA^y|o{s*Bo6b9^NC_&VE|;M8QE-|g7Ob%GvN;0naz;jNr$qr6gwi9vLTuAGjRpWpW|3ksg~Fa zGutyeGi%jidqrkTW@Tmp!hz(+!_a_#vw|V0HZnbjH3(bUy^>|%vVSGZjzfnw`RJc= z;I;mbm8=IsVM{KXYiW%1=dvd(pzF9*?0*{92S#I-jfj@8-6kh^qf_ku*I{JxGQ#$9 zTvg+i=??_*D;AdmaX-A;W`v&9JJrsBIP@oMlY`euemk_G3Oa0Oy-L_d$*bAwg`EK- z#tf04^GdC_-u4yHA{|n+w9A-ZEBEiuEy}!(8PRpOz8;7k$yiP zQqWId<+E4jx)HIKQU;joGN*ta6nx~icLcB(l2=77c#jOj6No+~G_Vc|Mls!7$BHMSoH)X>)s@~Dv6ir+xVm-|J|keW??A6)z@zH5 z8AoU|28=^0bbzafF82VB!j_J}5&RHJGCCTSn{;8 zygt;Cl3p*7cS;4KeUUA_)T!3fr3$tru{nxqAtoqtMa5B)we+_NOpR?czmm;;AkAh+ z`ZqEL43HRghY5DG!DfIIH`wfc@x0w@58;}ZMxIKngd6BcB|Cr#xT1=sLuuMt1@>vD zgH>$JxCR^IQFhR;@&90{`T1%CsYPuvt8r-trcPKh(0zTHQJotQ0HV5}X7>t+0KX=y zRYRH~Eu9{FNE2k1Xvd(lQyUFo_C)`8`_xuc(Cyp*+X>U?R5eRhx;6T!nk_>l&flt8 zPF$M?VO_8Uhih0W9^9%CW|l_(T?5W-qMNnsQN^!OLmjIc@7B^`%4sxQ$2P<} zftaDChc%j1&mK}*H7cxUDG)B(>LGcMU0u%>PIh3sRpJ2@+JhRMuV>}=v}wRN@5UcJ zGPQwO6lgE^Ze;nmRBr?)v`}Cp=5$}=#f@zGbW2ad zDc6fYo0t^nT1q&|YLxBX{av$XQ2$Xj3++E}l=Wwiq>}?p0fGC{xsoc5tupg(#ceZD zAMvQzFc4|ul>Qp~L}}3u9E0l9Oo_+X!1Ou*xCq~OG&s~+MFrb=a=i3l*;};8yT{nu z!s##WQsxkwjNQwZj^r`O6 zXoMMd2%A=%Rgm84%@7&{l6QPRVeNzy5SMIjvuv6E8_t)cb`ouw0L7H|6DoBt9FS3O+@gnA2A!S}< zvlndtUhh7z0EEU_cL-xPDX$tg;I0|DLHAw8hwHxAhcmYt-+||6TCl&m5VC3MON?j=UUM!X|3qgSX>laX=(tNb?98aa9>+HdC z4O0FBCTHfva67``tU~tz0Lyh&rIc#)CzMedHA=q$UtAhJdjq|#*XZpVY>!f=VKa*j zDC;zO=O){(Y}6>{7AuC*GI)#4%1*;}fy^fe=!ju|0MT^a0`i%#LOqi%F3$N z==v>|JW;+X2iQwr-(m~Vf=JSBwjmBd!~Rb&y}h*i6ZV{FNy?{eg=h(`^QiYzG!M;r z?o+l^H0Q6MvYKh7nm~PZF4lUqHsVB5>}WZ3R594Oto9JjbfSD2#yvFb2SD z-{gqstGPEh#VAtu%_99mYpxLG=+6!Ohe<#{L58BShg)bQIzr57^wX2ki5#JEjnLaV%Z3b zb;VR7u#k-^5h9{jC=rVm!PDUKv{i^hb>Ypx=3#1Aw=39Jcp;~pl*xDE`4%V1o(?3&kFR@{?XT9u1N9Zv&)!0 zkuL)S2HZI)PFy$Z@r?z8@x@eYZ05-C$t|h>^LzjBbMkeh84Pp>;EZ<-nx7N;l~gFk zG!T?-!ZIZv#q=iEkJDylOj-r#of{gkyG37Q-6AAWL`MTRVYK^rVYKbJ&=^ME9u%*` zZnKS&6CO9x9jQ>wqUwL9R(nu|mr58Y_z z5qj0l=Oq}m6bo`;$6Sc%77v|w^XHXfH+6OJ8Kigc47kGgb#TNgME=mh>m{I&hkrTF zc#Sf>JS$HAPg}hFek$?ud$Wya28am!j^ARWP%M$019m@1kBmJpPmU93TMb06dpZ0d zeUUUj|4OLW30*umz1S^Azzy2_k(c1MZ$cltco~-5-*oX`DhTfWX_)s|jMhZ#Jse>P zQosLI)J(_&^qHk8a=4cx2Y)+V=;tNTN3(bG1xYXs4DRak3H~>kyO!#9^0%V}7Yy*F zu;FV5xNyZu>*M?YPex;J5AbQqAkuwg`nue_GLi^{nQSxvq`JKJnoPyi+(rA(?OEykMOT8P#E|R(A+*k+vZZ$4|o?96e>yd zR1d#r&^3^{d8?dE5J6IgMumZqMd-`&BDdZh@VN5bCJeP;Q5Jfe(UJO{Q& z%P!slPQI~=Bc`q;^2(GBV-bHU$j6iIF`fVhD1MCpaEdV@O=TGYgS+{> zRR;M?83Xscz^wVtD{j?r`b&s1enqx8dN-Adog(R^t_1geVbW$!c(eafgO> z^ZAJ|bH2^Dk;_l;*O{d}vh7Fw4GZnw2aRFTUOwyIB9TZws=(Lj($&zq7tGyD|FW0g z4|6}Vm*0f>T(BS7_zU|$mpb~_eGnW7VtAS#N4bxm=8ZFY0j`L3F2-yq5U(6Hij~o_ zXLvJxe30Kechh!Vt<=>5-OzwXbd)gkGunCtGw6$FcmZg7-?O|JbFA%I-l0G`$p(B$ zJbRKT2^(6d28EHdAM<{Tr7&{jIbI0qM8AE3+aXLB97G?=$#IZBPRCwEe=`s96qq`VV^EkD91 z(+4kduYyuJNBF)OL5Em+W9aF3(7ZSKEc){itQIu}IhMb~v-15Wy5A1KG5B2J7Ju&& z#Gm_vOAuR!&AX7pp6U=$;MQ{a+lk+W&S0ncvxAPj#1rS0=m>3Wb1(6Tk}chymef&w z)8nAKFG0U-b&%y{zH~~r)T9OZG30q7y>B*6c+xV7Ccnz3Qs`yAW}efL3nvuzp;3{P zMhLVALQx$wID5!Jw_oO)6FYPvm&We4mXP)ePfINMjz=A|^A&z2snwx&J2q!vdm@Ik zZ4Rn_l|Q3wlh+iAKgx5*H(`P=TGT{kNBQolO(+kas&Nk;`t?!%JY1W%-@^#*dyPMo z+y*L+@M4!3b8K=V_M2|6S7zKV;w}*F08qrJzAWwAcCn8FL3u;GPtlDpVbb0m;_EF+ zkNG=Dd2jMP2sV26O}<5xN*m@i6TN7e;a>^TKM(VV3VUMf+aS6#rr{O3>d@7-y1GMG zi*>a|SF64`9~_ z*>z)I*(jO=+ft+PCwLYt=7&!3Ex0^;g8N|AU`%FE(n&}ftf=PyNwni6Pg05;WIqK@ z6XoD854R&Qpc~T_+6Q7u ziYfmL-wb!L6fdXFKqj<+JI?U6N*|JU&+=8G(zdfapErZXbo(?I=HgkNHFbL|g{wzQ zuXKp2oO8U=QW@EEj_(&BRddhtZcBCK>GQlnfn2-Z4ywjqpq$<}7=-U#VJ zTcAKVrPIB1p|te2KtmDTDBbC=`=#9OrR%+IZx`Cq_TIL@`<-(n*+75q`_KDn$F7fZ3B8Mp(R(6y3(Al{1d$O+~7BLRTO_5Z_D0)mb zrXr2QaieT94J*GR=F0~Q#vGd~hzi!L80j(MR6O*|mf3=Y7qWn)SGk*BMS7L5(%ua& zwPn++azJ+-=~Je4#@)RIV{hEplQiau+t$mL9)mj1SuwR;yjiwHN-Yl2WsZ1^_ zH4Q7*UVdEp#=4XHoJL8kxiOo|#6mfJhxp2?G^}r+#r(xmyPa7=2uK=cg2hZxCZA~ zNrkHfXm=?OHf&OUxxT*rqwzuDEwQ2T8Z@1oW7b;J zd2Mpc;FtQ6MiaC7CB5F9O~+%o4(sZK=anyP7~Em-8*?T}(rf+dJ8jC5jYfe**Bo=I zT{=}PCO7sqq1H3U?6rX$erX|w0T%sI00VW{1yFk(e&eF()U;BWr$ZL=99G;L4=bMi z>y_n(&C1zLZ9ubec8(3!y7Ofuhak$JiimG+ue~GfLw?Dd1y+VvDc98F2jh(kex*Zx zC3^Wa-A-e#U|GSX{gngW~h z+wbq3Rkm&2-Iw#KxR8=wW0EzsiPolEW??BK=kl3k<80n23rvLqxlq&?GcBz^B*gFy zDovF(ve(!&=~oh48xD-AbXlBZ^R?-wyc*Hxfs#F!;p?W9^4QiM<}^C06Uuruj07rx z8uHSZ06boqh)rqVwztb6;LdtGZF$S;%410epwO!UfMV)WygCn5#7r#kqS@G#*Kd2( zRUpXd99yhG7^)1P_e#TpFkua!9gC|333)q}`R(M6>KLss`i9*RuW>BTgiNfUGHF^GQ+~I-;XL{nnPVfhKB8W&kF-}R393%y zCB5GtN@e8M*{nYs4P@l7->+v0uN3u8P2{JSm(yP3M4l~SHIA%;obXmwr(5OjfjKr% z8>5t!+@kLpucX|(x1YNAIOxk5i0^cs8e5EPm`w5sxOe2xvN-43mO)YM*S;#8Xq&9TYa z$O~S{DuC_Jt3Y=cCsnLI*syt1e|{>5`5XK5%3rUrK|!3^={jy#yXc=|a=5AryS-8y z^LwSiKrU*|1d`!Y0@RU}hju#Zy1gxavntIhL$_BUF>cW-*~K##mb_l0 zeokJ<>Xi@gJbb<}7uJSXpHk7gRwnvmLZ-+r7E?Qng=>0fsVX+}Nzo+dVu9M2KFn2M zw^YHlTU$KLsxcIEX0;`42LT5KP)@JZC7yP#% zS#vfALDy-V%}Lb)2vGegCFNpcm)FEnVQDsJo{@8`D=U6M9W{$q@Yfp; zYmFhZG^U%)0T@8RvSAiVb_A67)f>+bdKqBL$r(o~W9jo&DH2vGl60|rjUsauO2otJ zl4h=oQ1w)n=Wt~`gu+r@sGnJ{6bh>o?^S=vNmx%Inaz78O#>V8PzLwzA$hRhE+ut# zopR&eg2g4|mOdFs$a*N1c(_)A$Y3F<7q9U&XH$9f28>sKO7n_&U-Q;EuW2dUnVXWQ zrKH891ow52xblvDzVox-%4jTWs(m?JsaUBZC=wQI7;~|3ZPEs9(jDPdt~FG}$(*{p zGA@>`H6P4Mkuc`om(@g9G%QsmwDOycn_&+eCTVrH4>lay5)B&%vsgH$<>jdI{f5(G z;iX(GQR~iDS*Rg77H5u1AreoeG93x@azGi~zw3;{Yq5DvSaDU_MO4~lU2LY-(IN!7 zSQKNGJ`%BH$Bf#;r}tl0H|8}iDo^ZhJRMXK5OA?V?aR^1mlM@510^<6{f%A<>TKE$ zY#JREtG>$6$!ps>CqStdnYEcLBZ8z5_!UO2J=OGYkAE+Ou6cnT?& zEK0eeIh0Dm+%W33DeIX&ok`_VLa*pyd@DB{-lq&4ZfKB;!U`$Y=I0UfbBnH(_QMSq zzqwwy=kWSYr;7Eci&<;4juoXjFodcO6<^IMaB%pk~u}K)j2^SlzbsR3L&J2qv8=6`UrHfP1BB(H3<2p&2DRwrs zS(1{JP==ZswuD9BmZm0og+-NO)9Le(BGa4oCb$>QR8h{@16kNtD=ZBNW9D!m7l7}< z5^Bk1_4SQ*OL~`{&8QU~w{ybL=X6SXkG^AY6*snWV zbJZX&7NuTgNWcFs-+EHK6gD)F1H&qb7hKF!Yvn7d9vAHUw;W}XPoNpDl{J$IEa+>) zs-Jbc*lg{ylE!fzv#Z!EDY|CkIY8leF-NVTyQoP}Lsse)NSO~y?xGp|ACj|KW(Z63 z;pXP~u(=>-vhX~!%odgms4}4H8kWg1Po~2b?lfj{l1+I{^RbPFY;&_H8I*E!D={d) zY(7pL%JyS>4K@`!UKbmyjlLL`h6PEi8ozanDb8ap#Hy5zO`Tc9D2w51Ps32Fpm#!@ zXVJw*YaKX?l1!~%gSLWG;r6NWg32RGdu&CKu17Woz)>o7! z1RhE;sjFzz7w59D3EVNsUNn0b62VlQ&4D7tPIt`Wjx{&CW9DKk7ft1JURApb;8R;YE0+Rjo8T1j$?e=XYYIi=NfQ0iAF zT5_?W8vL%J<`#|vV*)-8m|1u%!w@BaGnnAt527WdekrUneV6lzrMd$oZtn7f~~gY3@>7`!{ZueP^XB+rdcvMdg=m?Ifqvw|A=X6Bv)R zj^t&GvHiF^>x1G7_-cwPqCzwb1FZI8+^2cOAwVKr(!5Xeh{HZcry8GwsG5dGu*gm9dBr#H6rdI=P>Ol>p$XCRbWSSwV#M`@ubNE zjP}ApsWpsN22T5=NCbc+BATX7_%wfG#wVpkeZi*&F<8*2`6DwCNq<()3d*KaO?APD z6jV-}Iz$&D!p&$eL|S^XEi;jpTnm2cPw2Jc3R}P^)u39=w3IU!GqId(Tu|O{>g?|B zH7_;qBqtS=|2lOonNbX<2jTr?P9NJdlx4k{)n3pEf*C`~1E1Xk;)qA$hEe1n8I>g&dH6vnW=&7^i(1Oc~H}}y&&UCN5VH1j7&>SZ5`c; z?aFQvRbG4LfeBFswHuQ}BZMNP%98GkS<*gZOoUM?Jm^&^GVfyk8lwF^O@erR(!BV* zSfPA>R`M&)U3qMGe|B0@L!`~kMIY>u$t>&7DmPj7Zt?nzB6KR`vR^Q0$h0(>okDvd z&YIe)gU+c2vH|v(I%si~^fiyPq{3x$F<%WXpHB;<`c|7a`FuwHX|rw*|D;2=MfvMh zLt(Iu1147OtCCNX=Wd@SnyeMJaAKB%UEC4L>ND#5y8WJEx6dscJ)flct*cV8!@4@A z)7L2i)ym^n@43S56EhIDf!kiIF z4giEfpJtErRY0Aq5WwZr!VR#A<^Ur2FB8b6G6KYi)YQ&AKE--=uky=l+UuMVqf==( zb8Me@)26wbT@fh?(hEqIm%Eh7Gbh`-A`s`O6agAzlgo$t2qb({pAWSx7r^hq%1`tz z!lR!$bM>G-Qk{uG^|;1h$JFpUtZ@g-s@V$oy%q5LB2q8FuEvplff)$ZIk3ecGOOHR z*|oV(j6E!n*QcDf7&d!UnvcR3Qt@={yidviKjyy5#1TW)loT^mSkvay;*AcUWDu;n z2w@^Dx-o&7eF)rJEe-t6J!GA7rlV=t;4{wq*iuq1R`B<(x=UEl12^Sl#&3V+P1rmoFJs9d#w)TpVHQ=oH42Y#k@8K z`Kd;lm?IE#k`=VOy{X<+`&CWCYmQyBVlVu`COimU@&M&z>eW<MGE1Fsnj$BkK2?d zJFg`3%Es%iIzJyV7EDc&6bOL34UtX*%9ymtQV9SSrqErJq^}BeeRH!-G;zk*L*Bsnt8%?bS9ETSS9NtBIYtTccUQS4`TDBrkl|88{@ z2}=yU$3^cjavaJF*X`#rO^odpMbix6&3F5g2`yhEH8(J zZKzhnO;{&GKJ*!73scc)#0%rtE*el0)&s!rE!G2qk9uGgs(cig^l8!eP(bnuJ{qX- zLr+8t49O)auJRLTs5%Ud)fJ{^xsucqF=r7iORB$Wu_@zt1UBTV7?c&0?NCFmq{ejE zl0da(JOUY#!6%kUpAxVgBT40TwkNg@M9kLAjJjQsl?D{Q{q&|>REWfJ*pkY{(LDqG z5zWYml{EJ<98ir5mMLleaH^#3FJu9^Sl)w zYjP!*mt!SkmH0+AM&A!Axst}Eprw5Uy%;AWN^e&)#UtJIYm!wayAK`6lpxeXQVNfb z)Y)uDZSyfN1(Y{*duV?|`Oof?Lzqavi)Er!qc~L3^k=>#g-S1xe=HV-@a>32r}Cv~ zNx!J?$gF}|iOR*4m}9@#l$(T^S?e`ik`{%C8_Q@rZHm!x5TUHkI!=;=@)rl&l3ML3 zthDwFHzi6&xq=>{rJ^O1@DQ`=rk=htX-O;h^td(!R7%Jm#63ZY12dIj3MDB59_h%g z_Bx{+?>%lPXcRZK=%;IbW>i&hNe_#w;Kr3w?`;Elwd0tFg=%x~m( zC{y|tZ%K57jr!~LEu$InfBkW2JD=k2>+11iI;L8DE7#nPB?!;NoRQP< zKu9(gOH8lFa?LfLe90SMHkaRLd|rPv3)=$u(4)>0@HmaREUB5G`EM*s+$HI-6Z&Gws7$rksph1!_I zB~_(#EJT%0-%+o`ojb^|a-;K*$**E8lwzJw|?dV<|wQ07bNS8M#Pdl#?%OdY# z-dgkCl4hsRmo$g90Ieh(RRhQlt%tQ{D`_sb11&)UmQG4GETDv(3xEq2mB`?Ah#TBD zc-XX9VnyutbOmw&3rt1?0@xTBwq~#+)+u)4n&y>14Bi3deBL!pCrZNNzsymBpRN4O zb?p2|N%F3OzBJrDG}1TR-DQC#5D8>+1M-4ptR#Z-VrxkqYP7^sNk>MO7iG&tX{DpL zG?h-OhOK6C`BWr@J*-%p^*}`!^prH6JYJFpFehlWgH>a0s06i*u+18Cvlvx88xACp ziBK`z!O=Y>NKrI{F`rvr9x4gW6TfTZbgQFBJgih3yYi+osTlj`br)Qt?1&;yJ|2Lk4 zV*4)bVO_OGF|`q5o^Ht}sGM?Zv4X5yizNiyl3Uc<(ZBjsdWX!kOJm5!u?-3z@<2lW zYUtEvdsM^|#72)@X&!DOF{O9dfym_@!#!7I+{UoUv?N@sIHCy&1WSK4+`iWytL_y? zs$mfA`*!aLu`93fny*^ZWTmn_q&A6(l~kR*UtK#14;xe`HmHF|eg12PRlLl2n5Q=7 zcm?f!Q7Qf+w6nP=4EYY>7`l`<`+V&1@1UvyeE@}Kve+~A6$ro$tK z+N}(ZY$9{Y_{b5YuPl#D9GzE(EqGXOZP<`oTWPaV)qd>gt>SR~W|peXepWd$dIIjb zcl5~q*(gk5*rqkx*P(VA^e~%H4#B)zGf>0sN^CHy21;4Ptr?9<)YepoSIh5dZcZ!V$@gOO zYva^G#C4BNHE-%s=eyux17f}i_#~(HpI@jjY^gGf?#itEm06BO)qoNkjcNjIBC45L zUbi$6RZXd)`m1J2F&}!2nj_fTV5Qp6KCxB8+-@*y&zi77PWkP|jmnO5d)JLbA?8Mu z6X&j~^SO;V<=pg$B1&*xzCZ3GCDnmM2`lWu>ovx zE1R!Bh{(0+dIKpcuIrB>SW&p%f~h`qeHxNd?=Nf{jl$Fno3ULCZin2x&;Qj;a#|Q{ z-5xe6Ff%wF)i}WFmSzNnofXR4!E%DKLs6+mJjb;>8#a_tabm9SL3X*d-Q_{IgyfQ+ z+;HUZc$D>Ls@7aA+g-}Z$!shbmswYg^$XQ^Q0WX@6Yg_MldDqOj^$L@`PZWr#x-?x zx#7j)KVw%+8j6YyP&?w&xlBF;=h=uxt6vC@&-o&@VxFYbr~DvrWVbUQd6Me(sa^dg zY+|djGicb_pMf0I;y$u8q;v;gA*x`URC2F|l&6B{UtVRQolfN)p=N9je<9Sm_C4Ud zD|}jcduXd-3-5;*x;|`fat4?^P>IsSRqT5`ERe2RnVGaQ6tCZyN=t1g+L+6&%*S`` z@VH@^oXfT><3GcR8D!A?Fk zSouf1iQ3%Cp~RVu4lGkQVzF-JhQxukMaXA05o%Rmu`#!_=&ogqu~D~{-;lsw<%F^! z(nuX{BBQ7{QJ9P{{g$?Yt6GR{2OL2 zNp7`Qg;k<+LU~~3Aezmm4z0JJm9YP8SKgR9tn7&X47G1cH{#!qrSHHxxHo1e8Rgfp zA&lBFTcka1<<9vQ0&bgaZ0x}Tf>Sl-u4bD^lFPkPH6R+ZO5@zIt>dCmRb8Z%k-3}B zd)&gvRHaK&n#GjmYz~d8@WIvStyOl;<9l;99)odu5^AdRq~#iuWq9>{Ds5@Wtpw6F zUuD2up?5^3chSSbHF^)ZC4INzi|^VP(n#K~l6-vfB_x-v!ZvMfnQkkAz-I!j5sk(< zQNM->l4^Mk6U3~mOpvkGm;jj&2NRYJS*w(>!UI?QiGytc>&sanZj}PoRTc?t;L;mYgsh?e zQzW9?G0$k!s{C~JaAU-(Qaf&4rFQ=sYUfpIM@6G5wL?mK=BD$LYpI>X>|RFgWUaC@ zhVNfSZF%*5NTqgomD*uzh1!0V+CJFUHEO4=6>47{O^c+fcq$yoM*YZLiTd+U6wn=& z+$%JkN~!Cy(NVE~;Y-aZOWDH>1<-iv+_~!w=Ho4$M$^=}>7|wBX~>13@^H3Mx3GrF z-71ySX=wpe?go_)Z0@Kn2fuP5*Md#Y59O}kRkXg;T7`dhIKO*uBK>lv=nY6|#hKqr zXCSR^-l;6)her!($+w14<^xh9Es}E9BuTQ8Ra90Zhslqf(8X4yUrke9tP?`!8 zO;)Q^w5r*sNON&Q{iluTG}9w34F1Dh459zG7M8&#dyB^jJf@WZ1I%vim|3$=X4XRUQrAnWp>3o=<)PBf-F+{4 z1N|Y*Dc>v2?RHragb=APX1`zTc>DcGU{Ibe9#NiI*sQ!};Yv7!pIT@To>y@%>dc6j z9$sWf!F4X);B#3!hW`a1o|jY$K!#sZ2P{joFR2q?_1?8Khge#C=~$B!Lr<1^MCJ0bS3El1R!h)Y z70I%;YDbiFD<@#z+_qx58f+obA1m70k8e<_w#Rr$?15UeJ^^1BjbjEC zf+fv0Xlj~CH#g6uMc^*C+ImE}c;f*Wl^?#*3hVWm8=VN%NasJ$YzUa`*mQ*2DgepJ zm1+1LmX+Yc2+r27n z3{_jgrb-*nFf-JoO{Pui6xh6%aNRAKCOl!GO?McR#=TfEUNGf4>Ly%o_L!U z;|jH@R%VA|wYzwmG1Mk350Qo-;#rlS`id+a5xuQ5&JVMRwAdFu+TEt5(oC%OQDtVV zLT%TrTY2&oynbAK+8?MS1P!D$U!_O6@Jd5-f51HA@{V{s?qOedmw!SUNUx13YTfiG zUwP%#N72+a>>lWL`R&$W>=gd%md9Ro_E^6|HhYV6Vs_W^a>x%I=%rvnQF5a)}qC2k`^t>o=PZ zcA*n&KIQOV61(};eA7%q%BSE<4l4KEVvb}I zD{M)CYr(H-x=04!AYFQx#S_Ase$m;BWE|fLa;6fRPumCFpg)#PX#5aJXd#rjwn`Re z8+g9s)+Qu5K6Xa~5-2xp3M3$f7>;>lmDk-m0K@00TSs)RHsQ$cRIa=29%!1M-Zl-x zs`K^xuR#7Uatl)|Kh-{MT8T9`&nfZO9~AT(8D=4se%n1*2k^4YS`-g4%*XE7tDN7y zah=>^Om=#dAH9CR*n1inW_fi+0{-F38k*JM$A^U|0k&U*AV;+^rD@^=X-O<=E(k7iaXE06~nvdNuy?idb z)Xq+>m`==eL@@GM7~#*|vG?-DHnI1WmnPtN!P&g?$7D<)7YlVkjI1nOJg_g~?8wLA zG-tFtVJYfVsS$E24_@50H}90>q=;;e4ENbniF7I{jzEN+$`3Dg(1=s{7Mv=R#G}65D(gmfj zj;5W;SNSP%`e!(SB!cViwJJStijd(;AAZvgov5Chg*k=lOY7gZVIBB&`@8248zdRo zEX7zDd6FFlMDdzLw7Q_xAOq^2ci-P=XNB7EtGqd@lE5{~y3yyZOEr9YqA*OREJ zZ-lO@;=R%1R9^VA4IZEESsQgZm7AYEjKce#y+8qrh<2X+%OebVCTkM)5n|Yb^$jzv+x!W7JDBXX%d0k#K9aO&cx7}xkozjRP!>m*4 z7th#?B+ua4>y(n>Iq#Hm(%GE0UB8NFgY(ki|M?E3Hs_`P`TK_`&CKwdzNXu!JpSCP z>9AAjd0wiY6%(+mu{}~Vs956PxL4PpeDwJS$eC|GFQm|c7rLp#sf1qW*%(lpOZiKI7pU1vyL3xy*dhemyyfh9m1qGiJ(H){{vTzq_8q_EiBH$;4sq!F;JK{6RjsfgGT{PF~tT8qxaA z8;G}2w1yr+%eA>Oiz?-9G3Mu6Hj@3+7UQ2eNp^1a$6<$PKA67K&-*u$-mSLSnmQZ5 zXCrAQw(^%Yl93(6&Yw4u+wpk4iR>S-vo7X>QKgx4UCqrtqkUD^vM%g$s�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 OqzG@|zz6*4$^Q!>YpLP@ diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index acb54704c78a97a0ed331c4e159d3ac3ff206b2e..ee27fd56b061756cf85435f95eeee535f5c11d25 100644 GIT binary patch delta 8848 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 delta 6307 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 E0GZ3#@Bjb+ diff --git a/netbox/project-static/dist/status.js b/netbox/project-static/dist/status.js index a2d02a7995289acc67ebd34f2137d717f2d5945c..aef5eccf18313187d71d310f43b2853ffe05148e 100644 GIT binary patch delta 2580 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 S?Xkbv{88&g3; - -/** - * Map of string keys to primitive values. Used to track variables within URLs from the server. For - * example, `/api/$key/thing`. `PathFilter` tracks `$key` as `{ key: '' }` in the map, and when the - * value is later known, the value is set — `{ key: 'value' }`, and the URL is transformed to - * `/api/value/thing`. - */ -type PathFilter = Map; - -/** - * Merge or replace incoming options with current options. - */ -type ApplyMethod = 'merge' | 'replace'; - -/** - * Trigger for which the select instance should fetch its data from the NetBox API. - */ -export type Trigger = - /** - * Load data when the select element is opened. - */ - | 'open' - /** - * Load data when the element is loaded. - */ - | 'load' - /** - * Load data when a parent element is uncollapsed. - */ - | 'collapse'; - -// Various one-off patterns to replace in query param keys. -const REPLACE_PATTERNS = [ - // Don't query `termination_a_device=1`, but rather `device=1`. - [new RegExp(/termination_(a|b)_(.+)/g), '$2'], - // A tenant's group relationship field is `group`, but the field name is `tenant_group`. - [new RegExp(/tenant_(group)/g), '$1'], -] as [RegExp, string][]; +import type { Trigger, PathFilter, ApplyMethod, QueryFilter } from './types'; // Empty placeholder option. const PLACEHOLDER = { @@ -81,7 +35,7 @@ const DISABLED_ATTRIBUTES = ['occupied'] as string[]; * Manage a single API-backed select element's state. Each API select element is likely controlled * or dynamically updated by one or more other API select (or static select) elements' values. */ -class APISelect { +export class APISelect { /** * Base `