Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2311: New ComboBox widget for form fields [BOB] #3302

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2651cd4
initial approach, from domain.py, not quite working
dave-kennedy-ecs Jan 2, 2025
f359a63
combobox in domain request organization contact
dave-kennedy-ecs Jan 6, 2025
4480e32
updated combobox widget to set proper data-default-value and set doma…
dave-kennedy-ecs Jan 6, 2025
3146dc0
applied widget to state territory
dave-kennedy-ecs Jan 6, 2025
560baed
linted
dave-kennedy-ecs Jan 6, 2025
bb5f61f
updated behavior of combobox, added state territory combobox
dave-kennedy-ecs Jan 10, 2025
0e2d62f
small improvement
dave-kennedy-ecs Jan 10, 2025
6283cad
state territory in org name address domain form
dave-kennedy-ecs Jan 10, 2025
462dae3
Merge branch 'main' into bob/2311-combo-boxes
dave-kennedy-ecs Jan 10, 2025
d411745
fixing test_export again
dave-kennedy-ecs Jan 10, 2025
b4505b3
lint
dave-kennedy-ecs Jan 10, 2025
ae6c461
added federal agency on domain page, and suborg on requesting entity …
dave-kennedy-ecs Jan 13, 2025
d54e57b
update federal agency drop down not to have any exclusions
dave-kennedy-ecs Jan 13, 2025
e2486c1
organization edit form - added state territory combobox
dave-kennedy-ecs Jan 14, 2025
ea509f6
uswds edits to combobox, default values for comboboxes, cleanup of co…
dave-kennedy-ecs Jan 14, 2025
1ca52b4
additional edits to uswds and to combobox.js to accomodate for empty …
dave-kennedy-ecs Jan 15, 2025
24e0243
fixed bug with portfolio requesting entity
dave-kennedy-ecs Jan 15, 2025
fabedda
modified combobox to handle error class
dave-kennedy-ecs Jan 15, 2025
74ef30b
fixed the 'other' problem in requesting entity form
dave-kennedy-ecs Jan 15, 2025
6a49f9e
requesting entity working - code still wip
dave-kennedy-ecs Jan 16, 2025
088140a
clean up of requesting entity
dave-kennedy-ecs Jan 16, 2025
f9fa877
cleanup and lint
dave-kennedy-ecs Jan 16, 2025
3708ef1
Merge branch 'main' into bob/2311-combo-boxes
dave-kennedy-ecs Jan 16, 2025
ba27880
removed default empty options from Checkboxes as they are only needed…
dave-kennedy-ecs Jan 17, 2025
463632b
lint
dave-kennedy-ecs Jan 17, 2025
96618ee
fixing tests
dave-kennedy-ecs Jan 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/registrar/assets/js/uswds-edited.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 0 additions & 113 deletions src/registrar/assets/src/js/getgov/combobox.js

This file was deleted.

3 changes: 0 additions & 3 deletions src/registrar/assets/src/js/getgov/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { initDomainValidators } from './domain-validators.js';
import { initFormsetsForms, triggerModalOnDsDataForm, nameserversFormListener } from './formset-forms.js';
import { initializeUrbanizationToggle } from './urbanization.js';
import { userProfileListener, finishUserSetupListener } from './user-profile.js';
import { loadInitialValuesForComboBoxes } from './combobox.js';
import { handleRequestingEntityFieldset } from './requesting-entity.js';
import { initDomainsTable } from './table-domains.js';
import { initDomainRequestsTable } from './table-domain-requests.js';
Expand Down Expand Up @@ -31,8 +30,6 @@ initializeUrbanizationToggle();
userProfileListener();
finishUserSetupListener();

loadInitialValuesForComboBoxes();

handleRequestingEntityFieldset();

initDomainsTable();
Expand Down
14 changes: 5 additions & 9 deletions src/registrar/assets/src/js/getgov/requesting-entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ export function handleRequestingEntityFieldset() {
const formPrefix = "portfolio_requesting_entity";
const radioFieldset = document.getElementById(`id_${formPrefix}-requesting_entity_is_suborganization__fieldset`);
const radios = radioFieldset?.querySelectorAll(`input[name="${formPrefix}-requesting_entity_is_suborganization"]`);
const select = document.getElementById(`id_${formPrefix}-sub_organization`);
const selectParent = select?.parentElement;
const input = document.getElementById(`id_${formPrefix}-sub_organization`);
const inputGrandParent = input?.parentElement?.parentElement;
const select = input?.previousElementSibling;
const suborgContainer = document.getElementById("suborganization-container");
const suborgDetailsContainer = document.getElementById("suborganization-container__details");
const suborgAddtlInstruction = document.getElementById("suborganization-addtl-instruction");
const subOrgCreateNewOption = document.getElementById("option-to-add-suborg")?.value;
// Make sure all crucial page elements exist before proceeding.
// This more or less ensures that we are on the Requesting Entity page, and not elsewhere.
if (!radios || !select || !selectParent || !suborgContainer || !suborgDetailsContainer) return;
if (!radios || !input || !select || !inputGrandParent || !suborgContainer || !suborgDetailsContainer) return;

// requestingSuborganization: This just broadly determines if they're requesting a suborg at all
// requestingNewSuborganization: This variable determines if the user is trying to *create* a new suborganization or not.
Expand All @@ -28,7 +29,7 @@ export function handleRequestingEntityFieldset() {
if (radio != null) requestingSuborganization = radio?.checked && radio.value === "True";
requestingSuborganization ? showElement(suborgContainer) : hideElement(suborgContainer);
if (select.options.length == 2) { // --Select-- and other are the only options
hideElement(selectParent); // Hide the select drop down and indicate requesting new suborg
hideElement(inputGrandParent); // Hide the combo box and indicate requesting new suborg
hideElement(suborgAddtlInstruction); // Hide additional instruction related to the list
requestingNewSuborganization.value = "True";
} else {
Expand All @@ -37,11 +38,6 @@ export function handleRequestingEntityFieldset() {
requestingNewSuborganization.value === "True" ? showElement(suborgDetailsContainer) : hideElement(suborgDetailsContainer);
}

// Add fake "other" option to sub_organization select
if (select && !Array.from(select.options).some(option => option.value === "other")) {
select.add(new Option(subOrgCreateNewOption, "other"));
}

Comment on lines -40 to -44
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling of 'other' has been moved from javascript to the form

if (requestingNewSuborganization.value === "True") {
select.value = "other";
}
Expand Down
50 changes: 22 additions & 28 deletions src/registrar/forms/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django import forms
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator, MaxLengthValidator
from django.forms import formset_factory
from registrar.forms.utility.combobox import ComboboxWidget
from registrar.models import DomainRequest, FederalAgency
from phonenumber_field.widgets import RegionalPhoneNumberWidget
from registrar.models.suborganization import Suborganization
Expand Down Expand Up @@ -161,9 +162,11 @@ class DomainSuborganizationForm(forms.ModelForm):
"""Form for updating the suborganization"""

sub_organization = forms.ModelChoiceField(
label="Suborganization name",
queryset=Suborganization.objects.none(),
empty_label="⎯ (No suborganization)",
required=False,
widget=forms.Select(),
widget=ComboboxWidget,
)

class Meta:
Expand All @@ -178,20 +181,6 @@ def __init__(self, *args, **kwargs):
portfolio = self.instance.portfolio if self.instance else None
self.fields["sub_organization"].queryset = Suborganization.objects.filter(portfolio=portfolio)

# Set initial value
if self.instance and self.instance.sub_organization:
self.fields["sub_organization"].initial = self.instance.sub_organization

# Set custom form label
self.fields["sub_organization"].label = "Suborganization name"

# Use the combobox rather than the regular select widget
self.fields["sub_organization"].widget.template_name = "django/forms/widgets/combobox.html"

# Set data-default-value attribute
if self.instance and self.instance.sub_organization:
self.fields["sub_organization"].widget.attrs["data-default-value"] = self.instance.sub_organization.pk


class BaseNameserverFormset(forms.BaseFormSet):
def clean(self):
Expand Down Expand Up @@ -456,6 +445,14 @@ class DomainSecurityEmailForm(forms.Form):
class DomainOrgNameAddressForm(forms.ModelForm):
"""Form for updating the organization name and mailing address."""

# for federal agencies we also want to know the top-level agency.
federal_agency = forms.ModelChoiceField(
label="Federal agency",
required=False,
queryset=FederalAgency.objects.all(),
empty_label="--Select--",
widget=ComboboxWidget,
)
zipcode = forms.CharField(
label="Zip code",
validators=[
Expand All @@ -469,6 +466,16 @@ class DomainOrgNameAddressForm(forms.ModelForm):
},
)

state_territory = forms.ChoiceField(
label="State, territory, or military post",
required=True,
choices=[("", "--Select--")] + DomainInformation.StateTerritoryChoices.choices,
error_messages={
"required": ("Select the state, territory, or military post where your organization is located.")
},
widget=ComboboxWidget(),
)

class Meta:
model = DomainInformation
fields = [
Expand All @@ -486,25 +493,12 @@ class Meta:
"organization_name": {"required": "Enter the name of your organization."},
"address_line1": {"required": "Enter the street address of your organization."},
"city": {"required": "Enter the city where your organization is located."},
"state_territory": {
"required": "Select the state, territory, or military post where your organization is located."
},
}
widgets = {
# We need to set the required attributed for State/territory
# because for this fields we are creating an individual
# instance of the Select. For the other fields we use the for loop to set
# the class's required attribute to true.
"organization_name": forms.TextInput,
"address_line1": forms.TextInput,
"address_line2": forms.TextInput,
"city": forms.TextInput,
"state_territory": forms.Select(
attrs={
"required": True,
},
choices=DomainInformation.StateTerritoryChoices.choices,
),
"urbanization": forms.TextInput,
}

Expand Down
Loading
Loading