mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-17 18:09:25 +02:00
initial logic
This commit is contained in:
parent
65f1e628a7
commit
860f8f4e3c
7 changed files with 302 additions and 94 deletions
|
@ -22,6 +22,7 @@ var SUCCESS = "success";
|
|||
*
|
||||
*/
|
||||
const hideElement = (element) => {
|
||||
if (element && !element.classList.contains("display-none"))
|
||||
element.classList.add('display-none');
|
||||
};
|
||||
|
||||
|
@ -30,6 +31,7 @@ const hideElement = (element) => {
|
|||
*
|
||||
*/
|
||||
const showElement = (element) => {
|
||||
if (element && element.classList.contains("display-none"))
|
||||
element.classList.remove('display-none');
|
||||
};
|
||||
|
||||
|
@ -2385,26 +2387,44 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
// This determines if we are on the requesting entity page or not.
|
||||
const fieldset = document.getElementById("requesting-entity-fieldset");
|
||||
if (!fieldset) return;
|
||||
console.log("past here")
|
||||
|
||||
// Get the is_suborganization radio buttons
|
||||
// Sadly, these ugly ids are the auto generated
|
||||
const formPrefix = "portfolio_requesting_entity"
|
||||
const isSuborgRadios = document.querySelectorAll(`input[name="${formPrefix}-is_suborganization"]`);
|
||||
var selectedRequestingEntityValue = document.querySelector(`input[name="${formPrefix}-is_suborganization"]:checked`)?.value;
|
||||
const subOrgSelect = document.querySelector(`#id_${formPrefix}-sub_organization`);
|
||||
const orgName = document.querySelector(`#id_${formPrefix}-organization_name`);
|
||||
const city = document.querySelector(`#id_${formPrefix}-city`);
|
||||
const stateTerritory = document.querySelector(`#id_${formPrefix}-state_territory`);
|
||||
|
||||
console.log(isSuborgRadios)
|
||||
console.log(subOrgSelect)
|
||||
console.log(orgName)
|
||||
console.log(city)
|
||||
console.log(stateTerritory)
|
||||
console.log(selectedRequestingEntityValue)
|
||||
// The suborganization section is its own div
|
||||
const suborganizationFieldset = document.querySelector("#requesting-entity-fieldset__suborganization");
|
||||
|
||||
// Within the suborganization section, we also have a div that contains orgname, city, and stateterritory
|
||||
const suborganizationDetailsFieldset = document.querySelector("#requesting-entity-fieldset__suborganization__details");
|
||||
|
||||
// Use a variable to determine which option has been selected on the yes/no form.
|
||||
|
||||
// Don't do anything if we are missing crucial page elements
|
||||
if (!isSuborgRadios || !subOrgSelect || !orgName || !city || !stateTerritory) return;
|
||||
console.log("past here x2")
|
||||
if (!isSuborgRadios || !subOrgSelect || !suborganizationFieldset || !suborganizationDetailsFieldset) return;
|
||||
|
||||
// Function to toggle suborganization based on is_suborganization selection
|
||||
function toggleSuborganization(radio) {
|
||||
if (radio && radio.checked && radio.value === "True") {
|
||||
showElement(suborganizationFieldset);
|
||||
toggleSuborganizationDetails();
|
||||
} else {
|
||||
hideElement(suborganizationFieldset);
|
||||
hideElement(suborganizationDetailsFieldset);
|
||||
}
|
||||
};
|
||||
|
||||
// Function to toggle organization details based on sub_organization selection
|
||||
function toggleSuborganizationDetails () {
|
||||
// We should hide the org name fields when we select the special other value
|
||||
if (subOrgSelect.value === "other") {
|
||||
showElement(suborganizationDetailsFieldset);
|
||||
} else {
|
||||
hideElement(suborganizationDetailsFieldset);
|
||||
}
|
||||
};
|
||||
|
||||
// Add fake "other" option to sub_organization select
|
||||
if (subOrgSelect && !Array.from(subOrgSelect.options).some(option => option.value === "other")) {
|
||||
|
@ -2414,52 +2434,21 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
subOrgSelect.add(fakeOption);
|
||||
}
|
||||
|
||||
// Hide organization_name, city, state_territory by default
|
||||
hideElement(orgName.parentElement);
|
||||
hideElement(city.parentElement);
|
||||
hideElement(stateTerritory.parentElement);
|
||||
|
||||
// Function to toggle forms based on is_suborganization selection
|
||||
function toggleSubOrganizationFields () {
|
||||
selectedRequestingEntityValue = document.querySelector(`input[name="${formPrefix}-is_suborganization"]:checked`)?.value;
|
||||
if (selectedRequestingEntityValue === "True") {
|
||||
showElement(subOrgSelect.parentElement);
|
||||
toggleOrganizationDetails();
|
||||
} else {
|
||||
hideElement(subOrgSelect.parentElement);
|
||||
hideElement(orgName.parentElement);
|
||||
hideElement(city.parentElement);
|
||||
hideElement(stateTerritory.parentElement);
|
||||
}
|
||||
};
|
||||
|
||||
// Function to toggle organization details based on sub_organization selection
|
||||
function toggleOrganizationDetails () {
|
||||
// We should hide the org name fields when we select the special other value
|
||||
if (subOrgSelect.value === "other") {
|
||||
showElement(orgName.parentElement);
|
||||
showElement(city.parentElement);
|
||||
showElement(stateTerritory.parentElement);
|
||||
} else {
|
||||
hideElement(orgName.parentElement);
|
||||
hideElement(city.parentElement);
|
||||
hideElement(stateTerritory.parentElement);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize visibility
|
||||
toggleSubOrganizationFields();
|
||||
|
||||
// Add event listeners to is_suborganization radio buttons
|
||||
// Add event listener to is_suborganization radio buttons
|
||||
isSuborgRadios.forEach(radio => {
|
||||
radio.addEventListener("change", () => {
|
||||
toggleSubOrganizationFields();
|
||||
// Run this here for initial display.
|
||||
// Since there are only two radio buttons and since this has (practically speaking) no performance impact, this is fine to do.
|
||||
toggleSuborganization(radio);
|
||||
|
||||
// Add an event listener to each to show/hide the relevant fields
|
||||
radio.addEventListener("click", () => {
|
||||
toggleSuborganization(radio);
|
||||
});
|
||||
});
|
||||
|
||||
// Add event listener to the suborg dropdown to show/hide the suborg details section
|
||||
subOrgSelect.addEventListener("change", () => {
|
||||
if (selectedRequestingEntityValue === "True") {
|
||||
toggleOrganizationDetails();
|
||||
}
|
||||
toggleSuborganizationDetails();
|
||||
});
|
||||
|
||||
})();
|
|
@ -31,17 +31,20 @@ class RequestingEntityForm(RegistrarForm):
|
|||
queryset=Suborganization.objects.none(),
|
||||
empty_label="--Select--",
|
||||
)
|
||||
organization_name = forms.CharField(
|
||||
|
||||
# We are using the current sub_organization naming convention here.
|
||||
# We may want to refactor this to suborganization eventually.
|
||||
requested_suborganization = forms.CharField(
|
||||
label="Requested suborganization",
|
||||
required=False,
|
||||
error_messages={"required": "Enter the name of your organization."},
|
||||
)
|
||||
city = forms.CharField(
|
||||
suborganization_city = forms.CharField(
|
||||
label="City",
|
||||
required=False,
|
||||
error_messages={"required": "Enter the city where your organization is located."},
|
||||
)
|
||||
state_territory = forms.ChoiceField(
|
||||
suborganization_state_territory = forms.ChoiceField(
|
||||
label="State, territory, or military post",
|
||||
required=False,
|
||||
choices=[("", "--Select--")] + DomainRequest.StateTerritoryChoices.choices,
|
||||
|
@ -66,26 +69,52 @@ class RequestingEntityForm(RegistrarForm):
|
|||
|
||||
def clean_sub_organization(self):
|
||||
"""Require something to be selected when this is a federal agency."""
|
||||
is_suborganization = self.cleaned_data.get("is_suborganization", None)
|
||||
sub_organization = self.cleaned_data.get("sub_organization", None)
|
||||
if self.cleaned_data.get("is_suborganization", None):
|
||||
# TODO - logic for if other is selected, display other stuff
|
||||
if not sub_organization:
|
||||
# no answer was selected
|
||||
print(f"sub org is: {sub_organization} vs is_suborg: {is_suborganization}")
|
||||
if is_suborganization and not sub_organization:
|
||||
raise forms.ValidationError(
|
||||
"Select a suborganization.",
|
||||
code="required",
|
||||
)
|
||||
# Maybe we just represent this with none?
|
||||
elif sub_organization == "other":
|
||||
org_name = self.cleaned_data.get("organization_name", None)
|
||||
city = self.cleaned_data.get("city", None)
|
||||
state = self.cleaned_data.get("state_territory", None)
|
||||
if not org_name or not city or not state:
|
||||
return sub_organization
|
||||
|
||||
def clean_requested_suborganization(self):
|
||||
field = self.cleaned_data.get("requested_suborganization")
|
||||
if self.is_custom_suborg() and not field:
|
||||
raise forms.ValidationError(
|
||||
"Enter details for your suborganization.",
|
||||
"Enter details for your organization name.",
|
||||
code="required",
|
||||
)
|
||||
return sub_organization
|
||||
return field
|
||||
|
||||
def clean_suborganization_city(self):
|
||||
field = self.cleaned_data.get("suborganization_city")
|
||||
if self.is_custom_suborg():
|
||||
if not field:
|
||||
raise forms.ValidationError(
|
||||
"Enter details for your city.",
|
||||
code="required",
|
||||
)
|
||||
return field
|
||||
|
||||
def clean_suborganization_state_territory(self):
|
||||
field = self.cleaned_data.get("suborganization_state_territory")
|
||||
if self.is_custom_suborg():
|
||||
if not field:
|
||||
raise forms.ValidationError(
|
||||
"Enter details for your state or territory.",
|
||||
code="required",
|
||||
)
|
||||
return field
|
||||
|
||||
def is_custom_suborg(self):
|
||||
"""Checks that the select suborg is 'other', which is a custom field indicating
|
||||
that we should create a new suborganization."""
|
||||
is_suborganization = self.cleaned_data.get("is_suborganization")
|
||||
sub_organization = self.cleaned_data.get("sub_organization")
|
||||
return is_suborganization and sub_organization == "other"
|
||||
|
||||
|
||||
class RequestingEntityYesNoForm(BaseYesNoForm):
|
||||
"""The yes/no field for the RequestingEntity form."""
|
||||
|
@ -107,10 +136,11 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
|
|||
Determines the initial checked state of the form based on the domain_request's attributes.
|
||||
"""
|
||||
|
||||
if self.domain_request.portfolio and (self.domain_request.sub_organization or self.domain_request.organization_name):
|
||||
return self.domain_request.organization_name != self.domain_request.portfolio.organization_name
|
||||
if self.domain_request.portfolio and self.domain_request.organization_name == self.domain_request.portfolio.organization_name:
|
||||
return False
|
||||
elif self.domain_request.is_suborganization():
|
||||
return True
|
||||
else:
|
||||
# No pre-selection for new domain requests
|
||||
return None
|
||||
|
||||
class OrganizationTypeForm(RegistrarForm):
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
# Generated by Django 4.2.10 on 2024-10-23 15:01
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0133_domainrequest_rejection_reason_email_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="domainrequest",
|
||||
name="requested_suborganization",
|
||||
field=models.CharField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="domainrequest",
|
||||
name="suborganization_city",
|
||||
field=models.CharField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="domainrequest",
|
||||
name="suborganization_state_territory",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("AL", "Alabama (AL)"),
|
||||
("AK", "Alaska (AK)"),
|
||||
("AS", "American Samoa (AS)"),
|
||||
("AZ", "Arizona (AZ)"),
|
||||
("AR", "Arkansas (AR)"),
|
||||
("CA", "California (CA)"),
|
||||
("CO", "Colorado (CO)"),
|
||||
("CT", "Connecticut (CT)"),
|
||||
("DE", "Delaware (DE)"),
|
||||
("DC", "District of Columbia (DC)"),
|
||||
("FL", "Florida (FL)"),
|
||||
("GA", "Georgia (GA)"),
|
||||
("GU", "Guam (GU)"),
|
||||
("HI", "Hawaii (HI)"),
|
||||
("ID", "Idaho (ID)"),
|
||||
("IL", "Illinois (IL)"),
|
||||
("IN", "Indiana (IN)"),
|
||||
("IA", "Iowa (IA)"),
|
||||
("KS", "Kansas (KS)"),
|
||||
("KY", "Kentucky (KY)"),
|
||||
("LA", "Louisiana (LA)"),
|
||||
("ME", "Maine (ME)"),
|
||||
("MD", "Maryland (MD)"),
|
||||
("MA", "Massachusetts (MA)"),
|
||||
("MI", "Michigan (MI)"),
|
||||
("MN", "Minnesota (MN)"),
|
||||
("MS", "Mississippi (MS)"),
|
||||
("MO", "Missouri (MO)"),
|
||||
("MT", "Montana (MT)"),
|
||||
("NE", "Nebraska (NE)"),
|
||||
("NV", "Nevada (NV)"),
|
||||
("NH", "New Hampshire (NH)"),
|
||||
("NJ", "New Jersey (NJ)"),
|
||||
("NM", "New Mexico (NM)"),
|
||||
("NY", "New York (NY)"),
|
||||
("NC", "North Carolina (NC)"),
|
||||
("ND", "North Dakota (ND)"),
|
||||
("MP", "Northern Mariana Islands (MP)"),
|
||||
("OH", "Ohio (OH)"),
|
||||
("OK", "Oklahoma (OK)"),
|
||||
("OR", "Oregon (OR)"),
|
||||
("PA", "Pennsylvania (PA)"),
|
||||
("PR", "Puerto Rico (PR)"),
|
||||
("RI", "Rhode Island (RI)"),
|
||||
("SC", "South Carolina (SC)"),
|
||||
("SD", "South Dakota (SD)"),
|
||||
("TN", "Tennessee (TN)"),
|
||||
("TX", "Texas (TX)"),
|
||||
("UM", "United States Minor Outlying Islands (UM)"),
|
||||
("UT", "Utah (UT)"),
|
||||
("VT", "Vermont (VT)"),
|
||||
("VI", "Virgin Islands (VI)"),
|
||||
("VA", "Virginia (VA)"),
|
||||
("WA", "Washington (WA)"),
|
||||
("WV", "West Virginia (WV)"),
|
||||
("WI", "Wisconsin (WI)"),
|
||||
("WY", "Wyoming (WY)"),
|
||||
("AA", "Armed Forces Americas (AA)"),
|
||||
("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
|
||||
("AP", "Armed Forces Pacific (AP)"),
|
||||
],
|
||||
max_length=2,
|
||||
null=True,
|
||||
verbose_name="state, territory, or military post",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -344,6 +344,24 @@ class DomainRequest(TimeStampedModel):
|
|||
verbose_name="Suborganization",
|
||||
)
|
||||
|
||||
requested_suborganization = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
suborganization_city = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
suborganization_state_territory = models.CharField(
|
||||
max_length=2,
|
||||
choices=StateTerritoryChoices.choices,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="state, territory, or military post",
|
||||
)
|
||||
|
||||
# This is the domain request user who created this domain request.
|
||||
creator = models.ForeignKey(
|
||||
"registrar.User",
|
||||
|
@ -1104,6 +1122,15 @@ class DomainRequest(TimeStampedModel):
|
|||
|
||||
self.creator.restrict_user()
|
||||
|
||||
# Form unlocking steps
|
||||
# These methods control the conditions in which we should unlock certain domain wizard steps.
|
||||
def unlock_requesting_entity(self) -> bool:
|
||||
"""Unlocks the requesting entity step """
|
||||
if self.portfolio and self.organization_name == self.portfolio.organization_name:
|
||||
return True
|
||||
else:
|
||||
return self.is_suborganization()
|
||||
|
||||
# ## Form policies ###
|
||||
#
|
||||
# These methods control what questions need to be answered by applicants
|
||||
|
@ -1174,15 +1201,24 @@ class DomainRequest(TimeStampedModel):
|
|||
return False
|
||||
|
||||
def is_suborganization(self) -> bool:
|
||||
"""Determines if this record is a suborganization or not"""
|
||||
if self.portfolio:
|
||||
if self.sub_organization:
|
||||
return True
|
||||
|
||||
if self.organization_name != self.portfolio.organization_name:
|
||||
if self.has_information_required_to_make_suborganization():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def has_information_required_to_make_suborganization(self):
|
||||
"""Checks if we have all the information we need to create a new suborganization object.
|
||||
Checks for a the existence of requested_suborganization, suborganization_city, suborganization_state_territory"""
|
||||
return (
|
||||
self.requested_domain and
|
||||
self.suborganization_city and
|
||||
self.suborganization_state_territory
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
"""This is to process to_dict for Domain Information, making it friendly
|
||||
to "copy" it
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.db import models
|
||||
from registrar.models import DomainRequest
|
||||
from .utility.time_stamped_model import TimeStampedModel
|
||||
|
||||
|
||||
|
|
|
@ -11,13 +11,38 @@
|
|||
<legend>
|
||||
<h2>Who will use the domain you’re requesting?</h2>
|
||||
</legend>
|
||||
|
||||
{# forms.0 is a small yes/no form that toggles the visibility of "requesting entity" formset #}
|
||||
{% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %}
|
||||
{% with attr_required=True %}
|
||||
{% input_with_errors forms.0.is_suborganization %}
|
||||
{% endwith %}
|
||||
{# forms.0 is a small yes/no form that toggles the visibility of "requesting entity" formset #}
|
||||
{% endwith %}
|
||||
|
||||
<div id="requesting-entity-fieldset__suborganization" class="margin-top-4">
|
||||
<h2>Add suborganization information</h2>
|
||||
<p>
|
||||
This information will be published in <a class="usa-link usa-link--always-blue" href="{% public_site_url 'about/data' %}">.gov’s public data</a>. If you don’t see your suborganization in the list,
|
||||
select “other” and enter the name or your suborganization.
|
||||
</p>
|
||||
{% with attr_required=True %}
|
||||
{% input_with_errors forms.1.sub_organization %}
|
||||
{% input_with_errors forms.1.organization_name %}
|
||||
{% input_with_errors forms.1.city %}
|
||||
{% input_with_errors forms.1.state_territory %}
|
||||
{% endwith %}
|
||||
|
||||
{% comment %} This will be toggled if a special value, "other", is selected.
|
||||
Otherwise this field is invisible.
|
||||
{% endcomment %}
|
||||
<div id="requesting-entity-fieldset__suborganization__details">
|
||||
{% with attr_required=True %}
|
||||
{% input_with_errors forms.1.requested_suborganization %}
|
||||
{% endwith %}
|
||||
{% with attr_required=True %}
|
||||
{% input_with_errors forms.1.suborganization_city %}
|
||||
{% endwith %}
|
||||
{% with attr_required=True %}
|
||||
{% input_with_errors forms.1.suborganization_state_territory %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endblock %}
|
||||
|
|
|
@ -11,6 +11,7 @@ from registrar.forms import domain_request_wizard as forms
|
|||
from registrar.forms.utility.wizard_form_helper import request_step_list
|
||||
from registrar.models import DomainRequest
|
||||
from registrar.models.contact import Contact
|
||||
from registrar.models.suborganization import Suborganization
|
||||
from registrar.models.user import User
|
||||
from registrar.views.utility import StepsHelper
|
||||
from registrar.views.utility.permission_views import DomainRequestPermissionDeleteView
|
||||
|
@ -137,7 +138,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
|||
}
|
||||
|
||||
PORTFOLIO_UNLOCKING_STEPS = {
|
||||
PortfolioDomainRequestStep.REQUESTING_ENTITY: lambda self: self.domain_request.organization_name is not None,
|
||||
PortfolioDomainRequestStep.REQUESTING_ENTITY: lambda w: w.from_model("unlock_requesting_entity", False),
|
||||
PortfolioDomainRequestStep.CURRENT_SITES: lambda self: (
|
||||
self.domain_request.current_websites.exists() or self.domain_request.requested_domain is not None
|
||||
),
|
||||
|
@ -590,6 +591,37 @@ class RequestingEntity(DomainRequestWizard):
|
|||
template_name = "domain_request_requesting_entity.html"
|
||||
forms = [forms.RequestingEntityYesNoForm, forms.RequestingEntityForm]
|
||||
|
||||
def save(self, forms: list):
|
||||
requesting_entity_form = forms[1]
|
||||
cleaned_data = requesting_entity_form.cleaned_data
|
||||
is_suborganization = cleaned_data.get("is_suborganization")
|
||||
sub_organization = cleaned_data.get("sub_organization")
|
||||
requested_suborganization = cleaned_data.get("requested_suborganization")
|
||||
|
||||
# If no suborganization presently exists but the user filled out org information then create a suborg automatically.
|
||||
if is_suborganization and (sub_organization or requested_suborganization):
|
||||
# Cleanup the organization name field, as this isn't for suborganizations.
|
||||
self.domain_request.organization_name = None
|
||||
|
||||
# Create or get the Suborganization.
|
||||
# Then update the domain_request with the new or existing suborganization
|
||||
if not sub_organization:
|
||||
sub_organization, created = Suborganization.objects.get_or_create(
|
||||
name=cleaned_data.get("requested_suborganization"),
|
||||
portfolio=self.domain_request.portfolio,
|
||||
)
|
||||
|
||||
self.domain_request.sub_organization = sub_organization
|
||||
else:
|
||||
# If the user doesn't intend to create a suborg, simply don't make one and do some data cleanup
|
||||
self.domain_request.organization_name = self.domain_request.portfolio.organization_name
|
||||
|
||||
self.domain_request.sub_organization = None
|
||||
self.domain_request.requested_suborganization = None
|
||||
self.domain_request.suborganization_city = None
|
||||
self.domain_request.suborganization_state_territory = None
|
||||
|
||||
super().save(forms)
|
||||
|
||||
class PortfolioAdditionalDetails(DomainRequestWizard):
|
||||
template_name = "portfolio_domain_request_additional_details.html"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue