mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-03 08:22:18 +02:00
Slight markup change and some JS to allow for deleting ns 1 and 2 when there are enough records in the formset
This commit is contained in:
parent
4fdbb23141
commit
d07f7b614b
4 changed files with 109 additions and 44 deletions
|
@ -256,7 +256,7 @@ function prepareDeleteButtons(formLabel) {
|
|||
|
||||
let formNumberRegex = RegExp(`form-(\\d){1}-`, 'g');
|
||||
let formLabelRegex = RegExp(`${formLabel} (\\d+){1}`, 'g');
|
||||
// For the eample on Nameservers
|
||||
// For the example on Nameservers
|
||||
let formExampleRegex = RegExp(`ns(\\d+){1}`, 'g');
|
||||
|
||||
forms.forEach((form, index) => {
|
||||
|
@ -275,31 +275,35 @@ function prepareDeleteButtons(formLabel) {
|
|||
// h2 and legend for DS form, label for nameservers
|
||||
Array.from(form.querySelectorAll('h2, legend, label, p')).forEach((node) => {
|
||||
|
||||
// Ticket: 1192
|
||||
// if (isNameserversForm && index <= 1 && !node.innerHTML.includes('*')) {
|
||||
// // Create a new element
|
||||
// const newElement = document.createElement('abbr');
|
||||
// newElement.textContent = '*';
|
||||
// // TODO: finish building abbr
|
||||
// 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('*')) {
|
||||
// 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 parent
|
||||
// node.appendChild(newElement);
|
||||
// // Find the next sibling that is an input element
|
||||
// let nextInputElement = node.nextElementSibling;
|
||||
// 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
|
||||
// console.log(nextInputElement);
|
||||
// break;
|
||||
// }
|
||||
// nextInputElement = nextInputElement.nextElementSibling;
|
||||
// }
|
||||
// nextInputElement.required = true;
|
||||
// }
|
||||
while (nextInputElement) {
|
||||
if (nextInputElement.tagName === 'INPUT') {
|
||||
// Found the next input element
|
||||
nextInputElement.setAttribute("required", "")
|
||||
break;
|
||||
}
|
||||
nextInputElement = nextInputElement.nextElementSibling;
|
||||
}
|
||||
nextInputElement.required = true;
|
||||
}
|
||||
|
||||
// Ticket: 1192 - remove if
|
||||
if (!(isNameserversForm && index <= 1)) {
|
||||
let innerSpan = node.querySelector('span')
|
||||
if (innerSpan) {
|
||||
innerSpan.textContent = innerSpan.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`);
|
||||
} else {
|
||||
node.textContent = node.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`);
|
||||
node.textContent = node.textContent.replace(formExampleRegex, `ns${index + 1}`);
|
||||
}
|
||||
|
@ -309,6 +313,13 @@ function prepareDeleteButtons(formLabel) {
|
|||
if (isNameserversForm && forms.length <= 13) {
|
||||
addButton.classList.remove("display-none")
|
||||
}
|
||||
|
||||
if (isNameserversForm && forms.length < 3) {
|
||||
// Hide the delete buttons on the remaining nameservers
|
||||
Array.from(form.querySelectorAll('.delete-record')).forEach((deleteButton) => {
|
||||
deleteButton.classList.add("display-none");
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -351,6 +362,33 @@ function prepareDeleteButtons(formLabel) {
|
|||
// 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 fileds 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 invisible delete button,
|
||||
// show that button
|
||||
let deleteButtonNeedsCleanUp = newForm.querySelector('.delete-record').classList.contains("display-none");
|
||||
if (deleteButtonNeedsCleanUp) {
|
||||
newForm.querySelector('.delete-record').classList.remove("display-none");
|
||||
}
|
||||
}
|
||||
|
||||
formNum++;
|
||||
newForm.innerHTML = newForm.innerHTML.replace(formNumberRegex, `form-${formNum-1}-`);
|
||||
newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum}`);
|
||||
|
@ -404,6 +442,15 @@ function prepareDeleteButtons(formLabel) {
|
|||
if (isNameserversForm && formNum == 13) {
|
||||
addButton.classList.add("display-none")
|
||||
}
|
||||
|
||||
if (isNameserversForm && forms.length >= 2) {
|
||||
// Show the delete buttons on the nameservers
|
||||
forms.forEach((form, index) => {
|
||||
Array.from(form.querySelectorAll('.delete-record')).forEach((deleteButton) => {
|
||||
deleteButton.classList.remove("display-none");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
"""Forms for domain management."""
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
from django import forms
|
||||
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator
|
||||
from django.forms import formset_factory
|
||||
from django.forms.utils import ErrorList
|
||||
|
||||
from phonenumber_field.widgets import RegionalPhoneNumberWidget
|
||||
from registrar.utility.errors import (
|
||||
|
@ -23,20 +26,31 @@ class DomainAddUserForm(forms.Form):
|
|||
email = forms.EmailField(label="Email")
|
||||
|
||||
|
||||
class IPAddressField(forms.CharField):
|
||||
def validate(self, value):
|
||||
super().validate(value) # Run the default CharField validation
|
||||
|
||||
|
||||
class DomainNameserverForm(forms.Form):
|
||||
"""Form for changing nameservers."""
|
||||
|
||||
domain = forms.CharField(widget=forms.HiddenInput, required=False)
|
||||
|
||||
server = forms.CharField(label="Name server", strip=True)
|
||||
server = forms.CharField(
|
||||
label="Name server",
|
||||
strip=True
|
||||
|
||||
)
|
||||
|
||||
ip = forms.CharField(label="IP Address (IPv4 or IPv6)", strip=True, required=False)
|
||||
ip = forms.CharField(
|
||||
label="IP Address (IPv4 or IPv6)",
|
||||
strip=True,
|
||||
required=False,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DomainNameserverForm, self).__init__(*args, **kwargs)
|
||||
|
||||
# add custom error messages
|
||||
self.fields['server'].error_messages.update({
|
||||
'required': 'A minimum of 2 Name Servers are required.',
|
||||
})
|
||||
|
||||
def clean(self):
|
||||
# clean is called from clean_forms, which is called from is_valid
|
||||
# after clean_fields. it is used to determine form level errors.
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
|
||||
{% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
|
||||
>
|
||||
{{ field.label }}
|
||||
{% if widget.attrs.required %}
|
||||
<abbr class="usa-hint usa-hint--required" title="required">*</abbr>
|
||||
{% endif %}
|
||||
{% if span_for_text %}
|
||||
<span>{{ field.label }}</span>
|
||||
{% else %}
|
||||
{{ field.label }}
|
||||
{% endif %}
|
||||
{% if widget.attrs.required %}
|
||||
<abbr class="usa-hint usa-hint--required" title="required">*</abbr>
|
||||
{% endif %}
|
||||
</{{ label_tag }}>
|
||||
|
|
|
@ -35,11 +35,14 @@
|
|||
{{ form.domain }}
|
||||
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
||||
{% if forloop.counter <= 2 %}
|
||||
{% with attr_required=True add_group_class="usa-form-group--unstyled-error" %}
|
||||
{# span_for_text will wrap the copy in s <span>, 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 %}
|
||||
{% input_with_errors form.server %}
|
||||
{% with span_for_text=True %}
|
||||
{% input_with_errors form.server %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
@ -49,14 +52,11 @@
|
|||
{% endwith %}
|
||||
</div>
|
||||
<div class="tablet:grid-col-2">
|
||||
{% comment %} TODO: remove this if for 1192 {% endcomment %}
|
||||
{% if forloop.counter > 2 %}
|
||||
<button type="button" class="usa-button usa-button--unstyled display-block delete-record margin-bottom-075">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#delete"></use>
|
||||
</svg><span class="margin-left-05">Delete</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button" class="usa-button usa-button--unstyled display-block delete-record margin-bottom-075">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#delete"></use>
|
||||
</svg><span class="margin-left-05">Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue