Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2867: Domain information admin changes for portfolio fields - [DK] #3215

Merged
merged 13 commits into from
Dec 16, 2024
Merged
221 changes: 217 additions & 4 deletions src/registrar/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ class Meta:
fields = "__all__"
widgets = {
"other_contacts": NoAutocompleteFilteredSelectMultiple("other_contacts", False),
"portfolio": AutocompleteSelectWithPlaceholder(
DomainInformation._meta.get_field("portfolio"), admin.site, attrs={"data-placeholder": "---------"}
),
"sub_organization": AutocompleteSelectWithPlaceholder(
DomainInformation._meta.get_field("sub_organization"),
admin.site,
attrs={"data-placeholder": "---------", "ajax-url": "get-suborganization-list-json"},
),
}


Expand All @@ -231,6 +239,14 @@ class Meta:
fields = "__all__"
widgets = {
"other_contacts": NoAutocompleteFilteredSelectMultiple("other_contacts", False),
"portfolio": AutocompleteSelectWithPlaceholder(
DomainInformation._meta.get_field("portfolio"), admin.site, attrs={"data-placeholder": "---------"}
),
"sub_organization": AutocompleteSelectWithPlaceholder(
DomainInformation._meta.get_field("sub_organization"),
admin.site,
attrs={"data-placeholder": "---------", "ajax-url": "get-suborganization-list-json"},
),
}


Expand Down Expand Up @@ -1523,6 +1539,70 @@ def converted_generic_org_type(self, obj):

orderable_fk_fields = [("domain", "name")]

# Define methods to display fields from the related portfolio
def portfolio_senior_official(self, obj) -> Optional[SeniorOfficial]:
return obj.portfolio.senior_official if obj.portfolio and obj.portfolio.senior_official else None

portfolio_senior_official.short_description = "Senior official" # type: ignore

def portfolio_organization_type(self, obj):
return (
DomainRequest.OrganizationChoices.get_org_label(obj.portfolio.organization_type)
if obj.portfolio and obj.portfolio.organization_type
else "-"
)

portfolio_organization_type.short_description = "Organization type" # type: ignore

def portfolio_federal_type(self, obj):
return (
BranchChoices.get_branch_label(obj.portfolio.federal_type)
if obj.portfolio and obj.portfolio.federal_type
else "-"
)

portfolio_federal_type.short_description = "Federal type" # type: ignore

def portfolio_organization_name(self, obj):
return obj.portfolio.organization_name if obj.portfolio else ""

portfolio_organization_name.short_description = "Organization name" # type: ignore

def portfolio_federal_agency(self, obj):
return obj.portfolio.federal_agency if obj.portfolio else ""

portfolio_federal_agency.short_description = "Federal agency" # type: ignore

def portfolio_state_territory(self, obj):
return obj.portfolio.state_territory if obj.portfolio else ""

portfolio_state_territory.short_description = "State, territory, or military post" # type: ignore

def portfolio_address_line1(self, obj):
return obj.portfolio.address_line1 if obj.portfolio else ""

portfolio_address_line1.short_description = "Address line 1" # type: ignore

def portfolio_address_line2(self, obj):
return obj.portfolio.address_line2 if obj.portfolio else ""

portfolio_address_line2.short_description = "Address line 2" # type: ignore

def portfolio_city(self, obj):
return obj.portfolio.city if obj.portfolio else ""

portfolio_city.short_description = "City" # type: ignore

def portfolio_zipcode(self, obj):
return obj.portfolio.zipcode if obj.portfolio else ""

portfolio_zipcode.short_description = "Zip code" # type: ignore

def portfolio_urbanization(self, obj):
return obj.portfolio.urbanization if obj.portfolio else ""

portfolio_urbanization.short_description = "Urbanization" # type: ignore

# Filters
list_filter = [GenericOrgFilter]

Expand All @@ -1535,18 +1615,38 @@ def converted_generic_org_type(self, obj):
fieldsets = [
(
None,
{
"fields": [
"domain_request",
"notes",
]
},
),
(
"Requested by",
{
"fields": [
"portfolio",
"sub_organization",
"creator",
"domain_request",
"notes",
]
},
),
(".gov domain", {"fields": ["domain"]}),
("Contacts", {"fields": ["senior_official", "other_contacts", "no_other_contacts_rationale"]}),
(
"Contacts",
{
"fields": [
"senior_official",
"portfolio_senior_official",
"other_contacts",
"no_other_contacts_rationale",
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email",
]
},
),
("Background info", {"fields": ["anything_else"]}),
(
"Type of organization",
Expand Down Expand Up @@ -1595,10 +1695,58 @@ def converted_generic_org_type(self, obj):
],
},
),
# the below three sections are for portfolio fields
(
"Type of organization",
{
"fields": [
"portfolio_organization_type",
"portfolio_federal_type",
]
},
),
(
"Organization name and mailing address",
{
"fields": [
"portfolio_organization_name",
"portfolio_federal_agency",
]
},
),
(
"Show details",
{
"classes": ["collapse--dgfieldset"],
"description": "Extends organization name and mailing address",
"fields": [
"portfolio_state_territory",
"portfolio_address_line1",
"portfolio_address_line2",
"portfolio_city",
"portfolio_zipcode",
"portfolio_urbanization",
],
},
),
]

# Readonly fields for analysts and superusers
readonly_fields = ("other_contacts", "is_election_board")
readonly_fields = (
"portfolio_senior_official",
"portfolio_organization_type",
"portfolio_federal_type",
"portfolio_organization_name",
"portfolio_federal_agency",
"portfolio_state_territory",
"portfolio_address_line1",
"portfolio_address_line2",
"portfolio_city",
"portfolio_zipcode",
"portfolio_urbanization",
"other_contacts",
"is_election_board",
)

# Read only that we'll leverage for CISA Analysts
analyst_readonly_fields = [
Expand Down Expand Up @@ -2575,7 +2723,72 @@ class DomainInformationInline(admin.StackedInline):
template = "django/admin/includes/domain_info_inline_stacked.html"
model = models.DomainInformation

# Define methods to display fields from the related portfolio
def portfolio_senior_official(self, obj) -> Optional[SeniorOfficial]:
return obj.portfolio.senior_official if obj.portfolio and obj.portfolio.senior_official else None

portfolio_senior_official.short_description = "Senior official" # type: ignore

def portfolio_organization_type(self, obj):
return (
DomainRequest.OrganizationChoices.get_org_label(obj.portfolio.organization_type)
if obj.portfolio and obj.portfolio.organization_type
else "-"
)

portfolio_organization_type.short_description = "Organization type" # type: ignore

def portfolio_federal_type(self, obj):
return (
BranchChoices.get_branch_label(obj.portfolio.federal_type)
if obj.portfolio and obj.portfolio.federal_type
else "-"
)

portfolio_federal_type.short_description = "Federal type" # type: ignore

def portfolio_organization_name(self, obj):
return obj.portfolio.organization_name if obj.portfolio else ""

portfolio_organization_name.short_description = "Organization name" # type: ignore

def portfolio_federal_agency(self, obj):
return obj.portfolio.federal_agency if obj.portfolio else ""

portfolio_federal_agency.short_description = "Federal agency" # type: ignore

def portfolio_state_territory(self, obj):
return obj.portfolio.state_territory if obj.portfolio else ""

portfolio_state_territory.short_description = "State, territory, or military post" # type: ignore

def portfolio_address_line1(self, obj):
return obj.portfolio.address_line1 if obj.portfolio else ""

portfolio_address_line1.short_description = "Address line 1" # type: ignore

def portfolio_address_line2(self, obj):
return obj.portfolio.address_line2 if obj.portfolio else ""

portfolio_address_line2.short_description = "Address line 2" # type: ignore

def portfolio_city(self, obj):
return obj.portfolio.city if obj.portfolio else ""

portfolio_city.short_description = "City" # type: ignore

def portfolio_zipcode(self, obj):
return obj.portfolio.zipcode if obj.portfolio else ""

portfolio_zipcode.short_description = "Zip code" # type: ignore

def portfolio_urbanization(self, obj):
return obj.portfolio.urbanization if obj.portfolio else ""

portfolio_urbanization.short_description = "Urbanization" # type: ignore

fieldsets = copy.deepcopy(list(DomainInformationAdmin.fieldsets))
readonly_fields = copy.deepcopy(DomainInformationAdmin.readonly_fields)
analyst_readonly_fields = copy.deepcopy(DomainInformationAdmin.analyst_readonly_fields)
autocomplete_fields = copy.deepcopy(DomainInformationAdmin.autocomplete_fields)

Expand Down
13 changes: 13 additions & 0 deletions src/registrar/assets/src/js/getgov-admin/domain-form.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { handlePortfolioSelection } from './helpers-portfolio-dynamic-fields.js';

/**
* A function that appends target="_blank" to the domain_form buttons
*/
Expand Down Expand Up @@ -28,3 +30,14 @@ export function initDomainFormTargetBlankButtons() {
domainSubmitButton.addEventListener("mouseout", () => openInNewTab(domainFormElement, false));
}
}

/**
* A function for dynamic Domain fields
*/
export function initDynamicDomainFields(){
const domainPage = document.getElementById("domain_form");
if (domainPage) {
handlePortfolioSelection("#id_domain_info-0-portfolio",
"#id_domain_info-0-sub_organization");
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { handleSuborganizationFields } from './helpers-portfolio-dynamic-fields.js';
import { handlePortfolioSelection } from './helpers-portfolio-dynamic-fields.js';

/**
* A function for dynamic DomainInformation fields
*/
export function initDynamicDomainInformationFields(){
const domainInformationPage = document.getElementById("domaininformation_form");
if (domainInformationPage) {
handleSuborganizationFields();
}

// DomainInformation is embedded inside domain so this should fire there too
const domainPage = document.getElementById("domain_form");
if (domainPage) {
handleSuborganizationFields(portfolioDropdownSelector="#id_domain_info-0-portfolio", suborgDropdownSelector="#id_domain_info-0-sub_organization");
console.log("handling domain information page");
handlePortfolioSelection();
}
}
Loading
Loading