diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index fa0dea885..ababbbaa1 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -2741,6 +2741,8 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin):
portfolio_urbanization.short_description = "Urbanization" # type: ignore
+ # ------ FEB fields ------
+
# This is just a placeholder. This field will be populated in the detail_table_fieldset view.
# This is not a field that exists on the model.
def status_history(self, obj):
@@ -2821,7 +2823,16 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin):
]
},
),
- (".gov domain", {"fields": ["requested_domain", "alternative_domains"]}),
+ (
+ ".gov domain",
+ {
+ "fields": [
+ "requested_domain",
+ "alternative_domains",
+ "feb_naming_requirements_details",
+ ]
+ },
+ ),
(
"Contacts",
{
@@ -2833,10 +2844,24 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin):
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email",
+ "eop_stakeholder_first_name",
+ "eop_stakeholder_last_name",
+ ]
+ },
+ ),
+ (
+ "Background info",
+ {
+ "fields": [
+ "feb_purpose_choice",
+ "purpose",
+ "time_frame_details",
+ "interagency_initiative_details",
+ "anything_else",
+ "current_websites",
]
},
),
- ("Background info", {"fields": ["purpose", "anything_else", "current_websites"]}),
(
"Type of organization",
{
@@ -3033,23 +3058,41 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin):
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
+ excluded_fields = set()
+ feb_fields = [
+ "feb_naming_requirements_details",
+ "feb_purpose_choice",
+ "time_frame_details",
+ "interagency_initiative_details",
+ "eop_stakeholder_first_name",
+ "eop_stakeholder_last_name",
+ ]
+
+ org_fields = [
+ "portfolio",
+ "sub_organization",
+ "requested_suborganization",
+ "suborganization_city",
+ "suborganization_state_territory",
+ ]
+
+ org_flag = flag_is_active_for_user(request.user, "organization_requests")
+ # Hide FEB fields for non-FEB requests
+ if not (obj and obj.portfolio and obj.is_feb()):
+ excluded_fields.update(feb_fields)
+
# Hide certain portfolio and suborg fields behind the organization requests flag
# if it is not enabled
- if not flag_is_active_for_user(request.user, "organization_requests"):
- excluded_fields = [
- "portfolio",
- "sub_organization",
- "requested_suborganization",
- "suborganization_city",
- "suborganization_state_territory",
- ]
- modified_fieldsets = []
- for name, data in fieldsets:
- fields = data.get("fields", [])
- fields = tuple(field for field in fields if field not in excluded_fields)
- modified_fieldsets.append((name, {**data, "fields": fields}))
- return modified_fieldsets
- return fieldsets
+ if not org_flag:
+ excluded_fields.update(org_fields)
+ excluded_fields.update(feb_fields)
+
+ modified_fieldsets = []
+ for name, data in fieldsets:
+ fields = data.get("fields", [])
+ fields = tuple(field for field in fields if field not in excluded_fields)
+ modified_fieldsets.append((name, {**data, "fields": fields}))
+ return modified_fieldsets
# Trigger action when a fieldset is changed
def save_model(self, request, obj, form, change):
diff --git a/src/registrar/assets/src/js/getgov/domain-purpose-form.js b/src/registrar/assets/src/js/getgov/domain-purpose-form.js
index 7cde5bc35..7934d5f68 100644
--- a/src/registrar/assets/src/js/getgov/domain-purpose-form.js
+++ b/src/registrar/assets/src/js/getgov/domain-purpose-form.js
@@ -1,41 +1,105 @@
import { showElement } from './helpers.js';
+// Flag to track if we're in the initial page load
+let isInitialLoad = true;
+
export const domain_purpose_choice_callbacks = {
'new': {
- callback: function(value, element) {
+ callback: function(value, element, event) {
+ // Only clear errors if this is a user-initiated event (not initial page load)
+ if (!isInitialLoad) {
+ clearErrors(element);
+ }
+
//show the purpose details container
showElement(element);
// change just the text inside the em tag
- const labelElement = element.querySelector('.usa-label em');
- labelElement.innerHTML = 'Explain why a new domain is required and why a ' +
- 'subdomain of an existing domain doesn\'t meet your needs.' +
+ const labelElement = element.querySelector('p em');
+ labelElement.innerHTML = 'Explain why a new domain name is needed instead of using a ' +
+ 'subdomain of an existing website.' +
'
' + // Adding double line break for spacing
- 'Include any data that supports a clear public benefit or ' +
- 'evidence user need for this new domain. ' +
+ 'Include any information or data that shows how the new domain would ' +
+ 'benefit the public or meet user needs. ' +
'*';
+
+ // Mark that we're no longer in initial load
+ isInitialLoad = false;
},
element: document.getElementById('purpose-details-container')
},
'redirect': {
- callback: function(value, element) {
+ callback: function(value, element, event) {
+ // Only clear errors if this is a user-initiated event (not initial page load)
+ if (!isInitialLoad) {
+ clearErrors(element);
+ }
+
// show the purpose details container
showElement(element);
// change just the text inside the em tag
- const labelElement = element.querySelector('.usa-label em');
+ const labelElement = element.querySelector('p em');
labelElement.innerHTML = 'Explain why a redirect is necessary. ' +
'*';
+
+ // Mark that we're no longer in initial load
+ isInitialLoad = false;
},
element: document.getElementById('purpose-details-container')
},
'other': {
- callback: function(value, element) {
+ callback: function(value, element, event) {
+ // Only clear errors if this is a user-initiated event (not initial page load)
+ if (!isInitialLoad) {
+ clearErrors(element);
+ }
+
// Show the purpose details container
showElement(element);
// change just the text inside the em tag
- const labelElement = element.querySelector('.usa-label em');
+ const labelElement = element.querySelector('p em');
labelElement.innerHTML = 'Describe how this domain will be used. ' +
'*';
+
+ // Mark that we're no longer in initial load
+ isInitialLoad = false;
},
element: document.getElementById('purpose-details-container')
}
+}
+
+// Helper function to clear error messages in a textarea
+function clearErrors(element) {
+ // Find the error message div
+ const errorMessage = element.querySelector('#id_purpose-purpose__error-message');
+ if (errorMessage) {
+ errorMessage.remove();
+ }
+
+ // Find the form group and remove error class
+ const formGroup = element.querySelector('.usa-form-group');
+ if (formGroup) {
+ formGroup.classList.remove('usa-form-group--error');
+ }
+
+ // Find the textarea and remove error class
+ const textarea = element.querySelector('#id_purpose-purpose');
+ if (textarea) {
+ textarea.classList.remove('usa-input--error');
+
+ // Also update aria attributes
+ textarea.setAttribute('aria-invalid', 'false');
+
+ // Remove error message from aria-describedby
+ const describedBy = textarea.getAttribute('aria-describedby');
+ if (describedBy) {
+ const newDescribedBy = describedBy.replace('id_purpose-purpose__error-message', '').trim();
+ textarea.setAttribute('aria-describedby', newDescribedBy);
+ }
+ }
+
+ // Find the label and remove error class
+ const label = element.querySelector('label');
+ if (label) {
+ label.classList.remove('usa-label--error');
+ }
}
\ No newline at end of file
diff --git a/src/registrar/fixtures/fixtures_users.py b/src/registrar/fixtures/fixtures_users.py
index fdaa1c135..a89d63cce 100644
--- a/src/registrar/fixtures/fixtures_users.py
+++ b/src/registrar/fixtures/fixtures_users.py
@@ -22,6 +22,13 @@ class UserFixture:
"""
ADMINS = [
+ {
+ "username": "4aa78480-6272-42f9-ac29-a034ebdd9231",
+ "first_name": "Kaitlin",
+ "last_name": "Abbitt",
+ "email": "kaitlin.abbitt@cisa.dhs.gov",
+ "title": "Captain pirate",
+ },
{
"username": "aad084c3-66cc-4632-80eb-41cdf5c5bcbf",
"first_name": "Aditi",
diff --git a/src/registrar/forms/feb.py b/src/registrar/forms/feb.py
index 2dabbff0d..f0b311b02 100644
--- a/src/registrar/forms/feb.py
+++ b/src/registrar/forms/feb.py
@@ -1,6 +1,7 @@
from django import forms
from django.core.validators import MaxLengthValidator
from registrar.forms.utility.wizard_form_helper import BaseDeletableRegistrarForm, BaseYesNoForm
+from registrar.models.domain_request import DomainRequest
class ExecutiveNamingRequirementsYesNoForm(BaseYesNoForm, BaseDeletableRegistrarForm):
@@ -11,6 +12,8 @@ class ExecutiveNamingRequirementsYesNoForm(BaseYesNoForm, BaseDeletableRegistrar
field_name = "feb_naming_requirements"
+ required_error_message = "Select “Yes” if your submission meets each domain naming requirement. Select “No” if it doesn’t meet each requirement." # noqa: E501
+
@property
def form_is_checked(self):
"""
@@ -25,7 +28,9 @@ class ExecutiveNamingRequirementsDetailsForm(BaseDeletableRegistrarForm):
widget=forms.Textarea(attrs={"maxlength": "2000"}),
max_length=2000,
required=True,
- error_messages={"required": ("This field is required.")},
+ error_messages={
+ "required": ("Provide details on why your submission does not meet each domain naming requirement.")
+ }, # noqa: E501
validators=[
MaxLengthValidator(
2000,
@@ -41,18 +46,14 @@ class FEBPurposeOptionsForm(BaseDeletableRegistrarForm):
field_name = "feb_purpose_choice"
- form_choices = (
- ("new", "Used for a new website"),
- ("redirect", "Used as a redirect for an existing website"),
- ("other", "Not for a website"),
- )
+ form_choices = DomainRequest.FEBPurposeChoices.choices
feb_purpose_choice = forms.ChoiceField(
required=True,
choices=form_choices,
widget=forms.RadioSelect,
error_messages={
- "required": "This question is required.",
+ "required": "Select the purpose of your requested domain.",
},
label="Select one",
)
@@ -65,6 +66,10 @@ class FEBTimeFrameYesNoForm(BaseDeletableRegistrarForm, BaseYesNoForm):
"""
field_name = "has_timeframe"
+ required_error_message = (
+ "Select “Yes” if you have a target time frame for"
+ " launching this domain. Select “No” if you don’t have a target time frame."
+ )
@property
def form_is_checked(self):
@@ -79,7 +84,7 @@ class FEBTimeFrameDetailsForm(BaseDeletableRegistrarForm):
label="time_frame_details",
widget=forms.Textarea(
attrs={
- "aria-label": "Provide details on your target timeframe. \
+ "aria-label": "Provide details on your target time frame. \
Is there a special significance to this date (legal requirement, announcement, event, etc)?"
}
),
@@ -89,7 +94,7 @@ class FEBTimeFrameDetailsForm(BaseDeletableRegistrarForm):
message="Response must be less than 2000 characters.",
)
],
- error_messages={"required": "Provide details on your target timeframe."},
+ error_messages={"required": "Provide details on your target time frame."},
)
@@ -100,6 +105,10 @@ class FEBInteragencyInitiativeYesNoForm(BaseDeletableRegistrarForm, BaseYesNoFor
"""
field_name = "is_interagency_initiative"
+ required_error_message = (
+ "Select “Yes” if the domain will be used for an "
+ "interagency initiative. Select “No” if it won’t be used for an interagency initiative."
+ )
@property
def form_is_checked(self):
@@ -156,29 +165,12 @@ class EOPContactForm(BaseDeletableRegistrarForm):
error_messages={"required": "Enter the last name / family name of this contact."},
required=True,
)
- email = forms.EmailField(
- label="Email",
- max_length=None,
- error_messages={
- "required": ("Enter an email address in the required format, like name@example.com."),
- "invalid": ("Enter an email address in the required format, like name@example.com."),
- },
- validators=[
- MaxLengthValidator(
- 320,
- message="Response must be less than 320 characters.",
- )
- ],
- required=True,
- help_text="Enter an email address in the required format, like name@example.com.",
- )
@classmethod
def from_database(cls, obj):
return {
"first_name": obj.eop_stakeholder_first_name,
"last_name": obj.eop_stakeholder_last_name,
- "email": obj.eop_stakeholder_email,
}
def to_database(self, obj):
@@ -192,7 +184,6 @@ class EOPContactForm(BaseDeletableRegistrarForm):
return
obj.eop_stakeholder_first_name = self.cleaned_data["first_name"]
obj.eop_stakeholder_last_name = self.cleaned_data["last_name"]
- obj.eop_stakeholder_email = self.cleaned_data["email"]
obj.save()
diff --git a/src/registrar/forms/utility/wizard_form_helper.py b/src/registrar/forms/utility/wizard_form_helper.py
index eedf5839b..4245bed30 100644
--- a/src/registrar/forms/utility/wizard_form_helper.py
+++ b/src/registrar/forms/utility/wizard_form_helper.py
@@ -234,9 +234,12 @@ class BaseYesNoForm(RegistrarForm):
# For instance, this could be "has_other_contacts"
field_name: str
+ # This field can be overriden to show a custom error
+ # message.
required_error_message = "This question is required."
# Default form choice mapping. Default is suitable for most cases.
+ # Override for more complex scenarios.
form_choices = ((True, "Yes"), (False, "No"))
def __init__(self, *args, **kwargs):
diff --git a/src/registrar/migrations/0144_domainrequest_eop_stakeholder_email_and_more.py b/src/registrar/migrations/0144_domainrequest_eop_stakeholder_email_and_more.py
index b23b6c107..2fcc86aa0 100644
--- a/src/registrar/migrations/0144_domainrequest_eop_stakeholder_email_and_more.py
+++ b/src/registrar/migrations/0144_domainrequest_eop_stakeholder_email_and_more.py
@@ -13,17 +13,17 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name="domainrequest",
name="eop_stakeholder_email",
- field=models.EmailField(blank=True, max_length=254, null=True, verbose_name="EOP Stakeholder Email"),
+ field=models.EmailField(blank=True, max_length=254, null=True, verbose_name="EOP contact email"),
),
migrations.AddField(
model_name="domainrequest",
name="eop_stakeholder_first_name",
- field=models.CharField(blank=True, null=True, verbose_name="EOP Stakeholder First Name"),
+ field=models.CharField(blank=True, null=True, verbose_name="EOP contact first name"),
),
migrations.AddField(
model_name="domainrequest",
name="eop_stakeholder_last_name",
- field=models.CharField(blank=True, null=True, verbose_name="EOP Stakeholder Last Name"),
+ field=models.CharField(blank=True, null=True, verbose_name="EOP contact last name"),
),
migrations.AddField(
model_name="domainrequest",
diff --git a/src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py b/src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py
new file mode 100644
index 000000000..a89d977b5
--- /dev/null
+++ b/src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py
@@ -0,0 +1,56 @@
+# Generated by Django 4.2.20 on 2025-03-26 19:47
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("registrar", "0145_create_groups_v19"),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name="domainrequest",
+ name="eop_stakeholder_email",
+ ),
+ migrations.AlterField(
+ model_name="domainrequest",
+ name="feb_naming_requirements",
+ field=models.BooleanField(blank=True, null=True, verbose_name="Meets naming requirements"),
+ ),
+ migrations.AlterField(
+ model_name="domainrequest",
+ name="feb_naming_requirements_details",
+ field=models.TextField(
+ blank=True,
+ help_text="Required if requested domain that doesn't meet naming requirements",
+ null=True,
+ verbose_name="Domain name rationale",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="domainrequest",
+ name="feb_purpose_choice",
+ field=models.CharField(
+ blank=True,
+ choices=[
+ ("new", "Used for a new website"),
+ ("redirect", "Used as a redirect for an existing website"),
+ ("other", "Not for a website"),
+ ],
+ null=True,
+ verbose_name="Purpose type",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="domainrequest",
+ name="interagency_initiative_details",
+ field=models.TextField(blank=True, null=True, verbose_name="Interagency initiative"),
+ ),
+ migrations.AlterField(
+ model_name="domainrequest",
+ name="time_frame_details",
+ field=models.TextField(blank=True, null=True, verbose_name="Target time frame"),
+ ),
+ ]
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index d68a29ab1..287712516 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -55,9 +55,14 @@ class DomainRequest(TimeStampedModel):
return cls(status_name).label if status_name else None
class FEBPurposeChoices(models.TextChoices):
- WEBSITE = "website"
- REDIRECT = "redirect"
- OTHER = "other"
+ WEBSITE = "new", "Used for a new website"
+ REDIRECT = "redirect", "Used as a redirect for an existing website"
+ OTHER = "other", "Not for a website"
+
+ @classmethod
+ def get_purpose_label(cls, purpose_name: str | None):
+ """Returns the associated label for a given purpose name"""
+ return cls(purpose_name).label if purpose_name else None
class StateTerritoryChoices(models.TextChoices):
ALABAMA = "AL", "Alabama (AL)"
@@ -510,17 +515,21 @@ class DomainRequest(TimeStampedModel):
feb_naming_requirements = models.BooleanField(
null=True,
blank=True,
+ verbose_name="Meets naming requirements",
)
feb_naming_requirements_details = models.TextField(
null=True,
blank=True,
+ help_text="Required if requested domain that doesn't meet naming requirements",
+ verbose_name="Domain name rationale",
)
feb_purpose_choice = models.CharField(
null=True,
blank=True,
choices=FEBPurposeChoices.choices,
+ verbose_name="Purpose type",
)
working_with_eop = models.BooleanField(
@@ -531,24 +540,17 @@ class DomainRequest(TimeStampedModel):
eop_stakeholder_first_name = models.CharField(
null=True,
blank=True,
- verbose_name="EOP Stakeholder First Name",
+ verbose_name="EOP contact first name",
)
eop_stakeholder_last_name = models.CharField(
null=True,
blank=True,
- verbose_name="EOP Stakeholder Last Name",
- )
-
- eop_stakeholder_email = models.EmailField(
- null=True,
- blank=True,
- verbose_name="EOP Stakeholder Email",
+ verbose_name="EOP contact last name",
)
# This field is alternately used for generic domain purpose explanations
# and for explanations of the specific purpose chosen with feb_purpose_choice
- # by a Federal Executive Branch agency.
purpose = models.TextField(
null=True,
blank=True,
@@ -562,6 +564,7 @@ class DomainRequest(TimeStampedModel):
time_frame_details = models.TextField(
null=True,
blank=True,
+ verbose_name="Target time frame",
)
is_interagency_initiative = models.BooleanField(
@@ -572,6 +575,7 @@ class DomainRequest(TimeStampedModel):
interagency_initiative_details = models.TextField(
null=True,
blank=True,
+ verbose_name="Interagency initiative",
)
alternative_domains = models.ManyToManyField(
@@ -1015,11 +1019,15 @@ class DomainRequest(TimeStampedModel):
if not context:
has_organization_feature_flag = flag_is_active_for_user(recipient, "organization_feature")
is_org_user = has_organization_feature_flag and recipient.has_view_portfolio_permission(self.portfolio)
+ requires_feb_questions = self.is_feb() and is_org_user
+ purpose_label = DomainRequest.FEBPurposeChoices.get_purpose_label(self.feb_purpose_choice)
context = {
"domain_request": self,
# This is the user that we refer to in the email
"recipient": recipient,
"is_org_user": is_org_user,
+ "requires_feb_questions": requires_feb_questions,
+ "purpose_label": purpose_label,
}
if custom_email_content:
diff --git a/src/registrar/templates/domain_request_dotgov_domain.html b/src/registrar/templates/domain_request_dotgov_domain.html
index 57df80cb1..60923a48b 100644
--- a/src/registrar/templates/domain_request_dotgov_domain.html
+++ b/src/registrar/templates/domain_request_dotgov_domain.html
@@ -2,19 +2,25 @@
{% load static field_helpers url_helpers %}
{% block form_instructions %}
-
Before requesting a .gov domain, please make sure it meets our naming requirements. Your domain name must: +
+ Before requesting a .gov domain, please make sure it meets + {% if requires_feb_questions %} + our naming requirements for executive branch agencies. Your domain name must: + {% else %} + our naming requirements. Your domain name must: + {% endif %}
Names that uniquely apply to your organization are likely to be approved over names that could also apply to other organizations. - {% if not is_federal %}In most instances, this requires including your state's two-letter abbreviation.{% endif %}
+ {% if not is_federal %}In most instances, this requires including your state’s two-letter abbreviation.{% endif %} {% if not portfolio %} -Requests for your organization's initials or an abbreviated name might not be approved, but we encourage you to request the name you want.
+Requests for your organization’s initials or an abbreviated name might not be approved, but we encourage you to request the name you want.
{% endif %}Note that only federal agencies can request generic terms like @@ -29,7 +35,7 @@ {% block form_required_fields_help_text %} -{# empty this block so it doesn't show on this page #} +{# empty this block so it doesn’t show on this page #} {% endblock %} @@ -42,8 +48,8 @@
- After you enter your domain, we'll make sure it's available and that it meets some of our naming requirements. - If your domain passes these initial checks, we'll verify that it meets all our requirements after you complete the rest of this form. + After you enter your domain, we’ll make sure it’s available and that it meets some of our naming requirements. + If your domain passes these initial checks, we’ll verify that it meets all our requirements after you complete the rest of this form.
{% with attr_aria_labelledby="domain_instructions domain_instructions2" attr_aria_describedby="id_dotgov_domain-requested_domain--toast" %} {# attr_validate / validate="domain" invokes code in getgov.min.js #} @@ -65,7 +71,7 @@- Are there other domains you'd like if we can't give you your first choice? + Are there other domains you’d like if we can’t give you your first choice?
{% with attr_aria_labelledby="alt_domain_instructions" %} {# Will probably want to remove blank-ok and do related cleanup when we implement delete #} @@ -99,7 +105,7 @@ >Check availability- If you're not sure this is the domain you want, that's ok. You can change the domain later. + If you’re not sure this is the domain you want, that’s ok. You can change the domain later.
@@ -114,9 +120,10 @@OMB will review each request against the domain - naming requirements for executive branch agencies - . - Agency submissions are expected to meet each requirement. + naming requirements for executive branch agencies. Agency submissions are expected to meet each requirement. +
++ Select one. *
{% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} {% input_with_errors forms.2.feb_naming_requirements %} @@ -124,13 +131,12 @@ {# Conditional Details Field – only shown when the executive naming requirements radio is "False" #} {% endif %} diff --git a/src/registrar/templates/domain_request_purpose.html b/src/registrar/templates/domain_request_purpose.html index 9c6754f22..5e1bd5b76 100644 --- a/src/registrar/templates/domain_request_purpose.html +++ b/src/registrar/templates/domain_request_purpose.html @@ -12,14 +12,12 @@ {% block form_fields %} {% if requires_feb_questions %} - {% else %}Describe how you’ll use your .gov domain. Will it be used for a website, email, or something else?
diff --git a/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt b/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt index 866fde50f..63a32fa11 100644 --- a/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt +++ b/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt @@ -8,12 +8,47 @@ Current websites: {% for site in domain_request.current_websites.all %} {% endfor %}{% endif %} .gov domain: {{ domain_request.requested_domain.name }} +{% if requires_feb_questions %} + Meets naming requirements + {% if domain_request.feb_naming_requirements %} + {{ domain_request.feb_naming_requirements }} + {% else %} + No + {{ domain_request.feb_naming_requirements_details }} + {% endif %} +{% endif %} {% if domain_request.alternative_domains.all %} Alternative domains: {% for site in domain_request.alternative_domains.all %}{% spaceless %}{{ site.website }}{% endspaceless %} {% endfor %}{% endif %} Purpose of your domain: +{% if requires_feb_questions %} +{{ purpose_label }} {{ domain_request.purpose }} +Target time frame: +{% if domain_request.has_target_time_frame %} +{{ domain_request.time_frame_details }} +{% else %} +No +{% endif %} +Interagency initiative: +{% if domain_request.is_interagency_initiative %} +{{ domain_request.interagency_initiative_details }} +{% else %} +No +{% endif %} +{% else %} +{{ domain_request.purpose }} +{% endif %} +{% if requires_feb_questions %} +EOP contact: +{% if domain_request.working_with_eop %} +{{ domain_request.eop_contact.first_name }} {{ domain_request.eop_contact.last_name }} +{{ domain_request.eop_contact.email }} +{% else %} +No +{% endif %} +{% endif %} {% if domain_request.anything_else %} Additional details: {{ domain_request.anything_else }} diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html index 53ad36a3f..51b1ce7cd 100644 --- a/src/registrar/templates/includes/portfolio_request_review_steps.html +++ b/src/registrar/templates/includes/portfolio_request_review_steps.html @@ -10,19 +10,19 @@ {% if step == Step.REQUESTING_ENTITY %} {% with title=form_titles|get_item:step %} {% if domain_request.sub_organization %} - {% include "includes/summary_item.html" with value=domain_request.sub_organization edit_link=domain_request_url %} + {% include "includes/summary_item.html" with title=title value=domain_request.sub_organization editable=is_editable edit_link=domain_request_url %} {% comment %} We don't have city or state_territory for suborganizations yet, so no data should display {% endcomment %} {% elif domain_request.requesting_entity_is_suborganization %} - {% include "includes/summary_item.html" with value=domain_request.requested_suborganization edit_link=domain_request_url %} + {% include "includes/summary_item.html" with title=title value=domain_request.requested_suborganization editable=is_editable edit_link=domain_request_url %}{{domain_request.suborganization_city}}, {{domain_request.suborganization_state_territory}}
{% elif domain_request.requesting_entity_is_portfolio %} - {% include "includes/summary_item.html" with value=domain_request.portfolio.organization_name edit_link=domain_request_url %} + {% include "includes/summary_item.html" with title=title value=domain_request.portfolio.organization_name editable=is_editable edit_link=domain_request_url %} {% if domain_request.portfolio.city and domain_request.portfolio.state_territory %}{{domain_request.portfolio.city}}, {{domain_request.portfolio.state_territory}}
{% endif %} {% else %} {% with value="Incomplete"|safe %} - {% include "includes/summary_item.html" with edit_link=domain_request_url %} + {% include "includes/summary_item.html" with title=title editable=is_editable edit_link=domain_request_url %} {% endwith %} {% endif %} {% endwith %} @@ -53,18 +53,78 @@ {% endfor %} {% endif %} + {% if requires_feb_questions %} +Incomplete
+ {% elif domain_request.feb_naming_requirements %} +Yes
+ {% else %} +No
+{{domain_request.feb_naming_requirements_details}}
+ {% endif %} + {% endif %} {% endif %} {% if step == Step.PURPOSE %} - {% with title=form_titles|get_item:step value=domain_request.purpose|default:"Incomplete"|safe %} - {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %} - {% endwith %} + {% if requires_feb_questions %} + {% with title=form_titles|get_item:step %} + {% include "includes/summary_item.html" with title=title value=" " heading_level=heading_level editable=is_editable edit_link=domain_request_url %} + {% endwith %} +{{purpose_label}}
+{{domain_request.purpose}}
+ {% else %} +Incomplete
+ {% endif %} +Incomplete
+ {% elif domain_request.has_timeframe %} +{{domain_request.time_frame_details}}
+ {% else %} +No
+ {% endif %} +Incomplete
+ {% elif domain_request.is_interagency_initiative %} +{{domain_request.interagency_initiative_details}}
+ {% else %} +No
+ {% endif %} + {% else %} + {% with title=form_titles|get_item:step value=domain_request.purpose|default:"Incomplete"|safe %} + {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %} + {% endwith %} + {% endif %} {% endif %} {% if step == Step.ADDITIONAL_DETAILS %} - {% with title=form_titles|get_item:step value=domain_request.anything_else|default:"None" %} - {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %} - {% endwith %} + {% if requires_feb_questions %} + {% with title=form_titles|get_item:step %} + {% include "includes/summary_item.html" with title=title value=" " heading_level=heading_level editable=is_editable edit_link=domain_request_url %} + {% endwith %} +Incomplete
+ {% elif domain_request.working_with_eop %} +{{domain_request.eop_stakeholder_first_name}} {{domain_request.eop_stakeholder_last_name}}
+ {% else %} +No
+ {% endif %} +{{domain_request.anything_else}}
+ {% else %} +None
+ {% endif %} + {% else %} + {% with title=form_titles|get_item:step value=domain_request.anything_else|default:"None" %} + {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %} + {% endwith %} + {% endif %} {% endif %} {% if step == Step.REQUIREMENTS %} diff --git a/src/registrar/templates/portfolio_domain_request_additional_details.html b/src/registrar/templates/portfolio_domain_request_additional_details.html index d7d53dd1a..9f005692e 100644 --- a/src/registrar/templates/portfolio_domain_request_additional_details.html +++ b/src/registrar/templates/portfolio_domain_request_additional_details.html @@ -6,60 +6,62 @@ {% endblock %} {% block form_fields %} - {% if requires_feb_questions %} + {% include "includes/required_fields.html" %} + {% if requires_feb_questions %} +Working with the EOP is not required to request a .gov domain.
++ Select one. * +
+ {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" add_aria_describedby="working-with-eop--requirement" add_legend_heading="Are you working with someone in the Executive Office of the President (EOP) on this request?" %} + {% input_with_errors forms.0.working_with_eop %} + {% endwith %} + ++ Provide the name of the person you're working with. * +
+ {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} + {% input_with_errors forms.1.first_name %} + {% input_with_errors forms.1.last_name %} + {% endwith %} +- Select one. * -
- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} - {% input_with_errors forms.0.working_with_eop %} - {% endwith %} ++ Select one. * +
+ {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" add_legend_heading="Is there anything else you'd like us to know about your domain request?"%} + {% input_with_errors forms.2.has_anything_else_text %} + {% endwith %} -- Provide the name and email of the person you're working with.* -
- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} - {% input_with_errors forms.1.first_name %} - {% input_with_errors forms.1.last_name %} - {% input_with_errors forms.1.email %} - {% endwith %} -- Select one. * -
- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} - {% input_with_errors forms.2.has_anything_else_text %} - {% endwith %} - -- Provide details below * -
- {% with add_label_class="usa-sr-only" attr_required="required" attr_maxlength="2000" %} - {% input_with_errors forms.3.anything_else %} - {% endwith %} -This question is optional.
- {% with attr_maxlength=2000 add_label_class="usa-sr-only" %} - {% input_with_errors forms.0.anything_else %} - {% endwith %} ++ Provide details below. * +
+ {% with add_label_class="usa-sr-only" attr_required="required" attr_maxlength="2000" %} + {% input_with_errors forms.3.anything_else %} + {% endwith %}This question is optional.
+ {% with attr_maxlength=2000 add_label_class="usa-sr-only" %} + {% input_with_errors forms.3.anything_else %} + {% endwith %} +