From dc6fcf7d10394dc37ea76342e505cc1ac1046abf Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 26 Aug 2024 16:29:52 -0400 Subject: [PATCH] Closes #17256: Fix translation support in VLAN group scope assignment form --- netbox/ipam/forms/model_forms.py | 118 ++++---------- netbox/project-static/dist/netbox.js | Bin 391545 -> 389668 bytes netbox/project-static/dist/netbox.js.map | Bin 528502 -> 526416 bytes netbox/project-static/src/forms/index.ts | 3 +- .../project-static/src/forms/scopeSelector.ts | 153 ------------------ 5 files changed, 32 insertions(+), 242 deletions(-) delete mode 100644 netbox/project-static/src/forms/scopeSelector.ts diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py index 4e405a035..ebd1d4350 100644 --- a/netbox/ipam/forms/model_forms.py +++ b/netbox/ipam/forms/model_forms.py @@ -1,9 +1,9 @@ from django import forms from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ValidationError +from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.utils.translation import gettext_lazy as _ -from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup +from dcim.models import Device, Interface, Site from ipam.choices import * from ipam.constants import * from ipam.formfields import IPNetworkFormField @@ -17,8 +17,9 @@ from utilities.forms.fields import ( SlugField, ) from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups -from utilities.forms.widgets import DatePicker -from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface +from utilities.forms.utils import get_field_value +from utilities.forms.widgets import DatePicker, HTMXSelect +from virtualization.models import VirtualMachine, VMInterface __all__ = ( 'AggregateForm', @@ -562,91 +563,30 @@ class FHRPGroupAssignmentForm(forms.ModelForm): class VLANGroupForm(NetBoxModelForm): - scope_type = ContentTypeChoiceField( - label=_('Scope type'), - queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), - required=False - ) - region = DynamicModelChoiceField( - label=_('Region'), - queryset=Region.objects.all(), - required=False, - initial_params={ - 'sites': '$site' - } - ) - sitegroup = DynamicModelChoiceField( - queryset=SiteGroup.objects.all(), - required=False, - initial_params={ - 'sites': '$site' - }, - label=_('Site group') - ) - site = DynamicModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - required=False, - initial_params={ - 'locations': '$location' - }, - query_params={ - 'region_id': '$region', - 'group_id': '$sitegroup', - } - ) - location = DynamicModelChoiceField( - label=_('Location'), - queryset=Location.objects.all(), - required=False, - initial_params={ - 'racks': '$rack' - }, - query_params={ - 'site_id': '$site', - } - ) - rack = DynamicModelChoiceField( - label=_('Rack'), - queryset=Rack.objects.all(), - required=False, - query_params={ - 'site_id': '$site', - 'location_id': '$location', - } - ) - clustergroup = DynamicModelChoiceField( - queryset=ClusterGroup.objects.all(), - required=False, - initial_params={ - 'clusters': '$cluster' - }, - label=_('Cluster group') - ) - cluster = DynamicModelChoiceField( - label=_('Cluster'), - queryset=Cluster.objects.all(), - required=False, - query_params={ - 'group_id': '$clustergroup', - } - ) slug = SlugField() + scope_type = ContentTypeChoiceField( + queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), + widget=HTMXSelect(), + required=False, + label=_('Scope type') + ) + scope = DynamicModelChoiceField( + label=_('Scope'), + queryset=Site.objects.none(), # Initial queryset + required=False, + selector=True + ) fieldsets = ( FieldSet('name', 'slug', 'description', 'tags', name=_('VLAN Group')), FieldSet('min_vid', 'max_vid', name=_('Child VLANs')), - FieldSet( - 'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster', - name=_('Scope') - ), + FieldSet('scope_type', 'scope', name=_('Scope')), ) class Meta: model = VLANGroup fields = [ - 'name', 'slug', 'description', 'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', - 'clustergroup', 'cluster', 'min_vid', 'max_vid', 'tags', + 'name', 'slug', 'description', 'min_vid', 'max_vid', 'scope_type', 'scope', 'tags', ] def __init__(self, *args, **kwargs): @@ -654,21 +594,25 @@ class VLANGroupForm(NetBoxModelForm): initial = kwargs.get('initial', {}) if instance is not None and instance.scope: - initial[instance.scope_type.model] = instance.scope - + initial['scope'] = instance.scope kwargs['initial'] = initial super().__init__(*args, **kwargs) + if scope_type_id := get_field_value(self, 'scope_type'): + try: + scope_type = ContentType.objects.get(pk=scope_type_id) + model = scope_type.model_class() + self.fields['scope'].queryset = model.objects.all() + self.fields['scope'].widget.attrs['selector'] = model._meta.label_lower + except ObjectDoesNotExist: + pass + def clean(self): super().clean() - # Assign scope based on scope_type - if self.cleaned_data.get('scope_type'): - scope_field = self.cleaned_data['scope_type'].model - self.instance.scope = self.cleaned_data.get(scope_field) - else: - self.instance.scope_id = None + # Assign the selected scope (if any) + self.instance.scope = self.cleaned_data.get('scope') class VLANForm(TenancyForm, NetBoxModelForm): diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index e9e9da59d2fc2bdc701a3e72478e85d3dfe6b7c6..0b29c22137d9e46583621b6a23121ac5d5bfd7a0 100644 GIT binary patch delta 14407 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 E4>_OClK=n! delta 16143 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 delta 2158 zcma)8&u<%55LUsh;T-5GDN&`W2Uao^5am*7_W5P&Y#hh69pgv{ZS1wZ>Be>)J9TpL zfkUs{e1-pj3-X0KSN;R;9JnAMBrbg4?AqN#D(PXz@5jtH-^`nN&%b@Y{r3;sKNU7_ zpS6dh@Vkx8R~wtR@V&F#*nIbwf98J0sfpA)#}m`}no?SnWygrwIdXi#ydvfhLMkn% zB+_(RVs~}!M6O8W9yu196xL~oIWe^82ymq8lts!;RiuHbow-+6eJoeRo474{YSQlb z=q>EjtkgGP*)vH9!Q#oi+}-7$ALMfH&D%nzs+fRgsJ@Q> z8sNnI51_`iqIzi))Sgxt{d8|KRaSaba~#Mxo7SXGiSlWhSX88@bll%(%(LHB3D(@>%odGB>b+g zd+6IV5q=VlrTNE3Dc1Hl`JB;M^d{+*xl(WK^QX#?s_BiR<(ghmsD7;z9P6d6P&L$B zr`2GzB?t?@xFvXB2;zW7Wii~(eK_x`c0j$BZerx2HlR_`kQ$nER&OSEU%HxI%k0)v zt%BT`OZS+DQPwJt($8EkXD0`gb6FNw{S#L3(xnA?v40vwf>J_YG%xE`xBU+1p zH**gjA;?p}131##U}m+Pedt^CoheEZ1G7eK6EEVe+()lYwsQDxHh# vGQ&YP>a909=tg1OIa`l7hz8L_F>B$SIBZXb