mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-29 22:16:33 +02:00
updatePortfolioFieldsDataDynamicDisplay cleanup
This commit is contained in:
parent
4887a47796
commit
4e12b1295b
4 changed files with 35 additions and 135 deletions
|
@ -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 "-"
|
||||
|
|
|
@ -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(){
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue