updatePortfolioFieldsDataDynamicDisplay cleanup

This commit is contained in:
Rachid Mrad 2024-11-06 17:31:40 -05:00
parent 4887a47796
commit 4e12b1295b
No known key found for this signature in database
4 changed files with 35 additions and 135 deletions

View file

@ -1735,7 +1735,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
return obj.portfolio.senior_official if obj.portfolio and obj.portfolio.senior_official else None
portfolio_senior_official.short_description = "Senior official"
def portfolio_organization_type(self, obj):
return obj.portfolio.organization_type if obj.portfolio else ""
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"
def portfolio_federal_type(self, obj):
return BranchChoices.get_branch_label(obj.portfolio.federal_type) if obj.portfolio and obj.portfolio.federal_type else "-"

View file

@ -86,6 +86,10 @@ function handleSuborganizationFields(
portfolioDropdown.on("change", toggleSuborganizationFields);
}
/**
* IMPORTANT NOTE: The logic in this method is paired dynamicPortfolioFields
*/
function handlePortfolioSelection() {
// These dropdown are select2 fields so they must be interacted with via jquery
const portfolioDropdown = django.jQuery("#id_portfolio");
@ -121,6 +125,7 @@ function handlePortfolioSelection() {
const portfolioUrbanizationField = document.querySelector(".field-portfolio_urbanization");
const portfolioUrbanization = portfolioUrbanizationField.querySelector(".readonly");
const portfolioJsonUrl = document.getElementById("portfolio_json_url")?.value || null;
const seniorOfficialAddress = portfolioSeniorOfficialField.querySelector(".dja-address-contact-list");
let isPageLoading = true;
function getPortfolio(portfolio_id) {
@ -174,19 +179,16 @@ function handlePortfolioSelection() {
function updatePortfolioSeniorOfficial(seniorOfficialField, senior_official) {
let seniorOfficial = seniorOfficialField.querySelector(".readonly");
let seniorOfficialAddress = seniorOfficialField.querySelector(".dja-address-contact-list");
let portfolioSeniorOfficialAddress = document.querySelector(".field-portfolio_senior_official .dja-address-contact-list");
if (senior_official) {
let seniorOfficialName = [senior_official.first_name, senior_official.last_name].join(' ');
let seniorOfficialLink = `<a href=/admin/registrar/seniorofficial/${senior_official.id}/change/ class='test'>${seniorOfficialName}</a>`
seniorOfficial.innerHTML = seniorOfficialName ? seniorOfficialLink : "-";
updateSeniorOfficialContactInfo(seniorOfficialAddress, senior_official);
showElement(portfolioSeniorOfficialAddress);
showElement(seniorOfficialAddress);
} else {
portfolioSeniorOfficial.innerText = "No senior official found.";
hideElement(portfolioSeniorOfficialAddress);
hideElement(seniorOfficialAddress);
}
}
@ -217,19 +219,14 @@ function handlePortfolioSelection() {
function updatePortfolioFieldsDataDynamicDisplay() {
// the federal agency change listener fires on page load, which we don't want.
var isInitialPageLoad = true
// This is the additional information that exists beneath the SO element.
var contactList = document.querySelector(".field-portfolio_senior_official .dja-address-contact-list");
document.addEventListener('DOMContentLoaded', function() {
let federalAgencyValue = portfolioFederalAgency.innerText;
let portfolioOrgTypeValue = portfolioOrgType.innerText;
// if (federalAgencyValue && portfolioOrgTypeValue) {
// handleFederalAgencyChange(federalAgencyValue, portfolioOrgTypeValue, portfolioOrgNameField, portfolioFederalTypeField);
// }
if (federalAgencyValue && portfolioOrgTypeValue) {
handleFederalAgencyChange(federalAgencyValue, portfolioOrgTypeValue);
}
// Handle dynamically hiding the urbanization field
let portfolioStateTerritoryValue = portfolioStateTerritory.innerText;
if (portfolioUrbanizationField && portfolioStateTerritoryValue) {
@ -237,8 +234,9 @@ function handlePortfolioSelection() {
}
// Handle hiding the organization name field when the organization_type is federal.
// Run this first one page load, then secondly on a change event.
handleOrganizationTypeChange(portfolioOrgTypeValue, portfolioOrgNameField, portfolioFederalTypeField);
handleNoSeniorOfficialData();
});
function handleOrganizationTypeChange(portfolioOrgTypeValue, portfolioOrgNameField, portfolioFederalTypeField) {
@ -257,13 +255,7 @@ function handlePortfolioSelection() {
}
}
function handleFederalAgencyChange(federalAgencyValue, organizationTypeValue, portfolioOrgNameField, portfolioFederalTypeField) {
// Don't do anything on page load
if (isInitialPageLoad) {
isInitialPageLoad = false;
return;
}
function handleFederalAgencyChange(federalAgencyValue, organizationTypeValue) {
// There isn't a federal senior official associated with null records
if (!federalAgencyValue) {
return;
@ -273,71 +265,12 @@ function handlePortfolioSelection() {
if (organizationTypeValue !== "federal") {
portfolioOrgType.innerText = "Federal"
}
}else {
} else {
if (organizationTypeValue === "federal") {
portfolioOrgType.innerText = "-"
}
}
handleOrganizationTypeChange(organizationTypeValue, portfolioOrgNameField, portfolioFederalTypeField);
// We are missing these hooks that exist on the portfolio template, so I hardcoded them for now:
// <input id="senior_official_from_agency_json_url" class="display-none" value="/admin/api/get-senior-official-from-federal-agency-json/" />
// <input id="federal_and_portfolio_types_from_agency_json_url" class="display-none" value="/admin/api/get-federal-and-portfolio-types-from-federal-agency-json/" />
// <input id="senior-official-add-url" class="display-none" value="/admin/registrar/seniorofficial/add/" />
let federalPortfolioApi = "/admin/api/get-federal-and-portfolio-types-from-federal-agency-json/";
fetch(`${federalPortfolioApi}?&agency_name=${selectedText}`)
.then(response => {
const statusCode = response.status;
return response.json().then(data => ({ statusCode, data }));
})
.then(({ statusCode, data }) => {
if (data.error) {
console.error("Error in AJAX call: " + data.error);
return;
}
updateReadOnly(data.federal_type, '.field-portfolio_federal_type');
})
.catch(error => console.error("Error fetching federal and portfolio types: ", error));
hideElement(contactList.parentElement);
let seniorOfficialAddUrl = "/admin/registrar/seniorofficial/add/";
let readonlySeniorOfficial = document.querySelector(".field-senior_official .readonly");
let seniorOfficialApi = "/admin/api/get-senior-official-from-federal-agency-json/";
fetch(`${seniorOfficialApi}?agency_name=${selectedText}`)
.then(response => {
const statusCode = response.status;
return response.json().then(data => ({ statusCode, data }));
})
.then(({ statusCode, data }) => {
if (data.error) {
if (statusCode === 404) {
readonlySeniorOfficial.innerHTML = `<a href="${seniorOfficialAddUrl}">No senior official found. Create one now.</a>`;
console.warn("Record not found: " + data.error);
}else {
console.error("Error in AJAX call: " + data.error);
}
return;
}
// Update the "contact details" blurb beneath senior official
updateContactInfo(data);
showElement(contactList.parentElement);
// Get the associated senior official with this federal agency
let seniorOfficialId = data.id;
let seniorOfficialName = [data.first_name, data.last_name].join(" ");
if (readonlySeniorOfficial) {
let seniorOfficialLink = `<a href=/admin/registrar/seniorofficial/${seniorOfficialId}/change/ class='test'>${seniorOfficialName}</a>`
readonlySeniorOfficial.innerHTML = seniorOfficialName ? seniorOfficialLink : "-";
}
})
.catch(error => console.error("Error fetching senior official: ", error));
}
function handleStateTerritoryChange(portfolioStateTerritoryValue, portfolioUrbanizationField) {
@ -348,58 +281,13 @@ function handlePortfolioSelection() {
}
}
/**
* Utility that selects a div from the DOM using selectorString,
* and updates a div within that div which has class of 'readonly'
* so that the text of the div is updated to updateText
* @param {*} updateText
* @param {*} selectorString
*/
function updateReadOnly(updateText, selectorString) {
// find the div by selectorString
const selectedDiv = document.querySelector(selectorString);
if (selectedDiv) {
// find the nested div with class 'readonly' inside the selectorString div
const readonlyDiv = selectedDiv.querySelector('.readonly');
if (readonlyDiv) {
// Update the text content of the readonly div
readonlyDiv.textContent = updateText !== null ? updateText : '-';
function handleNoSeniorOfficialData() {
if (portfolioSeniorOfficial.innerText.includes("No additional contact information found")) {
hideElement(seniorOfficialAddress);
}
}
}
function updateContactInfo(data) {
if (!contactList) return;
const titleSpan = contactList.querySelector(".contact_info_title");
const emailSpan = contactList.querySelector(".contact_info_email");
const phoneSpan = contactList.querySelector(".contact_info_phone");
if (titleSpan) {
titleSpan.textContent = data.title || "None";
};
// Update the email field and the content for the clipboard
if (emailSpan) {
let copyButton = contactList.querySelector(".admin-icon-group");
emailSpan.textContent = data.email || "None";
if (data.email) {
const clipboardInput = contactList.querySelector(".admin-icon-group input");
if (clipboardInput) {
clipboardInput.value = data.email;
};
showElement(copyButton);
}else {
hideElement(copyButton);
}
}
if (phoneSpan) {
phoneSpan.textContent = data.phone || "None";
};
}
}
async function updatePortfolioFields() {
if (!isPageLoading) {
if (portfolioDropdown.val()) {
@ -1426,6 +1314,7 @@ document.addEventListener('DOMContentLoaded', function() {
/** An IIFE for dynamically changing some fields on the portfolio admin model
* IMPORTANT NOTE: The logic in this IIFE is paired handlePortfolioSelection
*/
(function dynamicPortfolioFields(){

View file

@ -69,7 +69,9 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% elif field.field.name == "portfolio_senior_official" %}
<div class="readonly">
{% if original_object.portfolio.senior_official %}
<a href="{% url 'admin:registrar_seniorofficial_change' original_object.portfolio.senior_official.id %}">{{ field.contents }}</a></div>
<a href="{% url 'admin:registrar_seniorofficial_change' original_object.portfolio.senior_official.id %}">{{ field.contents }}</a>
{% else %}
No additional contact information found.<br>
{% endif %}
</div>
{% elif field.field.name == "other_contacts" %}
@ -341,6 +343,11 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% elif field.field.name == "portfolio_senior_official" %}
<div class="flex-container">
<label aria-label="Senior official contact details"></label>
{% comment %}fields_always_present=True will shortcut the contact_detail_list template when
1. Senior official field should be hidden on domain request because no portfoloio is selected, which is desirable
2. A portfolio is selected but there is no senior official on the portfolio, where the shortcut is not desirable
To solve 2, we use an else No additional contact information found on field.field.name == "portfolio_senior_official"
and we hide the placeholders from detail_table_fieldset in JS{% endcomment %}
{% include "django/admin/includes/contact_detail_list.html" with user=original_object.portfolio.senior_official no_title_top_padding=field.is_readonly fields_always_present=True %}
</div>
{% elif field.field.name == "other_contacts" and original_object.other_contacts.all %}

View file

@ -6,6 +6,7 @@ from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from registrar.utility.admin_helpers import get_action_needed_reason_default_email, get_rejection_reason_default_email
from registrar.models.portfolio import Portfolio
from registrar.models.domain_request import DomainRequest
from registrar.utility.constants import BranchChoices
logger = logging.getLogger(__name__)
@ -62,6 +63,9 @@ def get_portfolio_json(request):
# map portfolio federal type
portfolio_dict["federal_type"] = BranchChoices.get_branch_label(portfolio.federal_type) if portfolio.federal_type else "-"
# map portfolio organization type
portfolio_dict["organization_type"] = DomainRequest.OrganizationChoices.get_org_label(portfolio.organization_type) if portfolio.organization_type else "-"
# Add senior official information if it exists
if portfolio.senior_official:
senior_official = model_to_dict(
@ -84,7 +88,7 @@ def get_portfolio_json(request):
)
portfolio_dict["federal_agency"] = federal_agency["agency"]
else:
portfolio_dict["federal_agency"] = None
portfolio_dict["federal_agency"] = '-'
return JsonResponse(portfolio_dict)