init refactor of portfolio form js

This commit is contained in:
Rachid Mrad 2024-12-10 17:59:38 -05:00
parent 42c62c2ba0
commit 41c148b15e
No known key found for this signature in database
2 changed files with 186 additions and 177 deletions

View file

@ -4,41 +4,41 @@ import { hideElement, showElement } from './helpers-admin.js';
* Helper function that handles business logic for the suborganization field. * Helper function that handles business logic for the suborganization field.
* Can be used anywhere the suborganization dropdown exists * Can be used anywhere the suborganization dropdown exists
*/ */
export function handleSuborganizationFields( // export function handleSuborganizationFields(
portfolioDropdownSelector="#id_portfolio", // portfolioDropdownSelector="#id_portfolio",
suborgDropdownSelector="#id_sub_organization", // suborgDropdownSelector="#id_sub_organization",
requestedSuborgFieldSelector=".field-requested_suborganization", // requestedSuborgFieldSelector=".field-requested_suborganization",
suborgCitySelector=".field-suborganization_city", // suborgCitySelector=".field-suborganization_city",
suborgStateTerritorySelector=".field-suborganization_state_territory" // suborgStateTerritorySelector=".field-suborganization_state_territory"
) { // ) {
// These dropdown are select2 fields so they must be interacted with via jquery // // These dropdown are select2 fields so they must be interacted with via jquery
const portfolioDropdown = django.jQuery(portfolioDropdownSelector) // const portfolioDropdown = django.jQuery(portfolioDropdownSelector)
const suborganizationDropdown = django.jQuery(suborgDropdownSelector) // const suborganizationDropdown = django.jQuery(suborgDropdownSelector)
const requestedSuborgField = document.querySelector(requestedSuborgFieldSelector); // const requestedSuborgField = document.querySelector(requestedSuborgFieldSelector);
const suborgCity = document.querySelector(suborgCitySelector); // const suborgCity = document.querySelector(suborgCitySelector);
const suborgStateTerritory = document.querySelector(suborgStateTerritorySelector); // const suborgStateTerritory = document.querySelector(suborgStateTerritorySelector);
if (!suborganizationDropdown || !requestedSuborgField || !suborgCity || !suborgStateTerritory) { // if (!suborganizationDropdown || !requestedSuborgField || !suborgCity || !suborgStateTerritory) {
console.error("Requested suborg fields not found."); // console.error("Requested suborg fields not found.");
return; // return;
} // }
function toggleSuborganizationFields() { // function toggleSuborganizationFields() {
if (portfolioDropdown.val() && !suborganizationDropdown.val()) { // if (portfolioDropdown.val() && !suborganizationDropdown.val()) {
if (requestedSuborgField) showElement(requestedSuborgField); // if (requestedSuborgField) showElement(requestedSuborgField);
if (suborgCity) showElement(suborgCity); // if (suborgCity) showElement(suborgCity);
if (suborgStateTerritory) showElement(suborgStateTerritory); // if (suborgStateTerritory) showElement(suborgStateTerritory);
}else { // }else {
if (requestedSuborgField) hideElement(requestedSuborgField); // if (requestedSuborgField) hideElement(requestedSuborgField);
if (suborgCity) hideElement(suborgCity); // if (suborgCity) hideElement(suborgCity);
if (suborgStateTerritory) hideElement(suborgStateTerritory); // if (suborgStateTerritory) hideElement(suborgStateTerritory);
} // }
} // }
// Run the function once on page startup, then attach an event listener // // Run the function once on page startup, then attach an event listener
toggleSuborganizationFields(); // toggleSuborganizationFields();
suborganizationDropdown.on("change", toggleSuborganizationFields); // suborganizationDropdown.on("change", toggleSuborganizationFields);
portfolioDropdown.on("change", toggleSuborganizationFields); // portfolioDropdown.on("change", toggleSuborganizationFields);
} // }
/** /**

View file

@ -4,69 +4,87 @@ import { hideElement, showElement } from './helpers-admin.js';
* A function for dynamically changing some fields on the portfolio admin model * A function for dynamically changing some fields on the portfolio admin model
* IMPORTANT NOTE: The logic in this function is paired handlePortfolioSelection and should be refactored once we solidify our requirements. * IMPORTANT NOTE: The logic in this function is paired handlePortfolioSelection and should be refactored once we solidify our requirements.
*/ */
export function initDynamicPortfolioFields(){ function handlePortfolioFields(){
// 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-senior_official .dja-address-contact-list");
const federalAgencyContainer = document.querySelector(".field-federal_agency");
document.addEventListener('DOMContentLoaded', function() {
let isPortfolioPage = document.getElementById("portfolio_form");
if (!isPortfolioPage) {
return;
}
let isPageLoading = true
let seniorOfficialContactList = document.querySelector(".field-senior_official .dja-address-contact-list");
const federalAgency = document.querySelector(".field-federal_agency");
// $ symbolically denotes that this is using jQuery // $ symbolically denotes that this is using jQuery
let $federalAgency = django.jQuery("#id_federal_agency"); let $federalAgency = django.jQuery("#id_federal_agency");
let organizationType = document.getElementById("id_organization_type"); let organizationType = document.getElementById("id_organization_type");
let readonlyOrganizationType = document.querySelector(".field-organization_type .readonly"); let readonlyOrganizationType = document.querySelector(".field-organization_type .readonly");
let organizationName = document.querySelector(".field-organization_name");
let organizationNameContainer = document.querySelector(".field-organization_name");
let federalType = document.querySelector(".field-federal_type"); let federalType = document.querySelector(".field-federal_type");
let urbanization = document.querySelector(".field-urbanization");
if ($federalAgency && (organizationType || readonlyOrganizationType)) {
// Attach the change event listener
$federalAgency.on("change", function() {
handleFederalAgencyChange($federalAgency, organizationType, readonlyOrganizationType, organizationNameContainer, federalType);
});
}
// Handle dynamically hiding the urbanization field
let urbanizationField = document.querySelector(".field-urbanization");
let stateTerritory = document.getElementById("id_state_territory"); let stateTerritory = document.getElementById("id_state_territory");
if (urbanizationField && stateTerritory) { let $seniorOfficial = django.jQuery("#id_senior_official");
// Execute this function once on load let readonlySeniorOfficial = document.querySelector(".field-senior_official .readonly");
handleStateTerritoryChange(stateTerritory, urbanizationField);
// Attach the change event listener for state/territory function getFederalTypeFromAgency(agency) {
stateTerritory.addEventListener("change", function() { let federalPortfolioApi = document.getElementById("federal_and_portfolio_types_from_agency_json_url").value;
handleStateTerritoryChange(stateTerritory, urbanizationField); return fetch(`${federalPortfolioApi}?&agency_name=${agency}`)
.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;
}
return data.federal_type
})
.catch(error => {
console.error("Error fetching federal and portfolio types: ", error);
return null
}); });
} }
// Handle hiding the organization name field when the organization_type is federal. function getSeniorOfficialFromAgency(agency, seniorOfficialAddUrl) {
// Run this first one page load, then secondly on a change event. let seniorOfficialApi = document.getElementById("senior_official_from_agency_json_url").value;
handleOrganizationTypeChange(organizationType, organizationNameContainer, federalType); return fetch(`${seniorOfficialApi}?agency_name=${agency}`)
organizationType.addEventListener("change", function() { .then(response => {
handleOrganizationTypeChange(organizationType, organizationNameContainer, federalType); const statusCode = response.status;
}); return response.json().then(data => ({ statusCode, data }));
})
.then(({ statusCode, data }) => {
if (data.error) {
if (statusCode === 404) {
if ($seniorOfficial && $seniorOfficial.length > 0) {
$seniorOfficial.val("").trigger("change");
} else {
// Show the "create one now" text if this field is none in readonly mode.
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 null;
} else {
return data;
}
})
.catch(error => {
console.error("Error fetching senior official: ", error)
return null;
}); });
}
function handleOrganizationTypeChange(organizationType, organizationNameContainer, federalType) { function handleOrganizationTypeChange(organizationType, organizationNameContainer, federalType) {
if (organizationType && organizationNameContainer) { if (organizationType && organizationNameContainer) {
let selectedValue = organizationType.value; let selectedValue = organizationType.value;
if (selectedValue === "federal") { if (selectedValue === "federal") {
hideElement(organizationNameContainer); hideElement(organizationNameContainer);
showElement(federalAgencyContainer); showElement(federalAgency);
if (federalType) { if (federalType) {
showElement(federalType); showElement(federalType);
} }
} else { } else {
showElement(organizationNameContainer); showElement(organizationNameContainer);
hideElement(federalAgencyContainer); hideElement(federalAgency);
if (federalType) { if (federalType) {
hideElement(federalType); hideElement(federalType);
} }
@ -75,22 +93,16 @@ export function initDynamicPortfolioFields(){
} }
function handleFederalAgencyChange(federalAgency, organizationType, readonlyOrganizationType, organizationNameContainer, federalType) { function handleFederalAgencyChange(federalAgency, organizationType, readonlyOrganizationType, organizationNameContainer, federalType) {
// Don't do anything on page load if (!isPageLoading) {
if (isInitialPageLoad) {
isInitialPageLoad = false;
return;
}
// Set the org type to federal if an agency is selected
let selectedText = federalAgency.find("option:selected").text();
let selectedFederalAgency = federalAgency.find("option:selected").text();
// There isn't a federal senior official associated with null records // There isn't a federal senior official associated with null records
if (!selectedText) { if (!selectedFederalAgency) {
return; return;
} }
let organizationTypeValue = organizationType ? organizationType.value : readonlyOrganizationType.innerText.toLowerCase(); let organizationTypeValue = organizationType ? organizationType.value : readonlyOrganizationType.innerText.toLowerCase();
if (selectedText !== "Non-Federal Agency") { if (selectedFederalAgency !== "Non-Federal Agency") {
if (organizationTypeValue !== "federal") { if (organizationTypeValue !== "federal") {
if (organizationType){ if (organizationType){
organizationType.value = "federal"; organizationType.value = "federal";
@ -98,7 +110,7 @@ export function initDynamicPortfolioFields(){
readonlyOrganizationType.innerText = "Federal" readonlyOrganizationType.innerText = "Federal"
} }
} }
}else { } else {
if (organizationTypeValue === "federal") { if (organizationTypeValue === "federal") {
if (organizationType){ if (organizationType){
organizationType.value = ""; organizationType.value = "";
@ -112,55 +124,14 @@ export function initDynamicPortfolioFields(){
// Determine if any changes are necessary to the display of portfolio type or federal type // Determine if any changes are necessary to the display of portfolio type or federal type
// based on changes to the Federal Agency // based on changes to the Federal Agency
let federalPortfolioApi = document.getElementById("federal_and_portfolio_types_from_agency_json_url").value; getFederalTypeFromAgency(selectedFederalAgency).then((federalType) => updateReadOnly(federalType, '.field-federal_type'));
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-federal_type');
})
.catch(error => console.error("Error fetching federal and portfolio types: ", error));
// Hide the contactList initially.
// If we can update the contact information, it'll be shown again.
hideElement(contactList.parentElement);
hideElement(seniorOfficialContactList.parentElement);
let seniorOfficialAddUrl = document.getElementById("senior-official-add-url").value; let seniorOfficialAddUrl = document.getElementById("senior-official-add-url").value;
let $seniorOfficial = django.jQuery("#id_senior_official"); getSeniorOfficialFromAgency(selectedFederalAgency, seniorOfficialAddUrl).then((data) => {
let readonlySeniorOfficial = document.querySelector(".field-senior_official .readonly");
let seniorOfficialApi = document.getElementById("senior_official_from_agency_json_url").value;
fetch(`${seniorOfficialApi}?agency_name=${selectedText}`)
.then(response => {
const statusCode = response.status;
return response.json().then(data => ({ statusCode, data }));
})
.then(({ statusCode, data }) => {
if (data.error) {
// Clear the field if the SO doesn't exist.
if (statusCode === 404) {
if ($seniorOfficial && $seniorOfficial.length > 0) {
$seniorOfficial.val("").trigger("change");
}else {
// Show the "create one now" text if this field is none in readonly mode.
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 // Update the "contact details" blurb beneath senior official
updateContactInfo(data); updateContactInfo(data);
showElement(contactList.parentElement); showElement(seniorOfficialContactList.parentElement);
// Get the associated senior official with this federal agency // Get the associated senior official with this federal agency
let seniorOfficialId = data.id; let seniorOfficialId = data.id;
let seniorOfficialName = [data.first_name, data.last_name].join(" "); let seniorOfficialName = [data.first_name, data.last_name].join(" ");
@ -173,8 +144,11 @@ export function initDynamicPortfolioFields(){
readonlySeniorOfficial.innerHTML = seniorOfficialName ? seniorOfficialLink : "-"; readonlySeniorOfficial.innerHTML = seniorOfficialName ? seniorOfficialLink : "-";
} }
} }
}) });
.catch(error => console.error("Error fetching senior official: ", error));
} else {
isPageLoading = false;
}
} }
@ -184,7 +158,6 @@ export function initDynamicPortfolioFields(){
dropdown.val("").trigger("change"); dropdown.val("").trigger("change");
return; return;
} }
// Add the senior official to the dropdown. // Add the senior official to the dropdown.
// This format supports select2 - if we decide to convert this field in the future. // This format supports select2 - if we decide to convert this field in the future.
if (dropdown.find(`option[value='${seniorOfficialId}']`).length) { if (dropdown.find(`option[value='${seniorOfficialId}']`).length) {
@ -227,11 +200,11 @@ export function initDynamicPortfolioFields(){
} }
function updateContactInfo(data) { function updateContactInfo(data) {
if (!contactList) return; if (!seniorOfficialContactList) return;
const titleSpan = contactList.querySelector(".contact_info_title"); const titleSpan = seniorOfficialContactList.querySelector(".contact_info_title");
const emailSpan = contactList.querySelector(".contact_info_email"); const emailSpan = seniorOfficialContactList.querySelector(".contact_info_email");
const phoneSpan = contactList.querySelector(".contact_info_phone"); const phoneSpan = seniorOfficialContactList.querySelector(".contact_info_phone");
if (titleSpan) { if (titleSpan) {
titleSpan.textContent = data.title || "None"; titleSpan.textContent = data.title || "None";
@ -239,10 +212,10 @@ export function initDynamicPortfolioFields(){
// Update the email field and the content for the clipboard // Update the email field and the content for the clipboard
if (emailSpan) { if (emailSpan) {
let copyButton = contactList.querySelector(".admin-icon-group"); let copyButton = seniorOfficialContactList.querySelector(".admin-icon-group");
emailSpan.textContent = data.email || "None"; emailSpan.textContent = data.email || "None";
if (data.email) { if (data.email) {
const clipboardInput = contactList.querySelector(".admin-icon-group input"); const clipboardInput = seniorOfficialContactList.querySelector(".admin-icon-group input");
if (clipboardInput) { if (clipboardInput) {
clipboardInput.value = data.email; clipboardInput.value = data.email;
}; };
@ -256,4 +229,40 @@ export function initDynamicPortfolioFields(){
phoneSpan.textContent = data.phone || "None"; phoneSpan.textContent = data.phone || "None";
}; };
} }
function initializePortfolioSettings() {
if (urbanization && stateTerritory) {
handleStateTerritoryChange(stateTerritory, urbanization);
}
handleOrganizationTypeChange(organizationType, organizationName, federalType);
}
function setEventListeners() {
if ($federalAgency && (organizationType || readonlyOrganizationType)) {
$federalAgency.on("change", function() {
handleFederalAgencyChange($federalAgency, organizationType, readonlyOrganizationType, organizationName, federalType);
});
}
if (urbanization && stateTerritory) {
stateTerritory.addEventListener("change", function() {
handleStateTerritoryChange(stateTerritory, urbanization);
});
}
organizationType.addEventListener("change", function() {
handleOrganizationTypeChange(organizationType, organizationName, federalType);
});
}
// Run initial setup functions
initializePortfolioSettings();
setEventListeners();
}
export function initPortfolioFields() {
document.addEventListener('DOMContentLoaded', function() {
let isPortfolioPage = document.getElementById("portfolio_form");
if (isPortfolioPage) {
handlePortfolioFields();
}
});
} }