From cdfb4e4c21725bf9bd645e4f3248750d2f88f455 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Thu, 6 Feb 2025 17:03:09 -0500 Subject: [PATCH 01/62] changes --- src/registrar/assets/src/js/getgov/formset-forms.js | 12 ++++++++++-- src/registrar/assets/src/js/getgov/main.js | 2 +- src/registrar/templates/domain_nameservers.html | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/formset-forms.js b/src/registrar/assets/src/js/getgov/formset-forms.js index 27b85212e..87fcb5a66 100644 --- a/src/registrar/assets/src/js/getgov/formset-forms.js +++ b/src/registrar/assets/src/js/getgov/formset-forms.js @@ -214,13 +214,21 @@ export function initFormsetsForms() { let addButton = document.querySelector("#add-form"); let cloneIndex = 0; let formLabel = ''; + // remove nameservers + // clean up wherever nameservers are let isNameserversForm = document.querySelector(".nameservers-form"); let isOtherContactsForm = document.querySelector(".other-contacts-form"); let isDsDataForm = document.querySelector(".ds-data-form"); let isDotgovDomain = document.querySelector(".dotgov-domain-form"); // The Nameservers formset features 2 required and 11 optionals + // if not is other contactsform or dsdataform or isdotgovdomain + // remove nameservers form, start el + if( !(isOtherContactsForm || isDotgovDomain || isDsDataForm) ){ + console.log("we reached inside the if statement") + return + } if (isNameserversForm) { - // cloneIndex = 2; + // cloneInex = 2; formLabel = "Name server"; // DNSSEC: DS Data } else if (isDsDataForm) { @@ -240,7 +248,7 @@ export function initFormsetsForms() { addButton.setAttribute("disabled", "true"); } - // Hide forms which have previously been deleted + // Hide forms which have prevnniously been deleted hideDeletedForms() // Attach click event listener on the delete buttons of the existing forms diff --git a/src/registrar/assets/src/js/getgov/main.js b/src/registrar/assets/src/js/getgov/main.js index a077da929..ecb6de4a7 100644 --- a/src/registrar/assets/src/js/getgov/main.js +++ b/src/registrar/assets/src/js/getgov/main.js @@ -20,7 +20,7 @@ initDomainValidators(); initFormsetsForms(); triggerModalOnDsDataForm(); -nameserversFormListener(); +//nameserversFormListener(); hookupYesNoListener("other_contacts-has_other_contacts",'other-employees', 'no-other-employees'); hookupYesNoListener("additional_details-has_anything_else_text",'anything-else', null); diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index ad8d61592..fce8499ad 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -53,6 +53,7 @@ {% for form in formset %}
+
Domain Name
{{ form.domain }} From 1f109bd04046b2ed6f189e2ebe1e390dcd33b435 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 6 Feb 2025 17:18:44 -0500 Subject: [PATCH 02/62] pseudo code in template --- .../templates/domain_nameservers.html | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index fce8499ad..ef2ff879a 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -51,9 +51,60 @@ {% csrf_token %} {{ formset.management_form }} - {% for form in formset %} + + + + + - {% comment %} Work around USWDS' button margins to add some spacing between the submit and the 'add more' This solution still works when we remove the 'add more' at 13 forms {% endcomment %}
diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 5ac6ecb20..f0b2a140d 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -758,8 +758,10 @@ class DomainNameserversView(DomainFormBaseView): # Ensure at least 3 fields, filled or empty if len(initial_data) == 0: - while len(initial_data) < 2: + while len(initial_data) < 1: initial_data.append({}) + else: + initial_data.append({}) return initial_data @@ -771,6 +773,7 @@ class DomainNameserversView(DomainFormBaseView): """Adjust context from FormMixin for formsets.""" context = super().get_context_data(**kwargs) # use "formset" instead of "form" for the key + print(context) context["formset"] = context.pop("form") return context From f03a61f93150fcf712824920f325d4a7699a3d6b Mon Sep 17 00:00:00 2001 From: asaki222 Date: Wed, 12 Feb 2025 17:15:53 -0500 Subject: [PATCH 05/62] stuff i have so far --- src/registrar/templates/domain_nameservers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index dcaef42c4..87041e282 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -44,7 +44,7 @@

Add a name server record by clicking "Add name servers". You must add at least two name servers (13 max).

{% include "includes/required_fields.html" %} - +
+ + + {% endif %} + {% endfor %} + + - - - {% comment %} Work around USWDS' button margins to add some spacing between the submit and the 'add more' - This solution still works when we remove the 'add more' at 13 forms {% endcomment %} -
- - - -
+ {% else %} -

No initial data

+

Add name servers

{% csrf_token %} {{ formset.management_form }} @@ -196,7 +189,6 @@
- {{ form.domain }} {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %} {% if forloop.counter <= 2 %} {# span_for_text will wrap the copy in s , which we'll use in the JS for this component #} diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index f0b2a140d..e5e260a5d 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -756,11 +756,8 @@ class DomainNameserversView(DomainFormBaseView): # Add existing nameservers as initial data initial_data.extend({"server": name, "ip": ",".join(ip)} for name, ip in nameservers) - # Ensure at least 3 fields, filled or empty + # Ensure 2 fields in the case we have no data if len(initial_data) == 0: - while len(initial_data) < 1: - initial_data.append({}) - else: initial_data.append({}) return initial_data From 51366871800f50d36e981d4b8c627ee0927c0473 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 20 Feb 2025 17:44:48 -0500 Subject: [PATCH 08/62] Remove nameserver code from old js --- .../assets/src/js/getgov/formset-forms.js | 137 +----------------- 1 file changed, 6 insertions(+), 131 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/formset-forms.js b/src/registrar/assets/src/js/getgov/formset-forms.js index 87fcb5a66..17ead9aeb 100644 --- a/src/registrar/assets/src/js/getgov/formset-forms.js +++ b/src/registrar/assets/src/js/getgov/formset-forms.js @@ -3,7 +3,7 @@ * We will call this on the forms init, and also every time we add a form * */ -function removeForm(e, formLabel, isNameserversForm, addButton, formIdentifier){ +function removeForm(e, formLabel, addButton, formIdentifier){ let totalForms = document.querySelector(`#id_${formIdentifier}-TOTAL_FORMS`); let formToRemove = e.target.closest(".repeatable-form"); formToRemove.remove(); @@ -38,48 +38,7 @@ function removeForm(e, formLabel, isNameserversForm, addButton, formIdentifier){ node.textContent = node.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`); node.textContent = node.textContent.replace(formExampleRegex, `ns${index + 1}`); } - - // If the node is a nameserver label, one of the first 2 which was previously 3 and up (not required) - // inject the USWDS required markup and make sure the INPUT is required - if (isNameserversForm && index <= 1 && node.innerHTML.includes('server') && !node.innerHTML.includes('*')) { - - // Remove the word optional - innerSpan.textContent = innerSpan.textContent.replace(/\s*\(\s*optional\s*\)\s*/, ''); - - // Create a new element - const newElement = document.createElement('abbr'); - newElement.textContent = '*'; - newElement.setAttribute("title", "required"); - newElement.classList.add("usa-hint", "usa-hint--required"); - - // Append the new element to the label - node.appendChild(newElement); - // Find the next sibling that is an input element - let nextInputElement = node.nextElementSibling; - - while (nextInputElement) { - if (nextInputElement.tagName === 'INPUT') { - // Found the next input element - nextInputElement.setAttribute("required", "") - break; - } - nextInputElement = nextInputElement.nextElementSibling; - } - nextInputElement.required = true; - } }); - - // Display the add more button if we have less than 13 forms - if (isNameserversForm && forms.length <= 13) { - addButton.removeAttribute("disabled"); - } - - if (isNameserversForm && forms.length < 3) { - // Hide the delete buttons on the remaining nameservers - Array.from(form.querySelectorAll('.delete-record')).forEach((deleteButton) => { - deleteButton.setAttribute("disabled", "true"); - }); - } }); } @@ -131,7 +90,6 @@ function markForm(e, formLabel){ */ function prepareNewDeleteButton(btn, formLabel) { let formIdentifier = "form" - let isNameserversForm = document.querySelector(".nameservers-form"); let isOtherContactsForm = document.querySelector(".other-contacts-form"); let addButton = document.querySelector("#add-form"); @@ -144,7 +102,7 @@ function prepareNewDeleteButton(btn, formLabel) { } else { // We will remove the forms and re-order the formset btn.addEventListener('click', function(e) { - removeForm(e, formLabel, isNameserversForm, addButton, formIdentifier); + removeForm(e, formLabel, addButton, formIdentifier); }); } } @@ -157,7 +115,6 @@ function prepareNewDeleteButton(btn, formLabel) { function prepareDeleteButtons(formLabel) { let formIdentifier = "form" let deleteButtons = document.querySelectorAll(".delete-record"); - let isNameserversForm = document.querySelector(".nameservers-form"); let isOtherContactsForm = document.querySelector(".other-contacts-form"); let addButton = document.querySelector("#add-form"); if (isOtherContactsForm) { @@ -174,7 +131,7 @@ function prepareDeleteButtons(formLabel) { } else { // We will remove the forms and re-order the formset deleteButton.addEventListener('click', function(e) { - removeForm(e, formLabel, isNameserversForm, addButton, formIdentifier); + removeForm(e, formLabel, addButton, formIdentifier); }); } }); @@ -214,24 +171,14 @@ export function initFormsetsForms() { let addButton = document.querySelector("#add-form"); let cloneIndex = 0; let formLabel = ''; - // remove nameservers - // clean up wherever nameservers are - let isNameserversForm = document.querySelector(".nameservers-form"); let isOtherContactsForm = document.querySelector(".other-contacts-form"); let isDsDataForm = document.querySelector(".ds-data-form"); let isDotgovDomain = document.querySelector(".dotgov-domain-form"); - // The Nameservers formset features 2 required and 11 optionals - // if not is other contactsform or dsdataform or isdotgovdomain - // remove nameservers form, start el if( !(isOtherContactsForm || isDotgovDomain || isDsDataForm) ){ - console.log("we reached inside the if statement") return } - if (isNameserversForm) { - // cloneInex = 2; - formLabel = "Name server"; // DNSSEC: DS Data - } else if (isDsDataForm) { + if (isDsDataForm) { formLabel = "DS data record"; // The Other Contacts form } else if (isOtherContactsForm) { @@ -243,12 +190,7 @@ export function initFormsetsForms() { } let totalForms = document.querySelector(`#id_${formIdentifier}-TOTAL_FORMS`); - // On load: Disable the add more button if we have 13 forms - if (isNameserversForm && document.querySelectorAll(".repeatable-form").length == 13) { - addButton.setAttribute("disabled", "true"); - } - - // Hide forms which have prevnniously been deleted + // Hide forms which have previously been deleted hideDeletedForms() // Attach click event listener on the delete buttons of the existing forms @@ -266,33 +208,6 @@ export function initFormsetsForms() { // For the eample on Nameservers let formExampleRegex = RegExp(`ns(\\d){1}`, 'g'); - // Some Nameserver form checks since the delete can mess up the source object we're copying - // in regards to required fields and hidden delete buttons - if (isNameserversForm) { - - // If the source element we're copying has required on an input, - // reset that input - let formRequiredNeedsCleanUp = newForm.innerHTML.includes('*'); - if (formRequiredNeedsCleanUp) { - newForm.querySelector('label abbr').remove(); - // Get all input elements within the container - const inputElements = newForm.querySelectorAll("input"); - // Loop through each input element and remove the 'required' attribute - inputElements.forEach((input) => { - if (input.hasAttribute("required")) { - input.removeAttribute("required"); - } - }); - } - - // If the source element we're copying has an disabled delete button, - // enable that button - let deleteButton= newForm.querySelector('.delete-record'); - if (deleteButton.hasAttribute("disabled")) { - deleteButton.removeAttribute("disabled"); - } - } - formNum++; newForm.innerHTML = newForm.innerHTML.replace(formNumberRegex, `${formIdentifier}-${formNum-1}-`); @@ -302,14 +217,7 @@ export function initFormsetsForms() { let totalShownForms = document.querySelectorAll(`.repeatable-form:not([style*="display: none"])`).length; newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${totalShownForms + 1}`); } else { - // Nameservers form is cloned from index 2 which has the word optional on init, does not have the word optional - // if indices 0 or 1 have been deleted - let containsOptional = newForm.innerHTML.includes('(optional)'); - if (isNameserversForm && !containsOptional) { - newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum} (optional)`); - } else { - newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum}`); - } + newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum}`); } newForm.innerHTML = newForm.innerHTML.replace(formExampleRegex, `ns${formNum}`); newForm.innerHTML = newForm.innerHTML.replace(/\n/g, ''); // Remove newline characters @@ -366,20 +274,6 @@ export function initFormsetsForms() { let newDeleteButton = newForm.querySelector(".delete-record"); if (newDeleteButton) prepareNewDeleteButton(newDeleteButton, formLabel); - - // Disable the add more button if we have 13 forms - if (isNameserversForm && formNum == 13) { - addButton.setAttribute("disabled", "true"); - } - - if (isNameserversForm && forms.length >= 2) { - // Enable the delete buttons on the nameservers - forms.forEach((form, index) => { - Array.from(form.querySelectorAll('.delete-record')).forEach((deleteButton) => { - deleteButton.removeAttribute("disabled"); - }); - }); - } } } @@ -405,22 +299,3 @@ export function triggerModalOnDsDataForm() { }, 50); } } - -/** - * Disable the delete buttons on nameserver forms on page load if < 3 forms - * - */ -export function nameserversFormListener() { - let isNameserversForm = document.querySelector(".nameservers-form"); - if (isNameserversForm) { - let forms = document.querySelectorAll(".repeatable-form"); - if (forms.length < 3) { - // Hide the delete buttons on the 2 nameservers - forms.forEach((form) => { - Array.from(form.querySelectorAll('.delete-record')).forEach((deleteButton) => { - deleteButton.setAttribute("disabled", "true"); - }); - }); - } - } -} From 686208116532d7b68a6d1c42cc48576502cc9f65 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 20 Feb 2025 20:44:04 -0500 Subject: [PATCH 09/62] add nameserver button --- .../src/js/getgov/domain-nameservers.js | 39 -- .../assets/src/js/getgov/form-nameservers.js | 22 ++ src/registrar/assets/src/js/getgov/main.js | 7 +- .../templates/domain_nameservers.html | 337 +++++++++--------- 4 files changed, 198 insertions(+), 207 deletions(-) delete mode 100644 src/registrar/assets/src/js/getgov/domain-nameservers.js create mode 100644 src/registrar/assets/src/js/getgov/form-nameservers.js diff --git a/src/registrar/assets/src/js/getgov/domain-nameservers.js b/src/registrar/assets/src/js/getgov/domain-nameservers.js deleted file mode 100644 index d59d55b32..000000000 --- a/src/registrar/assets/src/js/getgov/domain-nameservers.js +++ /dev/null @@ -1,39 +0,0 @@ - -function addForm(e, nameServerRows){ - let formspace = document.getElementsByClassName("nameservers-form"); - - function formTemplate(num) { - return ( - `
- -
Example: ns${num}.example.com
- - ` - ) - } - - - if(nameServerRows.length > 0){ - for(let i = 0; i < 1; i++){ - formspace.add(formTemplate(i + 1)) - } - } - else{ - formspace.add(formTemplate(nameServerRows.length + 1)) - } -} - -export function domainNameServers() { - let addButton = document.querySelector("#nameserver-add-form"); - let nameServerRows = document.querySelectorAll("nameserver-row"); - addButton.addEventListener('click', addForm(nameServerRows)); - -} - -// need a listener for save and cancel to hide the form when clicked -// add function to add rows to the table after submiting form \ No newline at end of file diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js new file mode 100644 index 000000000..74906686d --- /dev/null +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -0,0 +1,22 @@ +import { showElement, hideElement } from './helpers'; + +function handleAddForm(e) { + let nameserversForm = document.querySelector('.nameservers-form'); + if (!nameserversForm) { + console.warn('Expected DOM element but did not find it'); + return; + } + + showElement(nameserversForm); + + if (e?.target) { + hideElement(e.target); + } +} + +export function initFormNameservers() { + const addButton = document.getElementById('nameserver-add-form'); + if (!addButton) return; + + addButton.addEventListener('click', handleAddForm); +} diff --git a/src/registrar/assets/src/js/getgov/main.js b/src/registrar/assets/src/js/getgov/main.js index ecb6de4a7..637488187 100644 --- a/src/registrar/assets/src/js/getgov/main.js +++ b/src/registrar/assets/src/js/getgov/main.js @@ -1,6 +1,7 @@ -import { hookupYesNoListener, hookupRadioTogglerListener } from './radios.js'; +import { hookupYesNoListener } from './radios.js'; import { initDomainValidators } from './domain-validators.js'; -import { initFormsetsForms, triggerModalOnDsDataForm, nameserversFormListener } from './formset-forms.js'; +import { initFormsetsForms, triggerModalOnDsDataForm } from './formset-forms.js'; +import { initFormNameservers } from './form-nameservers' import { initializeUrbanizationToggle } from './urbanization.js'; import { userProfileListener, finishUserSetupListener } from './user-profile.js'; import { handleRequestingEntityFieldset } from './requesting-entity.js'; @@ -20,7 +21,7 @@ initDomainValidators(); initFormsetsForms(); triggerModalOnDsDataForm(); -//nameserversFormListener(); +initFormNameservers(); hookupYesNoListener("other_contacts-has_other_contacts",'other-employees', 'no-other-employees'); hookupYesNoListener("additional_details-has_anything_else_text",'anything-else', null); diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index a81cac242..11369ed59 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -47,35 +47,183 @@ {% if formset.initial and formset.forms.0.initial %} -
- {% csrf_token %} - {{ formset.management_form }} + + {% csrf_token %} + {{ formset.management_form }} -
+ - - - - - - - - - - - - {% for form in formset %} - {% if not forloop.last %} - - - - - - - - - - - - - {% endif %} - {% endfor %} - -
Your registered domains
Name ServersIP addressAction
{{ form.server.value }}{{ form.ip.value }} -
- - - - -
-
- -
- -
- -
-
- - - - {% else %} - -

Add name servers

-
- {% csrf_token %} - {{ formset.management_form }} - {% for form in formset %} -
-
-
- {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %} - {% if forloop.counter <= 2 %} - {# span_for_text will wrap the copy in s , which we'll use in the JS for this component #} - {% with attr_required=True add_group_class="usa-form-group--unstyled-error" span_for_text=True %} - {% input_with_errors form.server %} - {% endwith %} - {% else %} - {% with span_for_text=True %} - {% input_with_errors form.server %} - {% endwith %} - {% endif %} - {% endwith %} -
-
- {% with label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %} - {% input_with_errors form.ip %} - {% endwith %} -
-
- -
-
-
- {% endfor %} - {% comment %} Work around USWDS' button margins to add some spacing between the submit and the 'add more' - This solution still works when we remove the 'add more' at 13 forms {% endcomment %} -
- - - -
-
{% endif %} {% endblock %} {# domain_content #} From 5c4d1a811cae35ed6ac704fbbd9c68014a7bbd2e Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 20 Feb 2025 21:16:10 -0500 Subject: [PATCH 10/62] wip --- .../templates/domain_nameservers.html | 30 ++++++++++++++----- src/registrar/views/domain.py | 3 -- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 11369ed59..e70336c14 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -35,6 +35,7 @@

Name Servers

+ @@ -114,14 +115,14 @@ {{ form.ip.value }}
- - +
@@ -166,9 +167,24 @@ {{ form.server }} {{ form.ip }} - - - + + + + + + Delete +
@@ -232,7 +248,7 @@ class="usa-button" >Save - + +
+ +

Before your domain can be used we’ll need information about your domain name servers. Name server records indicate which DNS server is authoritative for your domain.

Add a name server record by clicking "Add name servers". You must add at least two name servers (13 max).

- {% include "includes/required_fields.html" %} - - {% if formset.initial and formset.forms.0.initial %} + + {% include "includes/required_fields.html" %}
{% csrf_token %} {{ formset.management_form }} - + @@ -115,7 +113,7 @@ - - + + - + @@ -225,18 +225,18 @@ {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %} {% if forloop.counter <= 2 %} {# span_for_text will wrap the copy in s , which we'll use in the JS for this component #} - {% with attr_required=True add_group_class="usa-form-group--unstyled-error" span_for_text=True %} + {% with attr_required=True add_initial_value_attr=True add_group_class="usa-form-group--unstyled-error" span_for_text=True %} {% input_with_errors form.server %} {% endwith %} {% else %} - {% with span_for_text=True %} + {% with span_for_text=True add_initial_value_attr=True %} {% input_with_errors form.server %} {% endwith %} {% endif %} {% endwith %}
- {% with attr_required=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %} + {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %} {% input_with_errors form.ip %} {% endwith %}
diff --git a/src/registrar/templatetags/field_helpers.py b/src/registrar/templatetags/field_helpers.py index 28a4d4556..c7389d3e3 100644 --- a/src/registrar/templatetags/field_helpers.py +++ b/src/registrar/templatetags/field_helpers.py @@ -173,6 +173,10 @@ def input_with_errors(context, field=None): # noqa: C901 if aria_labels: context["aria_label"] = " ".join(aria_labels) + # Conditionally add the data-initial-value attribute + if context.get("add_initial_value_attr", False): + attrs["data-initial-value"] = field.initial or "" + # ask Django to give us the widget dict # see Widget.get_context() on # https://docs.djangoproject.com/en/4.1/ref/forms/widgets From a527bd736a353d2cf90cb507eae4deaa6230b366 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 25 Feb 2025 21:04:40 -0500 Subject: [PATCH 16/62] added modals for unsaved changes and deletes --- .../assets/src/js/getgov/form-nameservers.js | 115 ++++++++++++++++-- src/registrar/forms/domain.py | 2 +- .../templates/domain_nameservers.html | 54 ++++++-- src/registrar/templates/includes/modal.html | 2 +- 4 files changed, 147 insertions(+), 26 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index fc67d3edc..94f8edf5f 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -5,10 +5,13 @@ export class NameserverForm { this.addNameserverButton = document.getElementById('nameserver-add-form'); this.nameserversForm = document.querySelector('.nameservers-form'); this.formChanged = false; + this.callback = null; // Bind event handlers to maintain 'this' context this.handleAddFormClick = this.handleAddFormClick.bind(this); this.handleEditClick = this.handleEditClick.bind(this); + this.handleDeleteClick = this.handleDeleteClick.bind(this); + this.handleDeleteKebabClick = this.handleDeleteKebabClick.bind(this); this.handleCancelClick = this.handleCancelClick.bind(this); } @@ -38,6 +41,7 @@ export class NameserverForm { editRows.forEach(editRow => { if (editRow.querySelector('.usa-input--error')) { const readOnlyRow = editRow.previousElementSibling; + this.formChanged = true; showElement(editRow); hideElement(readOnlyRow); } @@ -58,13 +62,52 @@ export class NameserverForm { cancelButton.addEventListener('click', this.handleCancelClick); }); + const deleteButtons = document.querySelectorAll('.nameserver-delete'); + deleteButtons.forEach(deleteButton => { + deleteButton.addEventListener('click', this.handleDeleteClick); + }); + + const deleteKebabButtons = document.querySelectorAll('.nameserver-delete-kebab'); + deleteKebabButtons.forEach(deleteKebabButton => { + deleteKebabButton.addEventListener('click', this.handleDeleteKebabClick); + }); + const textInputs = document.querySelectorAll("input[type='text']"); textInputs.forEach(input => { - input.addEventListener("input", function() { + input.addEventListener("input", () => { this.formChanged = true; - console.log("Form changed"); - }) - }) + }); + }); + + const unsaved_changes_modal = document.getElementById('unsaved-changes-modal'); + if (unsaved_changes_modal) { + const submitButton = document.getElementById('unsaved-changes-click-button'); + const closeButton = unsaved_changes_modal.querySelector('.usa-modal__close'); + submitButton.addEventListener('click', () => { + closeButton.click(); + this.executeCallback(); + }); + } + + const delete_modal = document.getElementById('delete-modal'); + if (delete_modal) { + const submitButton = document.getElementById('delete-click-button'); + const closeButton = delete_modal.querySelector('.usa-modal__close'); + submitButton.addEventListener('click', () => { + closeButton.click(); + this.executeCallback(); + }); + } + + } + + executeCallback() { + if (this.callback) { + this.callback(); + this.callback = null; + } else { + console.warn("No callback function set."); + } } handleAddFormClick(event) { @@ -80,17 +123,63 @@ export class NameserverForm { console.warn("Expected DOM element but did not find it"); return; } - // Check if any other edit row is currently visible and hide it - document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { - let correspondingReadOnlyRow = openEditRow.previousElementSibling; - hideElement(openEditRow); - showElement(correspondingReadOnlyRow); - }); - // hide and show rows as appropriate - hideElement(readOnlyRow); - showElement(editRow); + this.callback = () => { + // Check if any other edit row is currently visible and hide it + document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { + this.resetEditRowAndFormAndCollapseEditRow(openEditRow); + }); + // hide and show rows as appropriate + hideElement(readOnlyRow); + showElement(editRow); + }; + if (this.formChanged) { + //------- Show the confirmation modal + let modalTrigger = document.querySelector("#unsaved_changes_trigger"); + if (modalTrigger) { + modalTrigger.click(); + } + } else { + this.executeCallback(); + } } + handleDeleteClick(event) { + let deleteButton = event.target; + let editRow = deleteButton.closest('tr'); + if (!editRow) { + console.warn("Expected DOM element but did not find it"); + return; + } + this.deleteRow(editRow); + } + + handleDeleteKebabClick(event) { + let deleteKebabButton = event.target; + let readOnlyRow = deleteKebabButton.closest('tr'); // Find the closest row + let editRow = readOnlyRow.nextElementSibling; // Get the next row + if (!editRow) { + console.warn("Expected DOM element but did not find it"); + return; + } + this.deleteRow(editRow); + } + + deleteRow(editRow) { + this.callback = () => { + hideElement(editRow); + let textInputs = editRow.querySelectorAll("input[type='text']"); + textInputs.forEach(input => { + input.value = ""; + }); + document.querySelector("form").submit(); + }; + let modalTrigger = document.querySelector('#delete_trigger'); + if (modalTrigger) { + modalTrigger.click(); + } + } + + /** * Handles the click event for the cancel button within the table form. * diff --git a/src/registrar/forms/domain.py b/src/registrar/forms/domain.py index 05eb90db3..d0e228e0b 100644 --- a/src/registrar/forms/domain.py +++ b/src/registrar/forms/domain.py @@ -212,7 +212,7 @@ class BaseNameserverFormset(forms.BaseFormSet): # We need to make sure not to trigger the duplicate error in case the first and second nameservers # are empty. If there are enough records in the formset, that error is an unecessary blocker. # If there aren't, the required error will block the submit. - if value in data and not (form.cleaned_data.get("server", "").strip() == "" and index == 1): + if value in data and not (form.cleaned_data.get("server", "").strip() == ""): form.add_error( "server", NameserverError(code=nsErrorCodes.DUPLICATE_HOST, nameserver=value), diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index d547378df..d2d4ecb00 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -148,9 +148,10 @@
@@ -265,4 +265,36 @@ {% endif %} + + +
+ {% include 'includes/modal.html' with modal_heading="Are you sure you want to continue?" modal_description="You have unsaved changes that will be lost." modal_button_id="unsaved-changes-click-button" modal_button_text="Continue without saving" cancel_button_text="Go back" %} +
+ + +
+ {% include 'includes/modal.html' with modal_heading="Are you sure you want to delete this name server?" modal_description="This will delete the name server from your DNS records. This action cannot be undone." modal_button_id="delete-click-button" modal_button_text="Yes, delete name server" modal_button_class="usa-button--secondary" %} +
{% endblock %} {# domain_content #} diff --git a/src/registrar/templates/includes/modal.html b/src/registrar/templates/includes/modal.html index 8e3f45c44..af49d2b6c 100644 --- a/src/registrar/templates/includes/modal.html +++ b/src/registrar/templates/includes/modal.html @@ -75,7 +75,7 @@ class="usa-button usa-button--unstyled padding-105 text-center" data-close-modal > - Cancel + {% if cancel_button_text %}{{ cancel_button_text }}{% else %}Cancel{% endif %} {% endif %} From 9d22f9f64a26b1a0e1ab8089d3ed3737407e47c9 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 25 Feb 2025 22:20:26 -0500 Subject: [PATCH 17/62] edit, cancel and delete interactions --- .../assets/src/js/getgov/form-nameservers.js | 85 +++++++++++++++---- .../templates/domain_nameservers.html | 23 +++-- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index 94f8edf5f..ac1332ae3 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -13,6 +13,7 @@ export class NameserverForm { this.handleDeleteClick = this.handleDeleteClick.bind(this); this.handleDeleteKebabClick = this.handleDeleteKebabClick.bind(this); this.handleCancelClick = this.handleCancelClick.bind(this); + this.handleCancelAddFormClick = this.handleCancelAddFormClick.bind(this); } init() { @@ -30,7 +31,12 @@ export class NameserverForm { if (secondNameserver && !thirdNameserver && errorMessages.length > 0) { showElement(this.nameserversForm); - hideElement(this.addNameserverButton); + this.formChanged = true; + } + + if (this.nameserversForm.querySelector('.usa-input--error')) { + showElement(this.nameserversForm); + this.formChanged = true; } // handle display of table view errors @@ -62,6 +68,11 @@ export class NameserverForm { cancelButton.addEventListener('click', this.handleCancelClick); }); + const cancelAddFormButtons = document.querySelectorAll('.nameserver-cancel-add-form'); + cancelAddFormButtons.forEach(cancelAddFormButton => { + cancelAddFormButton.addEventListener('click', this.handleCancelAddFormClick); + }); + const deleteButtons = document.querySelectorAll('.nameserver-delete'); deleteButtons.forEach(deleteButton => { deleteButton.addEventListener('click', this.handleDeleteClick); @@ -111,8 +122,27 @@ export class NameserverForm { } handleAddFormClick(event) { - showElement(this.nameserversForm); - hideElement(this.addNameserverButton); + this.callback = () => { + // Check if any other edit row is currently visible and hide it + document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { + this.resetEditRowAndFormAndCollapseEditRow(openEditRow); + }); + // Check if this.nameserversForm is visible (i.e., does not have 'display-none') + if (!this.nameserversForm.classList.contains('display-none')) { + this.resetNameserversForm(); + } + // show nameservers form + showElement(this.nameserversForm); + }; + if (this.formChanged) { + //------- Show the confirmation modal + let modalTrigger = document.querySelector("#unsaved_changes_trigger"); + if (modalTrigger) { + modalTrigger.click(); + } + } else { + this.executeCallback(); + } } handleEditClick(event) { @@ -128,6 +158,10 @@ export class NameserverForm { document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { this.resetEditRowAndFormAndCollapseEditRow(openEditRow); }); + // Check if this.nameserversForm is visible (i.e., does not have 'display-none') + if (!this.nameserversForm.classList.contains('display-none')) { + this.resetNameserversForm(); + } // hide and show rows as appropriate hideElement(readOnlyRow); showElement(editRow); @@ -180,6 +214,10 @@ export class NameserverForm { } + handleCancelAddFormClick(event) { + this.resetNameserversForm(); + } + /** * Handles the click event for the cancel button within the table form. * @@ -207,11 +245,11 @@ export class NameserverForm { return; } // reset the values set in editRow - this.resetInputValuesInRow(editRow); + this.resetInputValuesInElement(editRow); // copy values from editRow to readOnlyRow this.copyEditRowToReadonlyRow(editRow, readOnlyRow); // remove errors from the editRow - this.removeErrorsFromRow(editRow); + this.removeErrorsFromElement(editRow); // remove errors from the entire form this.removeFormErrors(); // reset formChanged @@ -221,8 +259,25 @@ export class NameserverForm { showElement(readOnlyRow); } - resetInputValuesInRow(editRow) { - let textInputs = editRow.querySelectorAll("input[type='text']"); + resetNameserversForm() { + if (!this.nameserversForm) { + console.warn("Expected DOM element but did not find it"); + return; + } + // reset the values set in nameserversForm + this.resetInputValuesInElement(this.nameserversForm); + // remove errors from the nameserversForm + this.removeErrorsFromElement(this.nameserversForm); + // remove errors from the entire form + this.removeFormErrors(); + // reset formChanged + this.resetFormChanged(); + // hide the nameserversForm + hideElement(this.nameserversForm); + } + + resetInputValuesInElement(domElement) { + let textInputs = domElement.querySelectorAll("input[type='text']"); textInputs.forEach(input => { input.value = input.dataset.initialValue; }) @@ -243,24 +298,24 @@ export class NameserverForm { } } - removeErrorsFromRow(editRow) { - // remove class 'usa-form-group--error' from divs in editRow - editRow.querySelectorAll("div.usa-form-group--error").forEach(div => { + removeErrorsFromElement(domElement) { + // remove class 'usa-form-group--error' from divs in domElement + domElement.querySelectorAll("div.usa-form-group--error").forEach(div => { div.classList.remove("usa-form-group--error"); }); - // remove class 'usa-label--error' from labels in editRow - editRow.querySelectorAll("label.usa-label--error").forEach(label => { + // remove class 'usa-label--error' from labels in domElement + domElement.querySelectorAll("label.usa-label--error").forEach(label => { label.classList.remove("usa-label--error"); }); // Remove divs whose id ends with '__error-message' (error message divs) - editRow.querySelectorAll("div[id$='__error-message']").forEach(errorDiv => { + domElement.querySelectorAll("div[id$='__error-message']").forEach(errorDiv => { errorDiv.remove(); }); - // remove class 'usa-input--error' from inputs in editRow - editRow.querySelectorAll("input.usa-input--error").forEach(input => { + // remove class 'usa-input--error' from inputs in domElement + domElement.querySelectorAll("input.usa-input--error").forEach(input => { input.classList.remove("usa-input--error"); }); } diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index d2d4ecb00..f8713fa12 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -80,11 +80,11 @@
- -
{% for form in formset %} {% if not forloop.last %} + {{ form.domain }} @@ -218,6 +220,7 @@ {% csrf_token %} {{ formset.management_form }} {% for form in formset %} + {{ form.domain }}
From e392ffac4e4a4b150797575b17f53bdd5576d32e Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 26 Feb 2025 07:01:04 -0500 Subject: [PATCH 19/62] initialize smart nameservers --- .../assets/src/js/getgov/form-nameservers.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index ac1332ae3..57a24a30d 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -4,6 +4,7 @@ export class NameserverForm { constructor() { this.addNameserverButton = document.getElementById('nameserver-add-form'); this.nameserversForm = document.querySelector('.nameservers-form'); + this.domain = ''; this.formChanged = false; this.callback = null; @@ -22,6 +23,12 @@ export class NameserverForm { } initializeNameserverFormDisplay() { + + const domainName = document.getElementById('id_form-0-domain'); + if (domainName) { + this.domain = domainName.value; + } + // Check if exactly two nameserver forms exist: id_form-1-server is present but id_form-2-server is not const secondNameserver = document.getElementById('id_form-1-server'); const thirdNameserver = document.getElementById('id_form-2-server'); // This should not exist @@ -53,6 +60,23 @@ export class NameserverForm { } }) } + + // hide ip in forms unless nameserver ends with domain name + let formIndex = 0; + while (document.getElementById('id_form-' + formIndex + '-domain')) { + let serverInput = document.getElementById('id_form-' + formIndex + '-server'); + let ipInput = document.getElementById('id_form-' + formIndex + '-ip'); + if (serverInput && ipInput) { + let serverValue = serverInput.value.trim(); // Get the value and trim spaces + let ipParent = ipInput.parentElement; // Get the parent element of ipInput + + if (ipParent && !serverValue.endsWith('.' + this.domain)) { + hideElement(ipParent); // Hide the parent element of ipInput + } + } + formIndex++; + } + } initializeEventListeners() { From 4db7fe03e38ab6eb87d2ce2bed995ca85ba7e941 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 26 Feb 2025 07:24:58 -0500 Subject: [PATCH 20/62] nameserver forms are smart --- .../assets/src/js/getgov/form-nameservers.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index 57a24a30d..e128b768a 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -114,6 +114,29 @@ export class NameserverForm { }); }); + // Add a specific listener for 'id_form-{number}-server' inputs to make + // nameserver forms 'smart' + let formIndex = 0; + while (document.getElementById(`id_form-${formIndex}-server`)) { + let serverInput = document.getElementById(`id_form-${formIndex}-server`); + let ipInput = document.getElementById(`id_form-${formIndex}-ip`); + if (serverInput && ipInput) { + let ipParent = ipInput.parentElement; // Get the parent element of ipInput + serverInput.addEventListener("input", () => { + let serverValue = serverInput.value.trim(); + if (ipParent) { + if (serverValue.endsWith('.' + this.domain)) { + showElement(ipParent); // Show IP field if the condition matches + } else { + hideElement(ipParent); // Hide IP field otherwise + ipInput.value = ""; // Set the IP value to blank + } + } + }); + } + formIndex++; // Move to the next index + } + const unsaved_changes_modal = document.getElementById('unsaved-changes-modal'); if (unsaved_changes_modal) { const submitButton = document.getElementById('unsaved-changes-click-button'); From 3f84587a16d097a77acf18225acdd84c66f8ec04 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 26 Feb 2025 13:41:02 -0500 Subject: [PATCH 21/62] enabling support for refactoring 13 nameservers handling --- .../assets/src/js/getgov/form-nameservers.js | 85 ++++++++++--------- .../templates/domain_nameservers.html | 48 +++++------ 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index e128b768a..67eee34b7 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -3,7 +3,7 @@ import { showElement, hideElement } from './helpers'; export class NameserverForm { constructor() { this.addNameserverButton = document.getElementById('nameserver-add-form'); - this.nameserversForm = document.querySelector('.nameservers-form'); + this.addNameserversForm = document.querySelector('.add-nameservers-form'); this.domain = ''; this.formChanged = false; this.callback = null; @@ -36,13 +36,13 @@ export class NameserverForm { // Check if there are error messages in the form (indicated by elements with class 'usa-alert--error') const errorMessages = document.querySelectorAll('.usa-alert--error'); - if (secondNameserver && !thirdNameserver && errorMessages.length > 0) { - showElement(this.nameserversForm); + if (this.addNameserversForm && secondNameserver && !thirdNameserver && errorMessages.length > 0) { + showElement(this.addNameserversForm); this.formChanged = true; } - if (this.nameserversForm.querySelector('.usa-input--error')) { - showElement(this.nameserversForm); + if (this.addNameserversForm && this.addNameserversForm.querySelector('.usa-input--error')) { + showElement(this.addNameserversForm); this.formChanged = true; } @@ -169,26 +169,31 @@ export class NameserverForm { } handleAddFormClick(event) { - this.callback = () => { - // Check if any other edit row is currently visible and hide it - document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { - this.resetEditRowAndFormAndCollapseEditRow(openEditRow); - }); - // Check if this.nameserversForm is visible (i.e., does not have 'display-none') - if (!this.nameserversForm.classList.contains('display-none')) { - this.resetNameserversForm(); - } - // show nameservers form - showElement(this.nameserversForm); - }; - if (this.formChanged) { - //------- Show the confirmation modal - let modalTrigger = document.querySelector("#unsaved_changes_trigger"); - if (modalTrigger) { - modalTrigger.click(); + if (this.addNameserversForm) { + this.callback = () => { + // Check if any other edit row is currently visible and hide it + document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { + this.resetEditRowAndFormAndCollapseEditRow(openEditRow); + }); + // Check if this.addNameserversForm is visible (i.e., does not have 'display-none') + if (!this.addNameserversForm.classList.contains('display-none')) { + this.resetAddNameserversForm(); + } + // show nameservers form + showElement(this.addNameserversForm); + }; + if (this.formChanged) { + //------- Show the confirmation modal + let modalTrigger = document.querySelector("#unsaved_changes_trigger"); + if (modalTrigger) { + modalTrigger.click(); + } + } else { + this.executeCallback(); } } else { - this.executeCallback(); + // this indicates there are already 13 nameservers and we need to display an error message + console.warn("There are 13 nameservers"); } } @@ -205,9 +210,9 @@ export class NameserverForm { document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { this.resetEditRowAndFormAndCollapseEditRow(openEditRow); }); - // Check if this.nameserversForm is visible (i.e., does not have 'display-none') - if (!this.nameserversForm.classList.contains('display-none')) { - this.resetNameserversForm(); + // Check if this.addNameserversForm is visible (i.e., does not have 'display-none') + if (this.addNameserversForm && !this.addNameserversForm.classList.contains('display-none')) { + this.resetAddNameserversForm(); } // hide and show rows as appropriate hideElement(readOnlyRow); @@ -262,7 +267,7 @@ export class NameserverForm { handleCancelAddFormClick(event) { - this.resetNameserversForm(); + this.resetAddNameserversForm(); } /** @@ -306,21 +311,19 @@ export class NameserverForm { showElement(readOnlyRow); } - resetNameserversForm() { - if (!this.nameserversForm) { - console.warn("Expected DOM element but did not find it"); - return; + resetAddNameserversForm() { + if (this.addNameserversForm) { + // reset the values set in addNameserversForm + this.resetInputValuesInElement(this.addNameserversForm); + // remove errors from the addNameserversForm + this.removeErrorsFromElement(this.addNameserversForm); + // remove errors from the entire form + this.removeFormErrors(); + // reset formChanged + this.resetFormChanged(); + // hide the addNameserversForm + hideElement(this.addNameserversForm); } - // reset the values set in nameserversForm - this.resetInputValuesInElement(this.nameserversForm); - // remove errors from the nameserversForm - this.removeErrorsFromElement(this.nameserversForm); - // remove errors from the entire form - this.removeFormErrors(); - // reset formChanged - this.resetFormChanged(); - // hide the nameserversForm - hideElement(this.nameserversForm); } resetInputValuesInElement(domElement) { diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index cd89c647b..7499daa82 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -38,7 +38,7 @@
-
@@ -54,9 +54,9 @@ {% csrf_token %} {{ formset.management_form }} -
- - {% endif %} - {% endfor %} - -
- - -
- +
+ + +
+ + {% endif %} + {% endfor %}
{{ form.ip.value }}
-
{{ form.server.value }}
@@ -107,7 +105,7 @@ {% for form in formset %} - {% if not forloop.last %} + {% if forloop.counter == 13 or not forloop.last %} {{ form.domain }} @@ -213,7 +211,7 @@ {% endcomment %} - {% for form in formset %} - {% if forloop.counter == 13 or not forloop.last %} + {% if not forloop.last or form.initial %} {{ form.domain }} From 69f8b604f879e3cb88f04540565f8cbdeb2279c5 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 27 Feb 2025 13:51:03 -0500 Subject: [PATCH 23/62] fix bug in smart form in table view --- src/registrar/templates/domain_nameservers.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 5d47defa4..124a206da 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -117,13 +117,13 @@ - Edit {{ form.server }} + Edit {{ form.server.value }} IP address @@ -109,8 +109,7 @@ {{ form.domain }} - - + {% for form in formset %} {% if not forloop.last or form.initial %} + + {% comment %} + This section renders table rows for each existing nameserver. Two rows are rendered, a readonly row + and an edit row. Only one of which is displayed at a time. + {% endcomment %} + {{ form.domain }} @@ -205,10 +226,9 @@ {% else %} {% comment %} - No Nameservers. - We use the double-decker form + This section renders Add New Nameservers form which renders when there are no existing + nameservers defined on the domain. {% endcomment %} - - + From be11fafe83d0ec9923cfa55a1716a85d60da2c88 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 4 Mar 2025 10:22:49 -0500 Subject: [PATCH 33/62] make delete button red --- src/registrar/templates/domain_nameservers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 94d8be323..09a337e20 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -207,7 +207,7 @@
Action
{{ form.server.value }}{{ form.ip.value }}{{ form.server.value }} {% if form.ip.value %}({{ form.ip.value }}){% endif %}
Name Servers IP addressActionAction
+
From a4e229279800f6b24fef8e31f90ea7f227177131 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 4 Mar 2025 14:05:32 -0500 Subject: [PATCH 40/62] refactored the js --- .../assets/src/js/getgov/domain-dnssec.js | 2 +- .../assets/src/js/getgov/domain-dsdata.js | 2 +- .../assets/src/js/getgov/domain-managers.js | 2 +- .../src/js/getgov/domain-request-form.js | 2 +- .../assets/src/js/getgov/form-helpers.js | 57 +++++++++++++++++ .../assets/src/js/getgov/form-nameservers.js | 62 ++++--------------- 6 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 src/registrar/assets/src/js/getgov/form-helpers.js diff --git a/src/registrar/assets/src/js/getgov/domain-dnssec.js b/src/registrar/assets/src/js/getgov/domain-dnssec.js index 860359fe0..0d6ae4970 100644 --- a/src/registrar/assets/src/js/getgov/domain-dnssec.js +++ b/src/registrar/assets/src/js/getgov/domain-dnssec.js @@ -1,4 +1,4 @@ -import { submitForm } from './helpers.js'; +import { submitForm } from './form-helpers.js'; export function initDomainDNSSEC() { document.addEventListener('DOMContentLoaded', function() { diff --git a/src/registrar/assets/src/js/getgov/domain-dsdata.js b/src/registrar/assets/src/js/getgov/domain-dsdata.js index 7c0871bec..14132d812 100644 --- a/src/registrar/assets/src/js/getgov/domain-dsdata.js +++ b/src/registrar/assets/src/js/getgov/domain-dsdata.js @@ -1,4 +1,4 @@ -import { submitForm } from './helpers.js'; +import { submitForm } from './form-helpers.js'; export function initDomainDSData() { document.addEventListener('DOMContentLoaded', function() { diff --git a/src/registrar/assets/src/js/getgov/domain-managers.js b/src/registrar/assets/src/js/getgov/domain-managers.js index 26eccd8cd..3d77b7cca 100644 --- a/src/registrar/assets/src/js/getgov/domain-managers.js +++ b/src/registrar/assets/src/js/getgov/domain-managers.js @@ -1,4 +1,4 @@ -import { submitForm } from './helpers.js'; +import { submitForm } from './form-helpers.js'; export function initDomainManagersPage() { document.addEventListener('DOMContentLoaded', function() { diff --git a/src/registrar/assets/src/js/getgov/domain-request-form.js b/src/registrar/assets/src/js/getgov/domain-request-form.js index b49912fa4..73bb6accd 100644 --- a/src/registrar/assets/src/js/getgov/domain-request-form.js +++ b/src/registrar/assets/src/js/getgov/domain-request-form.js @@ -1,4 +1,4 @@ -import { submitForm } from './helpers.js'; +import { submitForm } from './form-helpers.js'; export function initDomainRequestForm() { document.addEventListener('DOMContentLoaded', function() { diff --git a/src/registrar/assets/src/js/getgov/form-helpers.js b/src/registrar/assets/src/js/getgov/form-helpers.js new file mode 100644 index 000000000..fabfab98a --- /dev/null +++ b/src/registrar/assets/src/js/getgov/form-helpers.js @@ -0,0 +1,57 @@ +/** + * Helper function to submit a form + * @param {} form_id - the id of the form to be submitted + */ +export function submitForm(form_id) { + let form = document.getElementById(form_id); + if (form) { + form.submit(); + } else { + console.error("Form '" + form_id + "' not found."); + } +} + + +/** + * Removes all error-related classes and messages from the specified DOM element. + * This method cleans up validation errors by removing error highlighting from input fields, + * labels, and form groups, as well as deleting error message elements. + * @param {HTMLElement} domElement - The parent element within which errors should be cleared. + */ +export function removeErrorsFromElement(domElement) { + // Remove the 'usa-form-group--error' class from all div elements + domElement.querySelectorAll("div.usa-form-group--error").forEach(div => { + div.classList.remove("usa-form-group--error"); + }); + + // Remove the 'usa-label--error' class from all label elements + domElement.querySelectorAll("label.usa-label--error").forEach(label => { + label.classList.remove("usa-label--error"); + }); + + // Remove all error message divs whose ID ends with '__error-message' + domElement.querySelectorAll("div[id$='__error-message']").forEach(errorDiv => { + errorDiv.remove(); + }); + + // Remove the 'usa-input--error' class from all input elements + domElement.querySelectorAll("input.usa-input--error").forEach(input => { + input.classList.remove("usa-input--error"); + }); +} + +/** + * Removes all form-level error messages displayed in the UI. + * The form error messages are contained within div elements with the ID 'form-errors'. + * Since multiple elements with the same ID may exist (even though not syntactically correct), + * this function removes them iteratively. + */ +export function removeFormErrors() { + let formErrorDiv = document.getElementById("form-errors"); + + // Recursively remove all instances of form error divs + while (formErrorDiv) { + formErrorDiv.remove(); + formErrorDiv = document.getElementById("form-errors"); + } +} \ No newline at end of file diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index e45d43f6a..cec8bcefb 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -1,4 +1,5 @@ import { showElement, hideElement, scrollToElement } from './helpers'; +import { removeErrorsFromElement, removeFormErrors } from './form-helpers'; export class NameserverForm { constructor() { @@ -46,11 +47,17 @@ export class NameserverForm { // Check if there are error messages in the form (indicated by elements with class 'usa-alert--error') const errorMessages = document.querySelectorAll('.usa-alert--error'); + // This check indicates that there are exactly two forms (which is the case for the Add New Nameservers form) + // and there is at least one error in the form. In this case, show the Add New Nameservers form, and + // indicate that the form has changed if (this.addNameserversForm && secondNameserver && !thirdNameserver && errorMessages.length > 0) { showElement(this.addNameserversForm); this.formChanged = true; } + // This check indicates that there is either an Add New Nameservers form or an Add New Nameserver form + // and that form has errors in it. In this case, show the form, and indicate that the form has + // changed. if (this.addNameserversForm && this.addNameserversForm.querySelector('.usa-input--error')) { showElement(this.addNameserversForm); this.formChanged = true; @@ -135,6 +142,8 @@ export class NameserverForm { let ipInput = document.getElementById(`id_form-${formIndex}-ip`); if (serverInput && ipInput) { let ipParent = ipInput.parentElement; // Get the parent element of ipInput + // add an event listener on the server input that adjusts visibility + // and value of the ip input (and its parent) serverInput.addEventListener("input", () => { let serverValue = serverInput.value.trim(); if (ipParent) { @@ -363,9 +372,9 @@ export class NameserverForm { // copy values from editRow to readOnlyRow this.copyEditRowToReadonlyRow(editRow, readOnlyRow); // remove errors from the editRow - this.removeErrorsFromElement(editRow); + removeErrorsFromElement(editRow); // remove errors from the entire form - this.removeFormErrors(); + removeFormErrors(); // reset formChanged this.resetFormChanged(); // hide and show rows as appropriate @@ -382,9 +391,9 @@ export class NameserverForm { // reset the values set in addNameserversForm this.resetInputValuesInElement(this.addNameserversForm); // remove errors from the addNameserversForm - this.removeErrorsFromElement(this.addNameserversForm); + removeErrorsFromElement(this.addNameserversForm); // remove errors from the entire form - this.removeFormErrors(); + removeFormErrors(); // reset formChanged this.resetFormChanged(); // hide the addNameserversForm @@ -435,51 +444,6 @@ export class NameserverForm { } } - /** - * Removes all error-related classes and messages from the specified DOM element. - * This method cleans up validation errors by removing error highlighting from input fields, - * labels, and form groups, as well as deleting error message elements. - * @param {HTMLElement} domElement - The parent element within which errors should be cleared. - */ - removeErrorsFromElement(domElement) { - // Remove the 'usa-form-group--error' class from all div elements - domElement.querySelectorAll("div.usa-form-group--error").forEach(div => { - div.classList.remove("usa-form-group--error"); - }); - - // Remove the 'usa-label--error' class from all label elements - domElement.querySelectorAll("label.usa-label--error").forEach(label => { - label.classList.remove("usa-label--error"); - }); - - // Remove all error message divs whose ID ends with '__error-message' - domElement.querySelectorAll("div[id$='__error-message']").forEach(errorDiv => { - errorDiv.remove(); - }); - - // Remove the 'usa-input--error' class from all input elements - domElement.querySelectorAll("input.usa-input--error").forEach(input => { - input.classList.remove("usa-input--error"); - }); - } - - /** - * Removes all form-level error messages displayed in the UI. - * The form error messages are contained within div elements with the ID 'form-errors'. - * Since multiple elements with the same ID may exist (even though not syntactically correct), - * this function removes them iteratively. - */ - removeFormErrors() { - let formErrorDiv = document.getElementById("form-errors"); - - // Recursively remove all instances of form error divs - while (formErrorDiv) { - formErrorDiv.remove(); - formErrorDiv = document.getElementById("form-errors"); - } - } - - /** * Resets the form change state. * This method marks the form as unchanged by setting `formChanged` to false. From d9cd4aeb4d1bcf0f4927cfaf9e574f6d9fe84230 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 4 Mar 2025 14:16:48 -0500 Subject: [PATCH 41/62] refactored the js --- .../assets/src/js/getgov/form-nameservers.js | 6 ++++-- src/registrar/assets/src/js/getgov/helpers.js | 13 ------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index cec8bcefb..2cf1fc106 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -458,10 +458,12 @@ export class NameserverForm { * This ensures that only the latest alert is displayed to the user. */ resetAlerts() { - const mainContent = document.querySelector("main#main-content"); + const mainContent = document.getElementById("main-content"); if (mainContent) { // Remove all alert elements within the main content area mainContent.querySelectorAll(".usa-alert").forEach(alert => alert.remove()); + } else { + console.warn("Expecting main-content DOM element"); } } @@ -474,7 +476,7 @@ export class NameserverForm { addAlert(level, message) { this.resetAlerts(); // Remove any existing alerts before adding a new one - const mainContent = document.querySelector("main#main-content"); + const mainContent = document.getElementById("main-content"); if (!mainContent) return; // Create a new alert div with appropriate classes based on alert level diff --git a/src/registrar/assets/src/js/getgov/helpers.js b/src/registrar/assets/src/js/getgov/helpers.js index 08be011c2..80a9fce1f 100644 --- a/src/registrar/assets/src/js/getgov/helpers.js +++ b/src/registrar/assets/src/js/getgov/helpers.js @@ -84,19 +84,6 @@ export function getCsrfToken() { return document.querySelector('input[name="csrfmiddlewaretoken"]').value; } -/** - * Helper function to submit a form - * @param {} form_id - the id of the form to be submitted - */ -export function submitForm(form_id) { - let form = document.getElementById(form_id); - if (form) { - form.submit(); - } else { - console.error("Form '" + form_id + "' not found."); - } -} - /** * Helper function to strip HTML tags * THIS IS NOT SUITABLE FOR SANITIZING DANGEROUS STRINGS From f537fa37aca2921db2c5055dcc38ffc24fc0ca0b Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 4 Mar 2025 14:29:25 -0500 Subject: [PATCH 42/62] fixed aria-label on kebab --- src/registrar/templates/domain_nameservers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 23f5209b2..7647f5a70 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -158,7 +158,7 @@ class="usa-button usa-button--unstyled usa-button--with-icon usa-accordion__button usa-button--more-actions margin-top-0" aria-expanded="false" aria-controls="more-actions-{{ form.server.value }}" - aria-label="" + aria-label="More Actions for ({{ form.server.value }})" >
{% for error in form.non_field_errors %} -
- + From a9970bcd5be2d58cf0ac71eacf1c292aa78b64eb Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 5 Mar 2025 17:31:14 -0500 Subject: [PATCH 48/62] fix form margins --- src/registrar/templates/domain_nameservers.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 0e64bccdb..610477b3d 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -78,13 +78,13 @@
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %} - {% with attr_required=True span_for_text=True add_initial_value_attr=True %} + {% with attr_required=True span_for_text=True add_initial_value_attr=True add_group_class="margin-top-2" %} {% input_with_errors form.server %} {% endwith %} {% endwith %}
- {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %} + {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-2" %} {% input_with_errors form.ip %} {% endwith %}
@@ -191,7 +191,7 @@ {% endwith %}
@@ -241,7 +241,7 @@
- {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %} + {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" add_group_class="margin-top-2" %} {% if forloop.counter <= 2 %} {# span_for_text will wrap the copy in s , which we'll use in the JS for this component #} {% with attr_required=True add_initial_value_attr=True span_for_text=True %} @@ -255,7 +255,7 @@ {% endwith %}
- {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %} + {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-2" %} {% input_with_errors form.ip %} {% endwith %}
From b96be921ea583400a99e0569a3d1f5945bb0cd3b Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 5 Mar 2025 18:56:29 -0500 Subject: [PATCH 49/62] unstyle errors in add forms --- src/registrar/templates/domain_nameservers.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 610477b3d..5863e9a6c 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -78,13 +78,13 @@
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %} - {% with attr_required=True span_for_text=True add_initial_value_attr=True add_group_class="margin-top-2" %} + {% with attr_required=True span_for_text=True add_initial_value_attr=True add_group_class="usa-form-group--unstyled-error margin-top-2" %} {% input_with_errors form.server %} {% endwith %} {% endwith %}
- {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-2" %} + {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="usa-form-group--unstyled-error margin-top-2" %} {% input_with_errors form.ip %} {% endwith %}
@@ -241,7 +241,7 @@
- {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" add_group_class="margin-top-2" %} + {% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" add_group_class="usa-form-group--unstyled-error margin-top-2" %} {% if forloop.counter <= 2 %} {# span_for_text will wrap the copy in s , which we'll use in the JS for this component #} {% with attr_required=True add_initial_value_attr=True span_for_text=True %} @@ -255,7 +255,7 @@ {% endwith %}
- {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-2" %} + {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="usa-form-group--unstyled-error margin-top-2" %} {% input_with_errors form.ip %} {% endwith %}
From 3e100d28c3cf99a2aa9afb2064d115d875341c96 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 5 Mar 2025 19:23:34 -0500 Subject: [PATCH 50/62] console logs for dev --- src/registrar/assets/src/js/getgov/form-nameservers.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index 49ad9d691..f72ba116b 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -188,6 +188,7 @@ export class NameserverForm { */ executeCallback() { if (this.callback) { + console.log("callback") this.callback(); this.callback = null; } else { @@ -205,6 +206,7 @@ export class NameserverForm { document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { this.resetEditRowAndFormAndCollapseEditRow(openEditRow); }); + console.log("this.addNameserversForm " + this.addNameserversForm); if (this.addNameserversForm) { // Check if this.addNameserversForm is visible (i.e., does not have 'display-none') if (!this.addNameserversForm.classList.contains('display-none')) { @@ -217,6 +219,7 @@ export class NameserverForm { } }; if (this.formChanged) { + console.log("this.formChanged") //------- Show the unsaved changes confirmation modal let modalTrigger = document.querySelector("#unsaved_changes_trigger"); if (modalTrigger) { From 636fea2d99afa61d572181ca7c4722d8f6c78da4 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 5 Mar 2025 19:43:12 -0500 Subject: [PATCH 51/62] reduce margin bottom on h1 --- src/registrar/assets/src/js/getgov/form-nameservers.js | 3 --- src/registrar/templates/domain_nameservers.html | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/registrar/assets/src/js/getgov/form-nameservers.js b/src/registrar/assets/src/js/getgov/form-nameservers.js index f72ba116b..49ad9d691 100644 --- a/src/registrar/assets/src/js/getgov/form-nameservers.js +++ b/src/registrar/assets/src/js/getgov/form-nameservers.js @@ -188,7 +188,6 @@ export class NameserverForm { */ executeCallback() { if (this.callback) { - console.log("callback") this.callback(); this.callback = null; } else { @@ -206,7 +205,6 @@ export class NameserverForm { document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => { this.resetEditRowAndFormAndCollapseEditRow(openEditRow); }); - console.log("this.addNameserversForm " + this.addNameserversForm); if (this.addNameserversForm) { // Check if this.addNameserversForm is visible (i.e., does not have 'display-none') if (!this.addNameserversForm.classList.contains('display-none')) { @@ -219,7 +217,6 @@ export class NameserverForm { } }; if (this.formChanged) { - console.log("this.formChanged") //------- Show the unsaved changes confirmation modal let modalTrigger = document.querySelector("#unsaved_changes_trigger"); if (modalTrigger) { diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 5863e9a6c..4b2571d6b 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -34,7 +34,7 @@
-

Name servers

+

Name servers

From c8925b733b6ca2db6fdd7967fe7ab7848d3d7bc0 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 5 Mar 2025 19:52:14 -0500 Subject: [PATCH 52/62] h1 and table last column margin, padding --- src/registrar/assets/src/sass/_theme/_tables.scss | 5 +++++ src/registrar/templates/domain_nameservers.html | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/registrar/assets/src/sass/_theme/_tables.scss b/src/registrar/assets/src/sass/_theme/_tables.scss index 222f44fcc..509bdc573 100644 --- a/src/registrar/assets/src/sass/_theme/_tables.scss +++ b/src/registrar/assets/src/sass/_theme/_tables.scss @@ -11,6 +11,11 @@ th { border: none; } + td.padding-right-0, + th.padding-right-0 { + padding-right: 0; + } + tr:first-child th:first-child { border-top: none; } diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 4b2571d6b..3e0fdb2fa 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -115,7 +115,7 @@
- + @@ -131,7 +131,7 @@ - - - - - - From d6e665d3786e8795d9ad601bd40e563c4a387425 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 6 Mar 2025 20:47:05 -0500 Subject: [PATCH 59/62] minh for form rows --- src/registrar/assets/src/sass/_theme/_base.scss | 4 ++++ src/registrar/templates/domain_nameservers.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/registrar/assets/src/sass/_theme/_base.scss b/src/registrar/assets/src/sass/_theme/_base.scss index 1f23223a5..71894ce59 100644 --- a/src/registrar/assets/src/sass/_theme/_base.scss +++ b/src/registrar/assets/src/sass/_theme/_base.scss @@ -293,3 +293,7 @@ Fit-content itself does not work. .width-40p { width: 40%; } + +.minh-143px { + min-height: 143px; +} diff --git a/src/registrar/templates/domain_nameservers.html b/src/registrar/templates/domain_nameservers.html index 3f0236486..d3a9edab5 100644 --- a/src/registrar/templates/domain_nameservers.html +++ b/src/registrar/templates/domain_nameservers.html @@ -85,7 +85,7 @@
Your registered domains
Your registered domains
Name ServersName servers IP address Action
- {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-0" %} + {% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-0" %} {% input_with_errors form.ip %} {% endwith %}
Name servers IP addressActionAction
{{ form.server.value }} {% if form.ip.value %}({{ form.ip.value }}){% endif %} +
+