Add clear button

This commit is contained in:
zandercymatics 2025-01-02 09:27:42 -07:00
parent f77b583750
commit 6f6e2dbc8b
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
9 changed files with 62 additions and 105 deletions

53
src/package-lock.json generated
View file

@ -6921,16 +6921,6 @@
"validate-npm-package-license": "^3.0.1" "validate-npm-package-license": "^3.0.1"
} }
}, },
"node_modules/normalize-package-data/node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/normalize-path": { "node_modules/normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -7307,39 +7297,6 @@
"node": ">= 12" "node": ">= 12"
} }
}, },
"node_modules/pa11y/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/pa11y/node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"license": "ISC",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/pa11y/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"license": "ISC"
},
"node_modules/parse-filepath": { "node_modules/parse-filepath": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
@ -8888,13 +8845,15 @@
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.1", "version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
} }
}, },
"node_modules/semver-greatest-satisfied-range": { "node_modules/semver-greatest-satisfied-range": {

View file

@ -2003,14 +2003,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
custom_requested_domain.admin_order_field = "requested_domain__name" # type: ignore custom_requested_domain.admin_order_field = "requested_domain__name" # type: ignore
# ------ Converted fields ------
# These fields map to @Property methods and
# require these custom definitions to work properly
@admin.display(description="Suborganization options")
def reject_suborganization_button(self, obj):
"""Custom field to display the reject suborganization button"""
return ""
@admin.display(description=_("Generic Org Type")) @admin.display(description=_("Generic Org Type"))
def converted_generic_org_type(self, obj): def converted_generic_org_type(self, obj):
return obj.converted_generic_org_type_display return obj.converted_generic_org_type_display
@ -2182,7 +2174,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"requested_suborganization", "requested_suborganization",
"suborganization_city", "suborganization_city",
"suborganization_state_territory", "suborganization_state_territory",
"reject_suborganization_button",
"creator", "creator",
] ]
}, },
@ -2304,7 +2295,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"alternative_domains", "alternative_domains",
"is_election_board", "is_election_board",
"status_history", "status_history",
"reject_suborganization_button",
) )
# Read only that we'll leverage for CISA Analysts # Read only that we'll leverage for CISA Analysts

View file

@ -644,21 +644,20 @@ function handleSuborgFieldsAndButtons() {
const requestedSuborganizationField = document.getElementById("id_requested_suborganization"); const requestedSuborganizationField = document.getElementById("id_requested_suborganization");
const suborganizationCity = document.getElementById("id_suborganization_city"); const suborganizationCity = document.getElementById("id_suborganization_city");
const suborganizationStateTerritory = document.getElementById("id_suborganization_state_territory"); const suborganizationStateTerritory = document.getElementById("id_suborganization_state_territory");
// The reject button is wrapped in a fieldset with a label
const rejectButtonFieldset = document.querySelector(".field-reject_suborganization_button");
const rejectButton = document.querySelector("#clear-requested-suborganization"); const rejectButton = document.querySelector("#clear-requested-suborganization");
console.log("test12345678")
// Ensure that every variable is present before proceeding // Ensure that every variable is present before proceeding
if (!requestedSuborganizationField || !suborganizationCity || !suborganizationStateTerritory || !rejectButtonFieldset || !rejectButton) { if (!requestedSuborganizationField || !suborganizationCity || !suborganizationStateTerritory || !rejectButton) {
console.warn("handleSuborganizationSelection() => Could not find required fields.") console.warn("handleSuborganizationSelection() => Could not find required fields.")
return; return;
} }
function updateRejectButtonFieldset() { function handleRejectButtonVisibility() {
if (requestedSuborganizationField.value || suborganizationCity.value || suborganizationStateTerritory.value) { if (requestedSuborganizationField.value || suborganizationCity.value || suborganizationStateTerritory.value) {
showElement(rejectButtonFieldset); showElement(rejectButton);
}else { }else {
hideElement(rejectButtonFieldset) hideElement(rejectButton)
} }
} }
@ -668,12 +667,12 @@ function handleSuborgFieldsAndButtons() {
suborganizationCity.value = ""; suborganizationCity.value = "";
suborganizationStateTerritory.value = ""; suborganizationStateTerritory.value = "";
// Update button visibility after clearing // Update button visibility after clearing
updateRejectButtonFieldset(); handleRejectButtonVisibility();
} }
rejectButton.addEventListener("click", handleRejectButton) rejectButton.addEventListener("click", handleRejectButton)
requestedSuborganizationField.addEventListener("blur", updateRejectButtonFieldset); requestedSuborganizationField.addEventListener("blur", handleRejectButtonVisibility);
suborganizationCity.addEventListener("blur", updateRejectButtonFieldset); suborganizationCity.addEventListener("blur", handleRejectButtonVisibility);
suborganizationStateTerritory.addEventListener("change", updateRejectButtonFieldset); suborganizationStateTerritory.addEventListener("change", handleRejectButtonVisibility);
} }
/** /**

View file

@ -49,7 +49,13 @@ export function handlePortfolioSelection(
const portfolioUrbanizationField = document.querySelector(".field-portfolio_urbanization"); const portfolioUrbanizationField = document.querySelector(".field-portfolio_urbanization");
const portfolioUrbanization = portfolioUrbanizationField.querySelector(".readonly"); const portfolioUrbanization = portfolioUrbanizationField.querySelector(".readonly");
const portfolioJsonUrl = document.getElementById("portfolio_json_url")?.value || null; const portfolioJsonUrl = document.getElementById("portfolio_json_url")?.value || null;
const rejectSuborganizationButtonFieldset = document.querySelector(".field-reject_suborganization_button"); // These requested suborganization fields only exist on the domain request page
const rejectSuborganizationButton = document.querySelector("#clear-requested-suborganization");
const requestedSuborganizationFieldInput = document.getElementById("id_requested_suborganization");
const suborganizationCityInput = document.getElementById("id_suborganization_city");
const suborganizationStateTerritoryInput = document.getElementById("id_suborganization_state_territory");
// Global var to track page load
let isPageLoading = true; let isPageLoading = true;
/** /**
@ -471,35 +477,26 @@ export function handlePortfolioSelection(
if (suborganizationCity) showElement(suborganizationCity); if (suborganizationCity) showElement(suborganizationCity);
if (suborganizationStateTerritory) showElement(suborganizationStateTerritory); if (suborganizationStateTerritory) showElement(suborganizationStateTerritory);
// Handle rejectSuborganizationButtonFieldset (display of the clear requested suborg button). // == LOGIC FOR THE DOMAIN REQUEST PAGE == //
// Handle rejectSuborganizationButton (display of the clear requested suborg button).
// Basically, this button should only be visible when we have data for suborg, city, and state_territory. // Basically, this button should only be visible when we have data for suborg, city, and state_territory.
// The function handleSuborgFieldsAndButtons() in domain-request-form.js handles doing this same logic // The function handleSuborgFieldsAndButtons() in domain-request-form.js handles doing this same logic
// but on field input for city, state_territory, and the suborg field. // but on field input for city, state_territory, and the suborg field.
// If it doesn't exist, don't do anything. // If it doesn't exist, don't do anything.
if (!rejectSuborganizationButtonFieldset){ if (rejectSuborganizationButton){
console.warn("updateSuborganizationFieldsDisplay() => Could not update rejectSuborganizationButtonFieldset") if (requestedSuborganizationFieldInput?.value || suborganizationCityInput?.value || suborganizationStateTerritoryInput?.value) {
return; showElement(rejectSuborganizationButton);
}
// Initially show / hide the clear button only if there is data to clear
let requestedSuborganizationFieldInput = document.getElementById("id_requested_suborganization");
let suborganizationCityInput = document.getElementById("id_suborganization_city");
let suborganizationStateTerritoryInput = document.getElementById("id_suborganization_state_territory");
if (!requestedSuborganizationFieldInput || !suborganizationCityInput || !suborganizationStateTerritoryInput) {
return;
}
if (requestedSuborganizationFieldInput.value || suborganizationCityInput.value || suborganizationStateTerritoryInput.value) {
showElement(rejectSuborganizationButtonFieldset);
}else { }else {
hideElement(rejectSuborganizationButtonFieldset); hideElement(rejectSuborganizationButton);
}
} }
} else { } else {
// Hide suborganization request fields if suborganization is selected // Hide suborganization request fields if suborganization is selected
if (requestedSuborganizationField) hideElement(requestedSuborganizationField); if (requestedSuborganizationField) hideElement(requestedSuborganizationField);
if (suborganizationCity) hideElement(suborganizationCity); if (suborganizationCity) hideElement(suborganizationCity);
if (suborganizationStateTerritory) hideElement(suborganizationStateTerritory); if (suborganizationStateTerritory) hideElement(suborganizationStateTerritory);
if (rejectSuborganizationButtonFieldset) hideElement(rejectSuborganizationButtonFieldset); // == LOGIC FOR THE DOMAIN REQUEST PAGE == //
if (rejectSuborganizationButton) hideElement(rejectSuborganizationButton);
} }
} }

View file

@ -244,6 +244,7 @@ class Domain(TimeStampedModel, DomainHelper):
is called in the validate function on the request/domain page is called in the validate function on the request/domain page
throws- RegistryError or InvalidDomainError""" throws- RegistryError or InvalidDomainError"""
return True
if not cls.string_could_be_domain(domain): if not cls.string_could_be_domain(domain):
logger.warning("Not a valid domain: %s" % str(domain)) logger.warning("Not a valid domain: %s" % str(domain))
# throw invalid domain error so that it can be caught in # throw invalid domain error so that it can be caught in

View file

@ -20,7 +20,16 @@
{% url 'get-rejection-email-for-user-json' as url_2 %} {% url 'get-rejection-email-for-user-json' as url_2 %}
<input id="get-rejection-email-for-user-json" class="display-none" value="{{ url_2 }}" /> <input id="get-rejection-email-for-user-json" class="display-none" value="{{ url_2 }}" />
{% for fieldset in adminform %} {% for fieldset in adminform %}
{% include "django/admin/includes/domain_request_fieldset.html" with original_object=original %} {% comment %}
TODO: this will eventually need to be changed to something like this
if we ever want to customize this file:
{% include "django/admin/includes/domain_information_fieldset.html" %}
Use detail_table_fieldset as an example, or just extend it.
original_object is just a variable name for "DomainInformation" or "DomainRequest"
{% endcomment %}
{% include "django/admin/includes/detail_table_fieldset.html" with original_object=original %}
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

View file

@ -321,6 +321,25 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% else %} {% else %}
<input id="last-sent-rejection-email-content" class="display-none" value="None"> <input id="last-sent-rejection-email-content" class="display-none" value="None">
{% endif %} {% endif %}
{% elif field.field.name == "requested_suborganization" %}
{{ field.field }}
<div class="requested-suborganization--clear-button">
<button
id="clear-requested-suborganization"
class="usa-button--dja usa-button usa-button__small-text usa-button--unstyled padding-left-1 usa-button--icon"
type="button"
>
<div class="no-outline-on-click">
<svg
class="usa-icon"
>
<use aria-hidden="true" xlink:href="{%static 'img/sprite.svg'%}#close"></use>
</svg>
<!-- the span is targeted in JS, do not remove -->
<span>Clear requested suborganization</span>
</div>
</button>
</div>
{% else %} {% else %}
{{ field.field }} {{ field.field }}
{% endif %} {% endif %}

View file

@ -1,14 +0,0 @@
{% extends "django/admin/includes/email_clipboard_fieldset.html" %}
{% load custom_filters %}
{% load static url_helpers %}
{% load i18n static %}
{% block field_readonly %}
{{ block.super }}
{% if field.field.name == "reject_suborganization_button" %}
<button type="button" class="usa-button--dja usa-button usa-button__small-text" id="clear-requested-suborganization">
Clear all requested suborganization fields
</button>
{% endif %}
{% endblock field_readonly %}

View file

@ -1644,7 +1644,6 @@ class TestDomainRequestAdmin(MockEppLib):
"alternative_domains", "alternative_domains",
"is_election_board", "is_election_board",
"status_history", "status_history",
"reject_suborganization_button",
"id", "id",
"created_at", "created_at",
"updated_at", "updated_at",
@ -1719,7 +1718,6 @@ class TestDomainRequestAdmin(MockEppLib):
"alternative_domains", "alternative_domains",
"is_election_board", "is_election_board",
"status_history", "status_history",
"reject_suborganization_button",
"federal_agency", "federal_agency",
"creator", "creator",
"about_your_organization", "about_your_organization",
@ -1760,7 +1758,6 @@ class TestDomainRequestAdmin(MockEppLib):
"alternative_domains", "alternative_domains",
"is_election_board", "is_election_board",
"status_history", "status_history",
"reject_suborganization_button",
] ]
self.assertEqual(readonly_fields, expected_fields) self.assertEqual(readonly_fields, expected_fields)