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"
}
},
"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": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -7307,39 +7297,6 @@
"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": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
@ -8888,13 +8845,15 @@
}
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"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
# ------ 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"))
def converted_generic_org_type(self, obj):
return obj.converted_generic_org_type_display
@ -2182,7 +2174,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"requested_suborganization",
"suborganization_city",
"suborganization_state_territory",
"reject_suborganization_button",
"creator",
]
},
@ -2304,7 +2295,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"alternative_domains",
"is_election_board",
"status_history",
"reject_suborganization_button",
)
# 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 suborganizationCity = document.getElementById("id_suborganization_city");
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");
console.log("test12345678")
// 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.")
return;
}
function updateRejectButtonFieldset() {
function handleRejectButtonVisibility() {
if (requestedSuborganizationField.value || suborganizationCity.value || suborganizationStateTerritory.value) {
showElement(rejectButtonFieldset);
showElement(rejectButton);
}else {
hideElement(rejectButtonFieldset)
hideElement(rejectButton)
}
}
@ -668,12 +667,12 @@ function handleSuborgFieldsAndButtons() {
suborganizationCity.value = "";
suborganizationStateTerritory.value = "";
// Update button visibility after clearing
updateRejectButtonFieldset();
handleRejectButtonVisibility();
}
rejectButton.addEventListener("click", handleRejectButton)
requestedSuborganizationField.addEventListener("blur", updateRejectButtonFieldset);
suborganizationCity.addEventListener("blur", updateRejectButtonFieldset);
suborganizationStateTerritory.addEventListener("change", updateRejectButtonFieldset);
requestedSuborganizationField.addEventListener("blur", handleRejectButtonVisibility);
suborganizationCity.addEventListener("blur", handleRejectButtonVisibility);
suborganizationStateTerritory.addEventListener("change", handleRejectButtonVisibility);
}
/**

View file

@ -49,7 +49,13 @@ export function handlePortfolioSelection(
const portfolioUrbanizationField = document.querySelector(".field-portfolio_urbanization");
const portfolioUrbanization = portfolioUrbanizationField.querySelector(".readonly");
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;
/**
@ -471,35 +477,26 @@ export function handlePortfolioSelection(
if (suborganizationCity) showElement(suborganizationCity);
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.
// 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.
// If it doesn't exist, don't do anything.
if (!rejectSuborganizationButtonFieldset){
console.warn("updateSuborganizationFieldsDisplay() => Could not update rejectSuborganizationButtonFieldset")
return;
}
// 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);
if (rejectSuborganizationButton){
if (requestedSuborganizationFieldInput?.value || suborganizationCityInput?.value || suborganizationStateTerritoryInput?.value) {
showElement(rejectSuborganizationButton);
}else {
hideElement(rejectSuborganizationButtonFieldset);
hideElement(rejectSuborganizationButton);
}
}
} else {
// Hide suborganization request fields if suborganization is selected
if (requestedSuborganizationField) hideElement(requestedSuborganizationField);
if (suborganizationCity) hideElement(suborganizationCity);
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
throws- RegistryError or InvalidDomainError"""
return True
if not cls.string_could_be_domain(domain):
logger.warning("Not a valid domain: %s" % str(domain))
# 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 %}
<input id="get-rejection-email-for-user-json" class="display-none" value="{{ url_2 }}" />
{% 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 %}
{% endblock %}

View file

@ -321,6 +321,25 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% else %}
<input id="last-sent-rejection-email-content" class="display-none" value="None">
{% 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 %}
{{ field.field }}
{% 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",
"is_election_board",
"status_history",
"reject_suborganization_button",
"id",
"created_at",
"updated_at",
@ -1719,7 +1718,6 @@ class TestDomainRequestAdmin(MockEppLib):
"alternative_domains",
"is_election_board",
"status_history",
"reject_suborganization_button",
"federal_agency",
"creator",
"about_your_organization",
@ -1760,7 +1758,6 @@ class TestDomainRequestAdmin(MockEppLib):
"alternative_domains",
"is_election_board",
"status_history",
"reject_suborganization_button",
]
self.assertEqual(readonly_fields, expected_fields)