diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 913820a14..2fab7a735 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1885,6 +1885,27 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): change_form_template = "django/admin/domain_request_change_form.html" + # While the organization feature is under development, we can gate some fields + # from analysts for now. Remove this array and the get_fieldset overrides once this is done. + # Not my code initially, credit to Nicolle. This was once removed and like a phoenix it has been reborn. + superuser_only_fields = [ + "requested_suborganization", + "suborganization_city", + "suborganization_state_territory", + ] + def get_fieldsets(self, request, obj=None): + fieldsets = super().get_fieldsets(request, obj) + + # Create a modified version of fieldsets to exclude certain fields + if not request.user.has_perm("registrar.full_access_permission"): + modified_fieldsets = [] + for name, data in fieldsets: + fields = data.get("fields", []) + fields = tuple(field for field in fields if field not in self.superuser_only_fields) + modified_fieldsets.append((name, {**data, "fields": fields})) + return modified_fieldsets + return fieldsets + # Trigger action when a fieldset is changed def save_model(self, request, obj, form, change): """Custom save_model definition that handles edge cases""" @@ -2297,6 +2318,15 @@ class DomainInformationInline(admin.StackedInline): analyst_readonly_fields = copy.deepcopy(DomainInformationAdmin.analyst_readonly_fields) autocomplete_fields = copy.deepcopy(DomainInformationAdmin.autocomplete_fields) + # While the organization feature is under development, we can gate some fields + # from analysts for now. Remove this array and the get_fieldset overrides once this is done. + # Not my code initially, credit to Nicolle. This was once removed and like a phoenix it has been reborn. + superuser_only_fields = [ + "requested_suborganization", + "suborganization_city", + "suborganization_state_territory", + ] + def get_domain_managers(self, obj): user_domain_roles = UserDomainRole.objects.filter(domain=obj.domain) user_ids = user_domain_roles.values_list("user_id", flat=True) @@ -2397,6 +2427,14 @@ class DomainInformationInline(admin.StackedInline): # for permission-based field visibility. modified_fieldsets = copy.deepcopy(DomainInformationAdmin.get_fieldsets(self, request, obj=None)) + # Create a modified version of fieldsets to exclude certain fields + if not request.user.has_perm("registrar.full_access_permission"): + for name, data in modified_fieldsets: + fields = data.get("fields", []) + fields = tuple(field for field in fields if field not in self.superuser_only_fields) + modified_fieldsets.append((name, {**data, "fields": fields})) + return modified_fieldsets + # Modify fieldset sections in place for index, (title, options) in enumerate(modified_fieldsets): if title is None: diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js index fd50fbb0c..9c770f40a 100644 --- a/src/registrar/assets/js/get-gov-admin.js +++ b/src/registrar/assets/js/get-gov-admin.js @@ -47,10 +47,49 @@ function addOrRemoveSessionBoolean(name, add){ // <<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>> // Event handlers. +/** Helper function that handles business logic for the suborganization field. + * Can be used anywhere the suborganization dropdown exists +*/ +function handleSuborganizationFields( + portfolioDropdownSelector="#id_portfolio", + suborgDropdownSelector="#id_sub_organization", + requestedSuborgFieldSelector=".field-requested_suborganization", + suborgCitySelector=".field-suborganization_city", + suborgStateTerritorySelector=".field-suborganization_state_territory" +) { + // These dropdown arecselect2 fields so they must be interacted with via jquery + const portfolioDropdown = django.jQuery(portfolioDropdownSelector) + const suborganizationDropdown = django.jQuery(suborgDropdownSelector) + const requestedSuborgField = document.querySelector(requestedSuborgFieldSelector); + const suborgCity = document.querySelector(suborgCitySelector); + const suborgStateTerritory = document.querySelector(suborgStateTerritorySelector); + if (!suborganizationDropdown || !requestedSuborgField || !suborgCity || !suborgStateTerritory) { + console.error("Requested suborg fields not found."); + return; + } + + function toggleSuborganizationFields() { + if (portfolioDropdown.val() && !suborganizationDropdown.val()) { + showElement(requestedSuborgField); + showElement(suborgCity); + showElement(suborgStateTerritory); + }else { + hideElement(requestedSuborgField); + hideElement(suborgCity); + hideElement(suborgStateTerritory); + } + } + + // Run the function once on page startup, then attach an event listener + toggleSuborganizationFields(); + suborganizationDropdown.on("change", toggleSuborganizationFields); + portfolioDropdown.on("change", toggleSuborganizationFields); +} // <<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>> // Initialization code. + /** An IIFE for pages in DjangoAdmin that use modals. * Dja strips out form elements, and modals generate their content outside * of the current form scope, so we need to "inject" these inputs. @@ -1170,3 +1209,28 @@ document.addEventListener('DOMContentLoaded', function() { }; } })(); + +/** An IIFE for dynamic DomainRequest fields +*/ +(function dynamicDomainRequestFields(){ + const domainRequestPage = document.getElementById("domainrequest_form"); + if (domainRequestPage) { + handleSuborganizationFields(); + } +})(); + + +/** An IIFE for dynamic DomainInformation fields +*/ +(function dynamicDomainInformationFields(){ + const domainInformationPage = document.getElementById("domaininformation_form"); + // DomainInformation is embedded inside domain so this should fire there too + const domainPage = document.getElementById("domain_form"); + if (domainInformationPage) { + handleSuborganizationFields(); + } + + if (domainPage) { + handleSuborganizationFields(portfolioDropdownSelector="#id_domain_info-0-portfolio", suborgDropdownSelector="#id_domain_info-0-sub_organization"); + } +})(); diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py index c7b962f60..4aea46efe 100644 --- a/src/registrar/forms/domain_request_wizard.py +++ b/src/registrar/forms/domain_request_wizard.py @@ -75,7 +75,6 @@ class RequestingEntityForm(RegistrarForm): def clean_sub_organization(self): sub_organization = self.cleaned_data.get("sub_organization") is_custom = self.cleaned_data.get("is_custom_suborganization") - print(f"in clean: {sub_organization}") if is_custom: # If it's a custom suborganization, return None (equivalent to selecting nothing) return None