From f918720383561bcad51f6ad6a66a3fe8245fa885 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 21 Nov 2024 14:57:48 -0800
Subject: [PATCH 001/231] Add screenreader text to no other contacts form
---
src/registrar/forms/domain_request_wizard.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index c7f5571af..a619aec26 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -733,7 +733,14 @@ class NoOtherContactsForm(BaseDeletableRegistrarForm):
required=True,
# label has to end in a space to get the label_suffix to show
label=("No other employees rationale"),
- widget=forms.Textarea(),
+ widget=forms.Textarea(
+ attrs={
+ "aria-label": "You don’t need to provide names of other employees now, \
+ but it may slow down our assessment of your eligibility. Describe \
+ why there are no other employees who can help verify your request. \
+ You can enter up to 1000 characters."
+ }
+ ),
validators=[
MaxLengthValidator(
1000,
From e76571eb50d4eead1429aa936ff96b48259172d2 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 21 Nov 2024 17:05:08 -0800
Subject: [PATCH 002/231] Remove unused legends from radio groups
---
src/registrar/forms/domain_request_wizard.py | 1 +
.../forms/utility/wizard_form_helper.py | 10 +++++-
.../templates/django/forms/label.html | 36 +++++++++++--------
.../templates/includes/input_with_errors.html | 6 +++-
src/registrar/templatetags/field_helpers.py | 1 +
5 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index a619aec26..5d8f23057 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -544,6 +544,7 @@ class OtherContactsYesNoForm(BaseYesNoForm):
"""The yes/no field for the OtherContacts form."""
form_choices = ((True, "Yes, I can name other employees."), (False, "No. (We’ll ask you to explain why.)"))
+ title_label = "Are there other employees who can help verify your request?"
field_name = "has_other_contacts"
@property
diff --git a/src/registrar/forms/utility/wizard_form_helper.py b/src/registrar/forms/utility/wizard_form_helper.py
index eedf5839b..22c70b010 100644
--- a/src/registrar/forms/utility/wizard_form_helper.py
+++ b/src/registrar/forms/utility/wizard_form_helper.py
@@ -239,6 +239,10 @@ class BaseYesNoForm(RegistrarForm):
# Default form choice mapping. Default is suitable for most cases.
form_choices = ((True, "Yes"), (False, "No"))
+ # Option to append question to aria label for screenreader accessibility.
+ # Not added by default.
+ aria_label = ""
+
def __init__(self, *args, **kwargs):
"""Extend the initialization of the form from RegistrarForm __init__"""
super().__init__(*args, **kwargs)
@@ -256,7 +260,11 @@ class BaseYesNoForm(RegistrarForm):
coerce=lambda x: x.lower() == "true" if x is not None else None,
choices=self.form_choices,
initial=self.get_initial_value(),
- widget=forms.RadioSelect,
+ widget=forms.RadioSelect(
+ attrs={
+ "aria-label": self.aria_label
+ }
+ ),
error_messages={
"required": self.required_error_message,
},
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index 545ccf781..e4d7842fa 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -1,19 +1,25 @@
-<{{ label_tag }}
- class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
- {% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
->
- {% if span_for_text %}
- {{ field.label }}
- {% else %}
- {{ field.label }}
- {% endif %}
+
+{% if not type == "radio" and not label_tag == "legend" %}
+ <{{ label_tag }}
+ class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
+ {% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
+ >
+{% endif %}
- {% if widget.attrs.required %}
-
- {% if field.label == "Is your organization an election office?" or field.label == "What .gov domain do you want?" or field.label == "I read and agree to the requirements for operating a .gov domain." or field.label == "Please explain why there are no other employees from your organization we can contact to help us assess your eligibility for a .gov domain." %}
+ {% if span_for_text %}
+ {{ field.label }}
{% else %}
- *
+ {{ field.label }}
{% endif %}
- {% endif %}
-{{ label_tag }}>
+ {% if widget.attrs.required %}
+
+ {% if field.label == "Is your organization an election office?" or field.label == "What .gov domain do you want?" or field.label == "I read and agree to the requirements for operating a .gov domain." or field.label == "Please explain why there are no other employees from your organization we can contact to help us assess your eligibility for a .gov domain." %}
+ {% else %}
+ *
+ {% endif %}
+ {% endif %}
+
+{% if not type == "radio" and not label_tag == "legend" %}
+ {{ label_tag }}>
+{% endif %}
diff --git a/src/registrar/templates/includes/input_with_errors.html b/src/registrar/templates/includes/input_with_errors.html
index d1e53968e..d239954a0 100644
--- a/src/registrar/templates/includes/input_with_errors.html
+++ b/src/registrar/templates/includes/input_with_errors.html
@@ -68,7 +68,11 @@ error messages, if necessary.
{% endif %}
{# this is the input field, itself #}
- {% include widget.template_name %}
+ {% with aria_label=aria_label %}
+ {% include widget.template_name %}
+ {% endwith %}
+
+
{% if append_gov %}
.gov
diff --git a/src/registrar/templatetags/field_helpers.py b/src/registrar/templatetags/field_helpers.py
index 8a80a75b9..d2bca13fb 100644
--- a/src/registrar/templatetags/field_helpers.py
+++ b/src/registrar/templatetags/field_helpers.py
@@ -169,5 +169,6 @@ def input_with_errors(context, field=None): # noqa: C901
) # -> {"widget": {"name": ...}}
context["widget"] = widget["widget"]
+ print("context: ", context)
return context
From 36b78e9cea8207cf14b64c11271a3bbe6033464a Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Fri, 22 Nov 2024 11:43:31 -0800
Subject: [PATCH 003/231] Refactor legends from two separate legends to one
combined legend
---
.../forms/utility/wizard_form_helper.py | 5 +++--
.../templates/django/forms/label.html | 21 +++++++++----------
.../domain_request_other_contacts.html | 11 +++-------
src/registrar/templatetags/field_helpers.py | 6 ++++++
4 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/src/registrar/forms/utility/wizard_form_helper.py b/src/registrar/forms/utility/wizard_form_helper.py
index 22c70b010..d48f7af64 100644
--- a/src/registrar/forms/utility/wizard_form_helper.py
+++ b/src/registrar/forms/utility/wizard_form_helper.py
@@ -241,7 +241,8 @@ class BaseYesNoForm(RegistrarForm):
# Option to append question to aria label for screenreader accessibility.
# Not added by default.
- aria_label = ""
+ title_label = ""
+ aria_label = title_label.join("")
def __init__(self, *args, **kwargs):
"""Extend the initialization of the form from RegistrarForm __init__"""
@@ -262,7 +263,7 @@ class BaseYesNoForm(RegistrarForm):
initial=self.get_initial_value(),
widget=forms.RadioSelect(
attrs={
- "aria-label": self.aria_label
+ # "aria-label": self.title_label
}
),
error_messages={
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index e4d7842fa..eb9604dec 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -1,25 +1,24 @@
-{% if not type == "radio" and not label_tag == "legend" %}
- <{{ label_tag }}
- class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
- {% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
- >
-{% endif %}
-
+<{{ label_tag }}
+ class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
+ {% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
+>
+ {% if legend_label %}
+
{{ legend_label }}
+ {% else %}
{% if span_for_text %}
{{ field.label }}
{% else %}
{{ field.label }}
{% endif %}
+ {% endif %}
{% if widget.attrs.required %}
- {% if field.label == "Is your organization an election office?" or field.label == "What .gov domain do you want?" or field.label == "I read and agree to the requirements for operating a .gov domain." or field.label == "Please explain why there are no other employees from your organization we can contact to help us assess your eligibility for a .gov domain." %}
+ {% if field.label == "Is your organization an election office?" or field.label == "What .gov domain do you want?" or field.label == "I read and agree to the requirements for operating a .gov domain." or field.label == "Please explain why there are no other employees from your organization we can contact to help us assess your eligibility for a .gov domain." or field.label == "Has other contacts" %}
{% else %}
*
{% endif %}
{% endif %}
-{% if not type == "radio" and not label_tag == "legend" %}
- {{ label_tag }}>
-{% endif %}
+{{ label_tag }}>
diff --git a/src/registrar/templates/domain_request_other_contacts.html b/src/registrar/templates/domain_request_other_contacts.html
index 72e4abd8b..93fafe872 100644
--- a/src/registrar/templates/domain_request_other_contacts.html
+++ b/src/registrar/templates/domain_request_other_contacts.html
@@ -17,17 +17,12 @@
{% endblock %}
{% block form_fields %}
-
-
- Are there other employees who can help verify your request?
-
-
- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %}
+
+ {% with add_class="usa-radio__input--tile" add_legend_label="Are there other employees who can help verify your request?" %}
{% input_with_errors forms.0.has_other_contacts %}
{% endwith %}
{# forms.0 is a small yes/no form that toggles the visibility of "other contact" formset #}
-
-
+
{% include "includes/required_fields.html" %}
diff --git a/src/registrar/templatetags/field_helpers.py b/src/registrar/templatetags/field_helpers.py
index d2bca13fb..31ceb1072 100644
--- a/src/registrar/templatetags/field_helpers.py
+++ b/src/registrar/templatetags/field_helpers.py
@@ -57,6 +57,7 @@ def input_with_errors(context, field=None): # noqa: C901
legend_classes = []
group_classes = []
aria_labels = []
+ legend_labels = []
# this will be converted to an attribute string
described_by = []
@@ -90,6 +91,8 @@ def input_with_errors(context, field=None): # noqa: C901
label_classes.append(value)
elif key == "add_legend_class":
legend_classes.append(value)
+ elif key == "add_legend_label":
+ legend_labels.append(value)
elif key == "add_group_class":
group_classes.append(value)
@@ -149,6 +152,9 @@ def input_with_errors(context, field=None): # noqa: C901
if legend_classes:
context["legend_classes"] = " ".join(legend_classes)
+ if legend_labels:
+ context["legend_label"] = " ".join(legend_labels)
+
if group_classes:
context["group_classes"] = " ".join(group_classes)
From 3f66face606cf13c916490b1d5bc1e6fdbdded12 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Fri, 22 Nov 2024 11:43:54 -0800
Subject: [PATCH 004/231] Remove outdated comment
---
src/registrar/templates/django/forms/label.html | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index eb9604dec..27407247b 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -1,4 +1,3 @@
-
<{{ label_tag }}
class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
{% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
From 394a04d47d173978b03a3ab2ce569dc55681f118 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Mon, 2 Dec 2024 12:28:39 -0800
Subject: [PATCH 005/231] Save changes
---
src/registrar/templates/django/forms/label.html | 3 +++
.../templates/domain_request_additional_details.html | 9 ++++++---
src/registrar/templatetags/field_helpers.py | 1 -
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index 27407247b..3fbb6b7af 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -4,6 +4,9 @@
>
{% if legend_label %}
{{ legend_label }}
+ {% if widget.attrs.id == 'id_additional_details-has_cisa_representative' %}
+
.gov is managed by the Cybersecurity and Infrastructure Security Agency. CISA has 10 regions that some organizations choose to work with. Regional representatives use titles like protective security advisors, cyber security advisors, or election security advisors.
+ {% endif %}
{% else %}
{% if span_for_text %}
{{ field.label }}
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index 2a581bbd2..454fbc8e4 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -10,14 +10,17 @@
{% block form_fields %}
-
+
+
+ .gov is managed by the Cybersecurity and Infrastructure Security Agency. CISA has 10 regions that some organizations choose to work with. Regional representatives use titles like protective security advisors, cyber security advisors, or election security advisors.
+
Select one. *
- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %}
+ {% with add_class="usa-radio__input--tile" add_legend_label="Are you working with a CISA regional representative on your domain request?" %}
{% input_with_errors forms.0.has_cisa_representative %}
{% endwith %}
{# forms.0 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
diff --git a/src/registrar/templatetags/field_helpers.py b/src/registrar/templatetags/field_helpers.py
index 31ceb1072..6cf671931 100644
--- a/src/registrar/templatetags/field_helpers.py
+++ b/src/registrar/templatetags/field_helpers.py
@@ -175,6 +175,5 @@ def input_with_errors(context, field=None): # noqa: C901
) # -> {"widget": {"name": ...}}
context["widget"] = widget["widget"]
- print("context: ", context)
return context
From 7b1e2662dd9776cad7f236295223eb15fcfa5768 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Tue, 3 Dec 2024 10:43:30 -0800
Subject: [PATCH 006/231] Add select instructions to radio fields
---
src/registrar/templates/django/forms/label.html | 13 ++++++++-----
.../domain_request_additional_details.html | 3 ---
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index 3fbb6b7af..422186522 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -15,12 +15,15 @@
{% endif %}
{% endif %}
- {% if widget.attrs.required %}
+ {% if widget.attrs.required %}
+
+ {% if field.widget_type == 'radioselect' %}
+ Select one. *
- {% if field.label == "Is your organization an election office?" or field.label == "What .gov domain do you want?" or field.label == "I read and agree to the requirements for operating a .gov domain." or field.label == "Please explain why there are no other employees from your organization we can contact to help us assess your eligibility for a .gov domain." or field.label == "Has other contacts" %}
- {% else %}
- *
- {% endif %}
+ {% elif field.label == "Is your organization an election office?" or field.label == "What .gov domain do you want?" or field.label == "I read and agree to the requirements for operating a .gov domain." or field.label == "Please explain why there are no other employees from your organization we can contact to help us assess your eligibility for a .gov domain." or field.label == "Has other contacts" %}
+ {% else %}
+ *
{% endif %}
+ {% endif %}
{{ label_tag }}>
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index 454fbc8e4..d09ec6966 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -15,9 +15,6 @@
.gov is managed by the Cybersecurity and Infrastructure Security Agency. CISA has 10 regions that some organizations choose to work with. Regional representatives use titles like protective security advisors, cyber security advisors, or election security advisors.
-->
- .gov is managed by the Cybersecurity and Infrastructure Security Agency. CISA has 10 regions that some organizations choose to work with. Regional representatives use titles like protective security advisors, cyber security advisors, or election security advisors.
-
-
Select one. *
{% with add_class="usa-radio__input--tile" add_legend_label="Are you working with a CISA regional representative on your domain request?" %}
From ab05cb7e4674e261de8154ae63a958b26fb91638 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Tue, 3 Dec 2024 12:16:20 -0800
Subject: [PATCH 007/231] Add select text to radios
---
src/registrar/assets/sass/_theme/_typography.scss | 3 +++
src/registrar/templates/domain_request_additional_details.html | 1 -
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/registrar/assets/sass/_theme/_typography.scss b/src/registrar/assets/sass/_theme/_typography.scss
index d815ef6dd..3b3958b9b 100644
--- a/src/registrar/assets/sass/_theme/_typography.scss
+++ b/src/registrar/assets/sass/_theme/_typography.scss
@@ -27,6 +27,9 @@ h2 {
.usa-form,
.usa-form fieldset {
font-size: 1rem;
+ legend em {
+ font-size: 1rem;
+ }
}
.p--blockquote {
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index d09ec6966..74a024c9b 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -16,7 +16,6 @@
-->
- Select one. *
{% with add_class="usa-radio__input--tile" add_legend_label="Are you working with a CISA regional representative on your domain request?" %}
{% input_with_errors forms.0.has_cisa_representative %}
{% endwith %}
From 1beb0947f7273ce200adc62b9851c0fef60feefb Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Tue, 3 Dec 2024 14:26:29 -0800
Subject: [PATCH 008/231] Refactor additional details radio
---
src/registrar/assets/sass/_theme/_typography.scss | 1 +
.../templates/domain_request_additional_details.html | 12 +-----------
2 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/src/registrar/assets/sass/_theme/_typography.scss b/src/registrar/assets/sass/_theme/_typography.scss
index 3b3958b9b..c60b7d802 100644
--- a/src/registrar/assets/sass/_theme/_typography.scss
+++ b/src/registrar/assets/sass/_theme/_typography.scss
@@ -29,6 +29,7 @@ h2 {
font-size: 1rem;
legend em {
font-size: 1rem;
+ margin-bottom: 0.5rem;
}
}
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index 74a024c9b..386a7a4af 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -10,11 +10,6 @@
{% block form_fields %}
-
-
{% with add_class="usa-radio__input--tile" add_legend_label="Are you working with a CISA regional representative on your domain request?" %}
{% input_with_errors forms.0.has_cisa_representative %}
@@ -30,13 +25,8 @@
-
- Is there anything else you’d like us to know about your domain request?
-
-
- Select one. *
- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %}
+ {% with add_class="usa-radio__input--tile" add_legend_label="Is there anything else you’d like us to know about your domain request?" %}
{% input_with_errors forms.2.has_anything_else_text %}
{% endwith %}
{# forms.2 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
From 780b53b3fca83544cfa3ef38eaa9e40982a6fe62 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Tue, 3 Dec 2024 14:31:57 -0800
Subject: [PATCH 009/231] Moved required fields text in other contacts form
---
src/registrar/templates/domain_request_other_contacts.html | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/registrar/templates/domain_request_other_contacts.html b/src/registrar/templates/domain_request_other_contacts.html
index 93fafe872..035fe442b 100644
--- a/src/registrar/templates/domain_request_other_contacts.html
+++ b/src/registrar/templates/domain_request_other_contacts.html
@@ -9,7 +9,7 @@
We typically don’t reach out to these employees , but if contact is necessary, our practice is to coordinate with you first.
-
+ {% include "includes/required_fields.html" %}
{% endblock %}
{% block form_required_fields_help_text %}
@@ -25,7 +25,6 @@
- {% include "includes/required_fields.html" %}
{{ forms.1.management_form }}
{# forms.1 is a formset and this iterates over its forms #}
{% for form in forms.1.forms %}
From 8154d25873208a08234c34490253ecdbb8d867a3 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Tue, 3 Dec 2024 14:55:25 -0800
Subject: [PATCH 010/231] Add aria label for additional details form
---
src/registrar/forms/domain_request_wizard.py | 7 ++++++-
src/registrar/templates/django/forms/label.html | 2 +-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 5d8f23057..5ce50dc0c 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -789,7 +789,12 @@ class AnythingElseForm(BaseDeletableRegistrarForm):
anything_else = forms.CharField(
required=True,
label="Anything else?",
- widget=forms.Textarea(),
+ widget=forms.Textarea(
+ attrs={
+ "aria-label": "Is there anything else you’d like us to know about your domain request? Provide details below. \
+ You can enter up to 2000 characters"
+ }
+ ),
validators=[
MaxLengthValidator(
2000,
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index 422186522..2852ce2ba 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -3,7 +3,7 @@
{% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
>
{% if legend_label %}
-
{{ legend_label }}
+
{{ legend_label }}
{% if widget.attrs.id == 'id_additional_details-has_cisa_representative' %}
.gov is managed by the Cybersecurity and Infrastructure Security Agency. CISA has 10 regions that some organizations choose to work with. Regional representatives use titles like protective security advisors, cyber security advisors, or election security advisors.
{% endif %}
From b9ea3d884665f863f18cc3852af6f1de6b97a469 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 11:31:58 -0800
Subject: [PATCH 011/231] Save changes
---
src/registrar/forms/domain_request_wizard.py | 7 +------
.../templates/domain_request_additional_details.html | 2 +-
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 5ce50dc0c..5d8f23057 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -789,12 +789,7 @@ class AnythingElseForm(BaseDeletableRegistrarForm):
anything_else = forms.CharField(
required=True,
label="Anything else?",
- widget=forms.Textarea(
- attrs={
- "aria-label": "Is there anything else you’d like us to know about your domain request? Provide details below. \
- You can enter up to 2000 characters"
- }
- ),
+ widget=forms.Textarea(),
validators=[
MaxLengthValidator(
2000,
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index 386a7a4af..6e28e5869 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -34,7 +34,7 @@
Provide details below. *
- {% with attr_maxlength=2000 add_label_class="usa-sr-only" %}
+ {% with attr_maxlength=2000 add_label_class="usa-sr-only" add_legend_class="usa-sr-only" add_legend_label="Is there anything else you’d like us to know about your domain request?" add_aria_label="Provide details below. You can enter up to 2000 characters" %}
{% input_with_errors forms.3.anything_else %}
{% endwith %}
{# forms.3 is a form for inputting the e-mail of a cisa representative #}
From 6ff3901c91f021e123feba9ef04328c35988e3b1 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 14:43:41 -0800
Subject: [PATCH 012/231] Add aria label to anything else text field
---
src/registrar/forms/domain_request_wizard.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 5d8f23057..ca1313184 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -789,7 +789,12 @@ class AnythingElseForm(BaseDeletableRegistrarForm):
anything_else = forms.CharField(
required=True,
label="Anything else?",
- widget=forms.Textarea(),
+ widget=forms.Textarea(
+ attrs={
+ "aria-label": "Is there anything else you’d like us to know about your domain request? \
+ Provide details below. You can enter up to 2000 characters"
+ }
+ ),
validators=[
MaxLengthValidator(
2000,
From 4671c8967fcbf1d3ae98c8b53e2425300abe9f95 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 15:10:57 -0800
Subject: [PATCH 013/231] Refactor legend heading
---
src/registrar/assets/sass/_theme/_base.scss | 8 ++++++++
src/registrar/assets/sass/_theme/_typography.scss | 3 +--
src/registrar/templates/django/forms/label.html | 4 ++--
.../templates/domain_request_additional_details.html | 8 ++++----
.../templates/domain_request_other_contacts.html | 2 +-
src/registrar/templatetags/field_helpers.py | 10 +++++-----
6 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/registrar/assets/sass/_theme/_base.scss b/src/registrar/assets/sass/_theme/_base.scss
index db1599621..9a6818f09 100644
--- a/src/registrar/assets/sass/_theme/_base.scss
+++ b/src/registrar/assets/sass/_theme/_base.scss
@@ -149,6 +149,14 @@ footer {
color: color('primary');
}
+.usa-footer {
+ margin-bottom: 0.5rem;
+}
+
+.usa-radio {
+ margin-top: 1rem;
+}
+
abbr[title] {
// workaround for underlining abbr element
border-bottom: none;
diff --git a/src/registrar/assets/sass/_theme/_typography.scss b/src/registrar/assets/sass/_theme/_typography.scss
index c60b7d802..952fc6dad 100644
--- a/src/registrar/assets/sass/_theme/_typography.scss
+++ b/src/registrar/assets/sass/_theme/_typography.scss
@@ -27,9 +27,8 @@ h2 {
.usa-form,
.usa-form fieldset {
font-size: 1rem;
- legend em {
+ .usa-legend {
font-size: 1rem;
- margin-bottom: 0.5rem;
}
}
diff --git a/src/registrar/templates/django/forms/label.html b/src/registrar/templates/django/forms/label.html
index 2852ce2ba..3783c0fef 100644
--- a/src/registrar/templates/django/forms/label.html
+++ b/src/registrar/templates/django/forms/label.html
@@ -2,8 +2,8 @@
class="{% if label_classes %} {{ label_classes }}{% endif %}{% if label_tag == 'legend' %} {{ legend_classes }}{% endif %}"
{% if not field.use_fieldset %}for="{{ widget.attrs.id }}"{% endif %}
>
- {% if legend_label %}
-
{{ legend_label }}
+ {% if legend_heading %}
+
{{ legend_heading }}
{% if widget.attrs.id == 'id_additional_details-has_cisa_representative' %}
.gov is managed by the Cybersecurity and Infrastructure Security Agency. CISA has 10 regions that some organizations choose to work with. Regional representatives use titles like protective security advisors, cyber security advisors, or election security advisors.
{% endif %}
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index 6e28e5869..ba7a7f441 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -9,9 +9,9 @@
{% block form_fields %}
-
+
- {% with add_class="usa-radio__input--tile" add_legend_label="Are you working with a CISA regional representative on your domain request?" %}
+ {% with add_class="usa-radio__input--tile" add_legend_heading="Are you working with a CISA regional representative on your domain request?" %}
{% input_with_errors forms.0.has_cisa_representative %}
{% endwith %}
{# forms.0 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
@@ -26,7 +26,7 @@
- {% with add_class="usa-radio__input--tile" add_legend_label="Is there anything else you’d like us to know about your domain request?" %}
+ {% with add_class="usa-radio__input--tile" 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 %}
{# forms.2 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
@@ -34,7 +34,7 @@
Provide details below. *
- {% with attr_maxlength=2000 add_label_class="usa-sr-only" add_legend_class="usa-sr-only" add_legend_label="Is there anything else you’d like us to know about your domain request?" add_aria_label="Provide details below. You can enter up to 2000 characters" %}
+ {% with attr_maxlength=2000 add_label_class="usa-sr-only" add_legend_class="usa-sr-only" add_legend_heading="Is there anything else you’d like us to know about your domain request?" add_aria_label="Provide details below. You can enter up to 2000 characters" %}
{% input_with_errors forms.3.anything_else %}
{% endwith %}
{# forms.3 is a form for inputting the e-mail of a cisa representative #}
diff --git a/src/registrar/templates/domain_request_other_contacts.html b/src/registrar/templates/domain_request_other_contacts.html
index 035fe442b..b3c1be8b4 100644
--- a/src/registrar/templates/domain_request_other_contacts.html
+++ b/src/registrar/templates/domain_request_other_contacts.html
@@ -18,7 +18,7 @@
{% block form_fields %}
- {% with add_class="usa-radio__input--tile" add_legend_label="Are there other employees who can help verify your request?" %}
+ {% with add_class="usa-radio__input--tile" add_legend_heading="Are there other employees who can help verify your request?" %}
{% input_with_errors forms.0.has_other_contacts %}
{% endwith %}
{# forms.0 is a small yes/no form that toggles the visibility of "other contact" formset #}
diff --git a/src/registrar/templatetags/field_helpers.py b/src/registrar/templatetags/field_helpers.py
index 6cf671931..a1f662fba 100644
--- a/src/registrar/templatetags/field_helpers.py
+++ b/src/registrar/templatetags/field_helpers.py
@@ -57,7 +57,7 @@ def input_with_errors(context, field=None): # noqa: C901
legend_classes = []
group_classes = []
aria_labels = []
- legend_labels = []
+ legend_headings = []
# this will be converted to an attribute string
described_by = []
@@ -91,8 +91,8 @@ def input_with_errors(context, field=None): # noqa: C901
label_classes.append(value)
elif key == "add_legend_class":
legend_classes.append(value)
- elif key == "add_legend_label":
- legend_labels.append(value)
+ elif key == "add_legend_heading":
+ legend_headings.append(value)
elif key == "add_group_class":
group_classes.append(value)
@@ -152,8 +152,8 @@ def input_with_errors(context, field=None): # noqa: C901
if legend_classes:
context["legend_classes"] = " ".join(legend_classes)
- if legend_labels:
- context["legend_label"] = " ".join(legend_labels)
+ if legend_headings:
+ context["legend_heading"] = " ".join(legend_headings)
if group_classes:
context["group_classes"] = " ".join(group_classes)
From 6854310449f81c28678e88022441cb44a3f8921c Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 15:55:16 -0800
Subject: [PATCH 014/231] Refactor how usa-legend is assigned
---
src/registrar/assets/sass/_theme/_base.scss | 1 +
src/registrar/templates/domain_request_additional_details.html | 2 +-
src/registrar/templatetags/field_helpers.py | 3 ---
3 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/registrar/assets/sass/_theme/_base.scss b/src/registrar/assets/sass/_theme/_base.scss
index 9a6818f09..f6a9eef90 100644
--- a/src/registrar/assets/sass/_theme/_base.scss
+++ b/src/registrar/assets/sass/_theme/_base.scss
@@ -155,6 +155,7 @@ footer {
.usa-radio {
margin-top: 1rem;
+ font-size: 1.06rem;
}
abbr[title] {
diff --git a/src/registrar/templates/domain_request_additional_details.html b/src/registrar/templates/domain_request_additional_details.html
index ba7a7f441..86fa79fa3 100644
--- a/src/registrar/templates/domain_request_additional_details.html
+++ b/src/registrar/templates/domain_request_additional_details.html
@@ -11,7 +11,7 @@
- {% with add_class="usa-radio__input--tile" add_legend_heading="Are you working with a CISA regional representative on your domain request?" %}
+ {% with add_class="usa-radio__input--tile" add_legend_class="margin-top-0" add_legend_heading="Are you working with a CISA regional representative on your domain request?" %}
{% input_with_errors forms.0.has_cisa_representative %}
{% endwith %}
{# forms.0 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
diff --git a/src/registrar/templatetags/field_helpers.py b/src/registrar/templatetags/field_helpers.py
index a1f662fba..426caf9bc 100644
--- a/src/registrar/templatetags/field_helpers.py
+++ b/src/registrar/templatetags/field_helpers.py
@@ -119,9 +119,6 @@ def input_with_errors(context, field=None): # noqa: C901
else:
context["label_tag"] = "label"
- if field.use_fieldset:
- label_classes.append("usa-legend")
-
if field.widget_type == "checkbox":
label_classes.append("usa-checkbox__label")
elif not field.use_fieldset:
From 5b2ecbcf8520c50927bd8d6c17881e7b1842f5cc Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 16:08:59 -0800
Subject: [PATCH 015/231] Remove unused param
---
src/registrar/forms/domain_request_wizard.py | 1 -
src/registrar/forms/utility/wizard_form_helper.py | 11 +----------
2 files changed, 1 insertion(+), 11 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 4a0403e08..5ec8deb24 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -547,7 +547,6 @@ class OtherContactsYesNoForm(BaseYesNoForm):
"""The yes/no field for the OtherContacts form."""
form_choices = ((True, "Yes, I can name other employees."), (False, "No. (We’ll ask you to explain why.)"))
- title_label = "Are there other employees who can help verify your request?"
field_name = "has_other_contacts"
@property
diff --git a/src/registrar/forms/utility/wizard_form_helper.py b/src/registrar/forms/utility/wizard_form_helper.py
index d48f7af64..e87998372 100644
--- a/src/registrar/forms/utility/wizard_form_helper.py
+++ b/src/registrar/forms/utility/wizard_form_helper.py
@@ -239,11 +239,6 @@ class BaseYesNoForm(RegistrarForm):
# Default form choice mapping. Default is suitable for most cases.
form_choices = ((True, "Yes"), (False, "No"))
- # Option to append question to aria label for screenreader accessibility.
- # Not added by default.
- title_label = ""
- aria_label = title_label.join("")
-
def __init__(self, *args, **kwargs):
"""Extend the initialization of the form from RegistrarForm __init__"""
super().__init__(*args, **kwargs)
@@ -261,11 +256,7 @@ class BaseYesNoForm(RegistrarForm):
coerce=lambda x: x.lower() == "true" if x is not None else None,
choices=self.form_choices,
initial=self.get_initial_value(),
- widget=forms.RadioSelect(
- attrs={
- # "aria-label": self.title_label
- }
- ),
+ widget=forms.RadioSelect(),
error_messages={
"required": self.required_error_message,
},
From 762bda225ad85ecb7154fc44c1d58045c2162c46 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 16:10:41 -0800
Subject: [PATCH 016/231] Remove unused change
---
src/registrar/assets/src/sass/_theme/_base.scss | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/registrar/assets/src/sass/_theme/_base.scss b/src/registrar/assets/src/sass/_theme/_base.scss
index dd1c375d9..62f9f436e 100644
--- a/src/registrar/assets/src/sass/_theme/_base.scss
+++ b/src/registrar/assets/src/sass/_theme/_base.scss
@@ -149,10 +149,6 @@ footer {
color: color('primary');
}
-.usa-footer {
- margin-bottom: 0.5rem;
-}
-
.usa-radio {
margin-top: 1rem;
font-size: 1.06rem;
From 904629734c4fec4cce0dea0ec6b5b4ddb222b786 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Thu, 5 Dec 2024 16:13:41 -0800
Subject: [PATCH 017/231] Remove unused parentheses
---
src/registrar/forms/utility/wizard_form_helper.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/registrar/forms/utility/wizard_form_helper.py b/src/registrar/forms/utility/wizard_form_helper.py
index e87998372..eedf5839b 100644
--- a/src/registrar/forms/utility/wizard_form_helper.py
+++ b/src/registrar/forms/utility/wizard_form_helper.py
@@ -256,7 +256,7 @@ class BaseYesNoForm(RegistrarForm):
coerce=lambda x: x.lower() == "true" if x is not None else None,
choices=self.form_choices,
initial=self.get_initial_value(),
- widget=forms.RadioSelect(),
+ widget=forms.RadioSelect,
error_messages={
"required": self.required_error_message,
},
From 8dfb183ce08e384e4dc35664b969ad0fab54a9c9 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 9 Dec 2024 10:38:46 -0700
Subject: [PATCH 018/231] Copy template
---
.../portfolio_member_permissions.html | 143 +++++++++++++++++-
1 file changed, 142 insertions(+), 1 deletion(-)
diff --git a/src/registrar/templates/portfolio_member_permissions.html b/src/registrar/templates/portfolio_member_permissions.html
index 02d120360..ca816ee2d 100644
--- a/src/registrar/templates/portfolio_member_permissions.html
+++ b/src/registrar/templates/portfolio_member_permissions.html
@@ -1,4 +1,145 @@
{% extends 'portfolio_base.html' %}
+{% load static url_helpers %}
+{% load field_helpers %}
+
+{% block title %}Organization member{% endblock %}
+
+{% block wrapper_class %}
+ {{ block.super }} dashboard--grey-1
+{% endblock %}
+
+{% block portfolio_content %}
+
+
+{% include "includes/form_errors.html" with form=form %}
+{% block messages %}
+ {% include "includes/form_messages.html" %}
+{% endblock messages%}
+
+
+
+
+
+ Members
+
+
+ Manage member
+
+ {% comment %} Manage members {% endcomment %}
+
+ Member access and permissions
+
+
+
+
+
+{% block new_member_header %}
+Member access and permissions
+{% endblock new_member_header %}
+
+{% include "includes/required_fields.html" %}
+
+
+
+{% endblock portfolio_content%}
+
+{% comment %} {% extends 'portfolio_base.html' %}
{% load static field_helpers%}
{% block title %}Organization member {% endblock %}
@@ -39,4 +180,4 @@
-{% endblock %}
+{% endblock %} {% endcomment %}
From dffae9163e7ccaa88388bd0c3ffd082c28c994fe Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Mon, 9 Dec 2024 12:20:58 -0800
Subject: [PATCH 019/231] Update portfolio screenreader additional details form
---
.../portfolio_domain_request_additional_details.html | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/src/registrar/templates/portfolio_domain_request_additional_details.html b/src/registrar/templates/portfolio_domain_request_additional_details.html
index 5bc529243..1adc4e308 100644
--- a/src/registrar/templates/portfolio_domain_request_additional_details.html
+++ b/src/registrar/templates/portfolio_domain_request_additional_details.html
@@ -6,15 +6,9 @@
{% endblock %}
{% block form_fields %}
-
-
- Is there anything else you’d like us to know about your domain request?
-
-
-
This question is optional.
- {% with attr_maxlength=2000 add_label_class="usa-sr-only" %}
+ {% with attr_maxlength=2000 add_legend_heading="Is there anything else you’d like us to know about your domain request?" add_aria_label="This question is optional." %}
{% input_with_errors forms.0.anything_else %}
{% endwith %}
From 1764155a8ba1579a2ba0500d9a23b9b55aff59d0 Mon Sep 17 00:00:00 2001
From: Erin Song <121973038+erinysong@users.noreply.github.com>
Date: Mon, 9 Dec 2024 12:22:53 -0800
Subject: [PATCH 020/231] Revert portfolio form screenreader changes
---
.../portfolio_domain_request_additional_details.html | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/registrar/templates/portfolio_domain_request_additional_details.html b/src/registrar/templates/portfolio_domain_request_additional_details.html
index 1adc4e308..5bc529243 100644
--- a/src/registrar/templates/portfolio_domain_request_additional_details.html
+++ b/src/registrar/templates/portfolio_domain_request_additional_details.html
@@ -6,9 +6,15 @@
{% endblock %}
{% block form_fields %}
+
+
+ Is there anything else you’d like us to know about your domain request?
+
+
+
This question is optional.
- {% with attr_maxlength=2000 add_legend_heading="Is there anything else you’d like us to know about your domain request?" add_aria_label="This question is optional." %}
+ {% with attr_maxlength=2000 add_label_class="usa-sr-only" %}
{% input_with_errors forms.0.anything_else %}
{% endwith %}
From ed9d21557793f13f268577c719eaaf6f4dffd250 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 9 Dec 2024 15:03:39 -0700
Subject: [PATCH 021/231] Form structure
---
src/registrar/forms/portfolio.py | 179 +++++++++++++++---
.../models/utility/portfolio_helper.py | 17 ++
.../django/forms/widgets/multiple_input.html | 14 +-
.../portfolio_member_permissions.html | 54 ++----
src/registrar/templatetags/custom_filters.py | 8 +
5 files changed, 201 insertions(+), 71 deletions(-)
diff --git a/src/registrar/forms/portfolio.py b/src/registrar/forms/portfolio.py
index 5309f7263..65911200b 100644
--- a/src/registrar/forms/portfolio.py
+++ b/src/registrar/forms/portfolio.py
@@ -110,52 +110,169 @@ class PortfolioSeniorOfficialForm(forms.ModelForm):
return cleaned_data
-class PortfolioMemberForm(forms.ModelForm):
+class BasePortfolioMemberForm(forms.ModelForm):
+ role = forms.ChoiceField(
+ label="Select permission",
+ choices=[
+ (UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value, "Admin Access"),
+ (UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value, "Basic Access")
+ ],
+ widget=forms.RadioSelect,
+ required=True,
+ error_messages={
+ "required": "Member access level is required",
+ },
+ )
+ # Permissions for admins
+ domain_request_permissions_admin = forms.ChoiceField(
+ label="Select permission",
+ choices=[
+ (UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value, "View all requests"),
+ (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "Create and edit requests")
+ ],
+ widget=forms.RadioSelect,
+ required=False,
+ error_messages={
+ "required": "Admin domain request permission is required",
+ },
+ )
+ member_permissions_admin = forms.ChoiceField(
+ label="Select permission",
+ choices=[
+ (UserPortfolioPermissionChoices.VIEW_MEMBERS.value, "View all members"),
+ (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "Create and edit members")
+ ],
+ widget=forms.RadioSelect,
+ required=False,
+ error_messages={
+ "required": "Admin member permission is required",
+ },
+ )
+ domain_request_permissions_member = forms.ChoiceField(
+ label="Select permission",
+ choices=[
+ (UserPortfolioPermissionChoices.VIEW_MEMBERS.value, "View all members"),
+ (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "Create and edit members")
+ ],
+ widget=forms.RadioSelect,
+ required=False,
+ error_messages={
+ "required": "Basic member permission is required",
+ },
+ )
+
+ # this form dynamically shows/hides some fields, depending on what
+ # was selected prior. This toggles which field is required or not.
+ ROLE_REQUIRED_FIELDS = {
+ UserPortfolioRoleChoices.ORGANIZATION_ADMIN: [
+ "domain_request_permissions_admin",
+ "member_permissions_admin",
+ ],
+ UserPortfolioRoleChoices.ORGANIZATION_MEMBER: [
+ "domain_request_permissions_member",
+ ],
+ }
+
+ def _map_instance_to_form(self, instance):
+ """Maps model instance data to form fields"""
+ if not instance:
+ return {}
+ mapped_data = {}
+ # Map roles with priority for admin
+ if instance.roles:
+ if UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value in instance.roles:
+ mapped_data['role'] = UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value
+ else:
+ mapped_data['role'] = UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value
+
+ perms = UserPortfolioPermission.get_portfolio_permissions(instance.roles, instance.additional_permissions)
+ # Map permissions with priority for edit permissions
+ if perms:
+ if UserPortfolioPermissionChoices.EDIT_REQUESTS.value in perms:
+ mapped_data['domain_request_permissions_admin'] = UserPortfolioPermissionChoices.EDIT_REQUESTS.value
+ elif UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value in perms:
+ mapped_data['domain_request_permissions_admin'] = UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value
+
+ if UserPortfolioPermissionChoices.EDIT_MEMBERS.value in perms:
+ mapped_data['member_permissions_admin'] = UserPortfolioPermissionChoices.EDIT_MEMBERS.value
+ elif UserPortfolioPermissionChoices.VIEW_MEMBERS.value in perms:
+ mapped_data['member_permissions_admin'] = UserPortfolioPermissionChoices.VIEW_MEMBERS.value
+
+ return mapped_data
+
+ def _map_form_to_instance(self, instance):
+ """Maps form data to model instance"""
+ if not self.is_valid():
+ return
+
+ role = self.cleaned_data.get("role")
+ domain_request_permissions_member = self.cleaned_data.get("domain_request_permissions_member")
+ domain_request_permissions_admin = self.cleaned_data.get('domain_request_permissions_admin')
+ member_permissions_admin = self.cleaned_data.get('member_permissions_admin')
+
+ instance.roles = [role]
+ additional_permissions = []
+ if domain_request_permissions_member:
+ additional_permissions.append(domain_request_permissions_member)
+ elif domain_request_permissions_admin:
+ additional_permissions.append(domain_request_permissions_admin)
+
+ if member_permissions_admin:
+ additional_permissions.append(member_permissions_admin)
+
+ instance.additional_permissions = additional_permissions
+ return instance
+
+ def clean(self):
+ cleaned_data = super().clean()
+ role = cleaned_data.get("role")
+
+ # Get required fields for the selected role.
+ # Then validate all required fields for the role.
+ required_fields = self.ROLE_REQUIRED_FIELDS.get(role, [])
+ for field_name in required_fields:
+ if not cleaned_data.get(field_name):
+ self.add_error(
+ field_name,
+ self.fields.get(field_name).error_messages.get("required")
+ )
+
+ return cleaned_data
+
+
+class PortfolioMemberForm(BasePortfolioMemberForm):
"""
Form for updating a portfolio member.
"""
-
- roles = forms.MultipleChoiceField(
- choices=UserPortfolioRoleChoices.choices,
- widget=forms.SelectMultiple(attrs={"class": "usa-select"}),
- required=False,
- label="Roles",
- )
-
- additional_permissions = forms.MultipleChoiceField(
- choices=UserPortfolioPermissionChoices.choices,
- widget=forms.SelectMultiple(attrs={"class": "usa-select"}),
- required=False,
- label="Additional Permissions",
- )
-
class Meta:
model = UserPortfolioPermission
fields = [
"roles",
"additional_permissions",
]
+ def __init__(self, *args, instance=None, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.fields['role'].descriptions = {
+ "organization_admin": UserPortfolioRoleChoices.get_role_description(UserPortfolioRoleChoices.ORGANIZATION_ADMIN),
+ "organization_member": UserPortfolioRoleChoices.get_role_description(UserPortfolioRoleChoices.ORGANIZATION_MEMBER)
+ }
+ self.instance = instance
+ self.initial = self._map_instance_to_form(self.instance)
+
+ def save(self):
+ """Save form data to instance"""
+ if not self.instance:
+ self.instance = self.Meta.model()
+ self._map_form_to_instance(self.instance)
+ self.instance.save()
+ return self.instance
-class PortfolioInvitedMemberForm(forms.ModelForm):
+class PortfolioInvitedMemberForm(BasePortfolioMemberForm):
"""
Form for updating a portfolio invited member.
"""
- roles = forms.MultipleChoiceField(
- choices=UserPortfolioRoleChoices.choices,
- widget=forms.SelectMultiple(attrs={"class": "usa-select"}),
- required=False,
- label="Roles",
- )
-
- additional_permissions = forms.MultipleChoiceField(
- choices=UserPortfolioPermissionChoices.choices,
- widget=forms.SelectMultiple(attrs={"class": "usa-select"}),
- required=False,
- label="Additional Permissions",
- )
-
class Meta:
model = PortfolioInvitation
fields = [
diff --git a/src/registrar/models/utility/portfolio_helper.py b/src/registrar/models/utility/portfolio_helper.py
index 3768aa77a..60fa2170a 100644
--- a/src/registrar/models/utility/portfolio_helper.py
+++ b/src/registrar/models/utility/portfolio_helper.py
@@ -17,6 +17,23 @@ class UserPortfolioRoleChoices(models.TextChoices):
@classmethod
def get_user_portfolio_role_label(cls, user_portfolio_role):
return cls(user_portfolio_role).label if user_portfolio_role else None
+
+ @classmethod
+ def get_role_description(cls, user_portfolio_role):
+ """Returns a detailed description for a given role."""
+ descriptions = {
+ cls.ORGANIZATION_ADMIN: (
+ "Grants this member access to the organization-wide information "
+ "on domains, domain requests, and members. Domain management can be assigned separately."
+ ),
+ cls.ORGANIZATION_MEMBER: (
+ "Grants this member access to the organization. They can be given extra permissions to view all "
+ "organization domain requests and submit domain requests on behalf of the organization. Basic access "
+ "members can’t view all members of an organization or manage them. "
+ "Domain management can be assigned separately."
+ )
+ }
+ return descriptions.get(user_portfolio_role)
class UserPortfolioPermissionChoices(models.TextChoices):
diff --git a/src/registrar/templates/django/forms/widgets/multiple_input.html b/src/registrar/templates/django/forms/widgets/multiple_input.html
index 90c241366..76e19b169 100644
--- a/src/registrar/templates/django/forms/widgets/multiple_input.html
+++ b/src/registrar/templates/django/forms/widgets/multiple_input.html
@@ -1,3 +1,5 @@
+{% load static custom_filters %}
+
{% for group, options, index in widget.optgroups %}
{% if group %}
{{ group }} {% endif %}
@@ -13,7 +15,17 @@
{{ option.label }}
+ >
+ {{ option.label }}
+ {% comment %} Add a description on each, if available {% endcomment %}
+ {% if field and field.field and field.field.descriptions %}
+ {% with description=field.field.descriptions|get_dict_value:option.value %}
+ {% if description %}
+
{{ description }}
+ {% endif %}
+ {% endwith %}
+ {% endif %}
+
{% endfor %}
{% if group %}
{% endif %}
{% endfor %}
diff --git a/src/registrar/templates/portfolio_member_permissions.html b/src/registrar/templates/portfolio_member_permissions.html
index ca816ee2d..a5f1731d0 100644
--- a/src/registrar/templates/portfolio_member_permissions.html
+++ b/src/registrar/templates/portfolio_member_permissions.html
@@ -10,12 +10,6 @@
{% block portfolio_content %}
-
-{% include "includes/form_errors.html" with form=form %}
-{% block messages %}
- {% include "includes/form_messages.html" %}
-{% endblock messages%}
-
@@ -33,9 +27,7 @@
-{% block new_member_header %}
Member access and permissions
-{% endblock new_member_header %}
{% include "includes/required_fields.html" %}
@@ -45,7 +37,6 @@
Member email
- {% comment %} TODO should default to name {% endcomment %}
{% if member %}
{{ member.email }}
@@ -64,24 +55,15 @@
Select the level of access for this member. *
- {% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
-
- {% for radio in form.member_access_level %}
- {{ radio.tag }}
-
- {{ radio.choice_label }}
-
- {% if radio.choice_label == "Admin Access" %}
- Grants this member access to the organization-wide information on domains, domain requests, and members. Domain management can be assigned separately.
- {% else %}
- Grants this member access to the organization. They can be given extra permissions to view all organization domain requests and submit domain requests on behalf of the organization. Basic access members can’t view all members of an organization or manage them. Domain management can be assigned separately.
- {% endif %}
-
-
- {% endfor %}
-
+ {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %}
+ {% input_with_errors form.role %}
{% endwith %}
+ {% comment %} {% if radio.value == "organization_admin" %}
+ Grants this member access to the organization-wide information on domains, domain requests, and members. Domain management can be assigned separately.
+ {% elif radio.value == "organization_member" %}
+ Grants this member access to the organization. They can be given extra permissions to view all organization domain requests and submit domain requests on behalf of the organization. Basic access members can’t view all members of an organization or manage them. Domain management can be assigned separately.
+ {% endif %} {% endcomment %}
@@ -93,7 +75,7 @@
text-primary-dark
margin-bottom-0">Organization domain requests
{% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
- {% input_with_errors form.admin_org_domain_request_permissions %}
+ {% input_with_errors form.domain_request_permissions_admin %}
{% endwith %}
Organization members
{% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
- {% input_with_errors form.admin_org_members_permissions %}
+ {% input_with_errors form.member_permissions_admin %}
{% endwith %}
@@ -112,7 +94,7 @@
Organization domain requests
{% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
- {% input_with_errors form.basic_org_domain_request_permissions %}
+ {% input_with_errors form.domain_request_permissions_member %}
{% endwith %}
@@ -123,17 +105,11 @@
href="{% url 'members' %}"
class="usa-button usa-button--outline"
name="btn-cancel-click"
- aria-label="Cancel adding new member"
- >Cancel
-
-
Trigger invite member modal
-
Invite Member
+ aria-label="Cancel editing member"
+ >
+ Cancel
+
+
Update Member
diff --git a/src/registrar/templatetags/custom_filters.py b/src/registrar/templatetags/custom_filters.py
index e88830156..6140130c8 100644
--- a/src/registrar/templatetags/custom_filters.py
+++ b/src/registrar/templatetags/custom_filters.py
@@ -282,3 +282,11 @@ def display_requesting_entity(domain_request):
)
return display
+
+
+@register.filter
+def get_dict_value(dictionary, key):
+ """Get a value from a dictionary. Returns a string on empty."""
+ if isinstance(dictionary, dict):
+ return dictionary.get(key, "")
+ return ""
From 278bc60099ba9291da1df8fcf37c0ef838bd5f6b Mon Sep 17 00:00:00 2001
From: CocoByte
Date: Mon, 9 Dec 2024 23:33:48 -0700
Subject: [PATCH 022/231] Design request #1 - make portfolio org name editable
for analysts
---
src/registrar/admin.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 0e8e4847a..17f3fd292 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -3533,10 +3533,6 @@ class PortfolioAdmin(ListHeaderAdmin):
"senior_official",
]
- analyst_readonly_fields = [
- "organization_name",
- ]
-
def get_admin_users(self, obj):
# Filter UserPortfolioPermission objects related to the portfolio
admin_permissions = self.get_user_portfolio_permission_admins(obj)
From bc3a96aa87d1d6216a1fcb0105d61b6fcb445353 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Tue, 10 Dec 2024 13:50:30 -0700
Subject: [PATCH 023/231] fine comb
---
src/registrar/admin.py | 1 +
.../src/js/getgov/portfolio-member-page.js | 2 +-
src/registrar/context_processors.py | 2 +
src/registrar/forms/portfolio.py | 99 ++++++++++---------
.../django/forms/widgets/multiple_input.html | 2 +-
.../portfolio_member_permissions.html | 15 +--
src/registrar/views/portfolios.py | 2 +-
7 files changed, 65 insertions(+), 58 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 0e8e4847a..144d1fcab 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -3791,6 +3791,7 @@ class WaffleFlagAdmin(FlagAdmin):
if extra_context is None:
extra_context = {}
extra_context["dns_prototype_flag"] = flag_is_active_for_user(request.user, "dns_prototype_flag")
+ extra_context["organization_member"] = flag_is_active_for_user(request.user, "organization_member")
return super().changelist_view(request, extra_context=extra_context)
diff --git a/src/registrar/assets/src/js/getgov/portfolio-member-page.js b/src/registrar/assets/src/js/getgov/portfolio-member-page.js
index ac0b7cffe..98bcf7d03 100644
--- a/src/registrar/assets/src/js/getgov/portfolio-member-page.js
+++ b/src/registrar/assets/src/js/getgov/portfolio-member-page.js
@@ -49,7 +49,7 @@ export function initPortfolioMemberPageToggle() {
* on the Add New Member page.
*/
export function initAddNewMemberPageListeners() {
- add_member_form = document.getElementById("add_member_form")
+ let add_member_form = document.getElementById("add_member_form")
if (!add_member_form){
return;
}
diff --git a/src/registrar/context_processors.py b/src/registrar/context_processors.py
index c1547ad88..5a526f86f 100644
--- a/src/registrar/context_processors.py
+++ b/src/registrar/context_processors.py
@@ -107,6 +107,8 @@ def is_widescreen_mode(request):
"/no-organization-requests/",
"/no-organization-domains/",
"/domain-request/",
+ # "/members/",
+ # "/member/"
]
is_widescreen = any(path in request.path for path in widescreen_paths) or request.path == "/"
is_portfolio_widescreen = bool(
diff --git a/src/registrar/forms/portfolio.py b/src/registrar/forms/portfolio.py
index 65911200b..92fd23906 100644
--- a/src/registrar/forms/portfolio.py
+++ b/src/registrar/forms/portfolio.py
@@ -4,7 +4,7 @@ import logging
from django import forms
from django.core.validators import RegexValidator
from django.core.validators import MaxLengthValidator
-
+from django.utils.safestring import mark_safe
from registrar.models import (
PortfolioInvitation,
UserPortfolioPermission,
@@ -109,13 +109,13 @@ class PortfolioSeniorOfficialForm(forms.ModelForm):
cleaned_data.pop("full_name", None)
return cleaned_data
-
-class BasePortfolioMemberForm(forms.ModelForm):
+class BasePortfolioMemberForm(forms.Form):
+ required_star = '* '
+
role = forms.ChoiceField(
- label="Select permission",
choices=[
- (UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value, "Admin Access"),
- (UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value, "Basic Access")
+ (UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value, "Admin access"),
+ (UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value, "Basic access")
],
widget=forms.RadioSelect,
required=True,
@@ -123,12 +123,12 @@ class BasePortfolioMemberForm(forms.ModelForm):
"required": "Member access level is required",
},
)
- # Permissions for admins
+
domain_request_permissions_admin = forms.ChoiceField(
- label="Select permission",
+ label=mark_safe(f"Select permission {required_star}"),
choices=[
(UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value, "View all requests"),
- (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "Create and edit requests")
+ (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "View all requests plus create requests"),
],
widget=forms.RadioSelect,
required=False,
@@ -136,11 +136,12 @@ class BasePortfolioMemberForm(forms.ModelForm):
"required": "Admin domain request permission is required",
},
)
+
member_permissions_admin = forms.ChoiceField(
- label="Select permission",
+ label=mark_safe(f"Select permission {required_star}"),
choices=[
(UserPortfolioPermissionChoices.VIEW_MEMBERS.value, "View all members"),
- (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "Create and edit members")
+ (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "View all members plus manage members"),
],
widget=forms.RadioSelect,
required=False,
@@ -148,11 +149,13 @@ class BasePortfolioMemberForm(forms.ModelForm):
"required": "Admin member permission is required",
},
)
+
domain_request_permissions_member = forms.ChoiceField(
- label="Select permission",
+ label=mark_safe(f"Select permission {required_star}"),
choices=[
- (UserPortfolioPermissionChoices.VIEW_MEMBERS.value, "View all members"),
- (UserPortfolioPermissionChoices.EDIT_MEMBERS.value, "Create and edit members")
+ (UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value, "View all requests"),
+ (UserPortfolioPermissionChoices.EDIT_REQUESTS.value, "View all requests plus create requests"),
+ ("no_access", "No access"),
],
widget=forms.RadioSelect,
required=False,
@@ -161,8 +164,6 @@ class BasePortfolioMemberForm(forms.ModelForm):
},
)
- # this form dynamically shows/hides some fields, depending on what
- # was selected prior. This toggles which field is required or not.
ROLE_REQUIRED_FIELDS = {
UserPortfolioRoleChoices.ORGANIZATION_ADMIN: [
"domain_request_permissions_admin",
@@ -173,10 +174,19 @@ class BasePortfolioMemberForm(forms.ModelForm):
],
}
+ def __init__(self, *args, instance=None, **kwargs):
+ self.instance = instance
+ # If we have an instance, set initial
+ if instance:
+ kwargs['initial'] = self._map_instance_to_form(instance)
+
+ super().__init__(*args, **kwargs)
+
def _map_instance_to_form(self, instance):
"""Maps model instance data to form fields"""
if not instance:
return {}
+
mapped_data = {}
# Map roles with priority for admin
if instance.roles:
@@ -192,37 +202,16 @@ class BasePortfolioMemberForm(forms.ModelForm):
mapped_data['domain_request_permissions_admin'] = UserPortfolioPermissionChoices.EDIT_REQUESTS.value
elif UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value in perms:
mapped_data['domain_request_permissions_admin'] = UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value
+ else:
+ mapped_data["member_permissions_admin"] = "no_access"
if UserPortfolioPermissionChoices.EDIT_MEMBERS.value in perms:
mapped_data['member_permissions_admin'] = UserPortfolioPermissionChoices.EDIT_MEMBERS.value
elif UserPortfolioPermissionChoices.VIEW_MEMBERS.value in perms:
mapped_data['member_permissions_admin'] = UserPortfolioPermissionChoices.VIEW_MEMBERS.value
-
+
return mapped_data
- def _map_form_to_instance(self, instance):
- """Maps form data to model instance"""
- if not self.is_valid():
- return
-
- role = self.cleaned_data.get("role")
- domain_request_permissions_member = self.cleaned_data.get("domain_request_permissions_member")
- domain_request_permissions_admin = self.cleaned_data.get('domain_request_permissions_admin')
- member_permissions_admin = self.cleaned_data.get('member_permissions_admin')
-
- instance.roles = [role]
- additional_permissions = []
- if domain_request_permissions_member:
- additional_permissions.append(domain_request_permissions_member)
- elif domain_request_permissions_admin:
- additional_permissions.append(domain_request_permissions_admin)
-
- if member_permissions_admin:
- additional_permissions.append(member_permissions_admin)
-
- instance.additional_permissions = additional_permissions
- return instance
-
def clean(self):
cleaned_data = super().clean()
role = cleaned_data.get("role")
@@ -239,6 +228,27 @@ class BasePortfolioMemberForm(forms.ModelForm):
return cleaned_data
+ def save(self):
+ """Save the form data to the instance"""
+ if not self.instance:
+ raise ValueError("Cannot save form without instance")
+
+ role = self.cleaned_data.get("role")
+ self.instance.roles = [self.cleaned_data["role"]]
+
+ additional_permissions = []
+ if self.cleaned_data.get("domain_request_permissions_member") and self.cleaned_data["domain_request_permissions_member"] != "no_access":
+ additional_permissions.append(self.cleaned_data["domain_request_permissions_member"])
+ elif self.cleaned_data.get("domain_request_permissions_admin"):
+ additional_permissions.append(self.cleaned_data["domain_request_permissions_admin"])
+
+ if self.cleaned_data.get("member_permissions_admin"):
+ additional_permissions.append(self.cleaned_data["member_permissions_admin"])
+ self.instance.additional_permissions = additional_permissions
+
+ self.instance.save()
+ return self.instance
+
class PortfolioMemberForm(BasePortfolioMemberForm):
"""
@@ -250,6 +260,7 @@ class PortfolioMemberForm(BasePortfolioMemberForm):
"roles",
"additional_permissions",
]
+
def __init__(self, *args, instance=None, **kwargs):
super().__init__(*args, **kwargs)
self.fields['role'].descriptions = {
@@ -258,14 +269,6 @@ class PortfolioMemberForm(BasePortfolioMemberForm):
}
self.instance = instance
self.initial = self._map_instance_to_form(self.instance)
-
- def save(self):
- """Save form data to instance"""
- if not self.instance:
- self.instance = self.Meta.model()
- self._map_form_to_instance(self.instance)
- self.instance.save()
- return self.instance
class PortfolioInvitedMemberForm(BasePortfolioMemberForm):
diff --git a/src/registrar/templates/django/forms/widgets/multiple_input.html b/src/registrar/templates/django/forms/widgets/multiple_input.html
index 76e19b169..cc0e11989 100644
--- a/src/registrar/templates/django/forms/widgets/multiple_input.html
+++ b/src/registrar/templates/django/forms/widgets/multiple_input.html
@@ -21,7 +21,7 @@
{% if field and field.field and field.field.descriptions %}
{% with description=field.field.descriptions|get_dict_value:option.value %}
{% if description %}
- {{ description }}
+ {{ description }}
{% endif %}
{% endwith %}
{% endif %}
diff --git a/src/registrar/templates/portfolio_member_permissions.html b/src/registrar/templates/portfolio_member_permissions.html
index a5f1731d0..f1db5941c 100644
--- a/src/registrar/templates/portfolio_member_permissions.html
+++ b/src/registrar/templates/portfolio_member_permissions.html
@@ -9,6 +9,7 @@
{% endblock %}
{% block portfolio_content %}
+{% include "includes/form_errors.html" with form=form %}
@@ -29,15 +30,15 @@
Member access and permissions
-{% include "includes/required_fields.html" %}
+{% include "includes/required_fields.html" with remove_margin_top=True %}
-
{% endblock portfolio_content%}
-
-{% comment %} {% extends 'portfolio_base.html' %}
-{% load static field_helpers%}
-
-{% block title %}Organization member {% endblock %}
-
-{% load static %}
-
-{% block portfolio_content %}
-
-
-
- {% block messages %}
- {% include "includes/form_messages.html" %}
- {% endblock %}
-
-
Manage member
-
-
- {% if member %}
- {{ member.email }}
- {% elif invitation %}
- {{ invitation.email }}
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-{% endblock %} {% endcomment %}
From 9fe87fbba1574aa36270e1c0d41513f468f6a75b Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 11 Dec 2024 13:51:18 -0700
Subject: [PATCH 028/231] wrap up js
---
.../src/js/getgov/portfolio-member-page.js | 77 ++++++++++---------
.../models/utility/portfolio_helper.py | 8 +-
2 files changed, 47 insertions(+), 38 deletions(-)
diff --git a/src/registrar/assets/src/js/getgov/portfolio-member-page.js b/src/registrar/assets/src/js/getgov/portfolio-member-page.js
index 429c0e70e..a12f68ec1 100644
--- a/src/registrar/assets/src/js/getgov/portfolio-member-page.js
+++ b/src/registrar/assets/src/js/getgov/portfolio-member-page.js
@@ -3,6 +3,7 @@ import { getCsrfToken } from './helpers.js';
import { generateKebabHTML } from './table-base.js';
import { MembersTable } from './table-members.js';
import { hookupRadioTogglerListener } from './radios.js';
+import { hideElement, showElement } from './helpers.js';
// This is specifically for the Member Profile (Manage Member) Page member/invitation removal
export function initPortfolioNewMemberPageToggle() {
@@ -182,48 +183,50 @@ export function initAddNewMemberPageListeners() {
}
// Export for the rest of the portfolio pages (not add)
+// Not using the
export function initPortfolioMemberPage() {
document.addEventListener("DOMContentLoaded", () => {
- console.log("test")
- hookupRadioTogglerListener(
- 'role',
- {
- 'organization_admin': 'new-member-admin-permissions',
- 'organization_member': 'new-member-basic-permissions'
+ let memberForm = document.getElementById("member_form");
+ if (!memberForm) {
+ return;
+ }
+
+ // console.log("test")
+ // hookupRadioTogglerListener(
+ // 'role',
+ // {
+ // 'organization_admin': 'new-member-admin-permissions',
+ // 'organization_member': 'new-member-basic-permissions'
+ // }
+ // )
+
+ let memberAdminContainer = document.getElementById("member-admin-permissions");
+ let memberBasicContainer = document.getElementById("member-basic-permissions");
+ let roleRadios = document.querySelectorAll('input[name="role"]');
+
+ function toggleContainers() {
+ let selectedRole = document.querySelector('input[name="role"]:checked');
+ if (!selectedRole) {
+ hideElement(memberAdminContainer);
+ hideElement(memberBasicContainer);
+ return;
}
- );
- // let memberForm = document.getElementById("member_form");
- // if (!memberForm) {
- // return;
- // }
- // let memberAdminContainer = document.getElementById("member-admin-permissions");
- // let memberBasicContainer = document.getElementById("member-basic-permissions");
- // let roleRadios = document.querySelectorAll('input[name="role"]');
+ if (selectedRole.value === "organization_admin") {
+ showElement(memberAdminContainer);
+ hideElement(memberBasicContainer);
+ } else if (selectedRole.value === "organization_member") {
+ hideElement(memberAdminContainer);
+ showElement(memberBasicContainer);
+ }
+ }
- // function toggleContainers() {
- // let selectedRole = document.querySelector('input[name="role"]:checked');
- // if (!selectedRole) {
- // hideElement(memberAdminContainer);
- // hideElement(memberBasicContainer);
- // return;
- // }
+ // Initial state
+ toggleContainers();
- // if (selectedRole.value === "organization_admin") {
- // showElement(memberAdminContainer);
- // hideElement(memberBasicContainer);
- // } else if (selectedRole.value === "organization_member") {
- // hideElement(memberAdminContainer);
- // showElement(memberBasicContainer);
- // }
- // }
-
- // // Initial state
- // toggleContainers();
-
- // // Add change listener to all radio buttons
- // roleRadios.forEach(radio => {
- // radio.addEventListener("change", toggleContainers);
- // });
+ // Add change listener to all radio buttons
+ roleRadios.forEach(radio => {
+ radio.addEventListener("change", toggleContainers);
+ });
});
}
\ No newline at end of file
diff --git a/src/registrar/models/utility/portfolio_helper.py b/src/registrar/models/utility/portfolio_helper.py
index 60fa2170a..25073639b 100644
--- a/src/registrar/models/utility/portfolio_helper.py
+++ b/src/registrar/models/utility/portfolio_helper.py
@@ -4,7 +4,9 @@ from django.apps import apps
from django.forms import ValidationError
from registrar.utility.waffle import flag_is_active_for_user
from django.contrib.auth import get_user_model
+import logging
+logger = logging.getLogger(__name__)
class UserPortfolioRoleChoices(models.TextChoices):
"""
@@ -16,7 +18,11 @@ class UserPortfolioRoleChoices(models.TextChoices):
@classmethod
def get_user_portfolio_role_label(cls, user_portfolio_role):
- return cls(user_portfolio_role).label if user_portfolio_role else None
+ try:
+ return cls(user_portfolio_role).label if user_portfolio_role else None
+ except ValueError:
+ logger.warning(f"Invalid portfolio role: {user_portfolio_role}")
+ return f"Unknown ({user_portfolio_role})"
@classmethod
def get_role_description(cls, user_portfolio_role):
From 6662d82539770f47f7bd7c9a7c9eb2731b4818ad Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 11 Dec 2024 14:03:38 -0700
Subject: [PATCH 029/231] Consolidate js
---
.../src/js/getgov/portfolio-member-page.js | 43 +++----------------
1 file changed, 6 insertions(+), 37 deletions(-)
diff --git a/src/registrar/assets/src/js/getgov/portfolio-member-page.js b/src/registrar/assets/src/js/getgov/portfolio-member-page.js
index a12f68ec1..3d5cc3609 100644
--- a/src/registrar/assets/src/js/getgov/portfolio-member-page.js
+++ b/src/registrar/assets/src/js/getgov/portfolio-member-page.js
@@ -190,43 +190,12 @@ export function initPortfolioMemberPage() {
if (!memberForm) {
return;
}
-
- // console.log("test")
- // hookupRadioTogglerListener(
- // 'role',
- // {
- // 'organization_admin': 'new-member-admin-permissions',
- // 'organization_member': 'new-member-basic-permissions'
- // }
- // )
-
- let memberAdminContainer = document.getElementById("member-admin-permissions");
- let memberBasicContainer = document.getElementById("member-basic-permissions");
- let roleRadios = document.querySelectorAll('input[name="role"]');
-
- function toggleContainers() {
- let selectedRole = document.querySelector('input[name="role"]:checked');
- if (!selectedRole) {
- hideElement(memberAdminContainer);
- hideElement(memberBasicContainer);
- return;
+ hookupRadioTogglerListener(
+ 'role',
+ {
+ 'organization_admin': 'member-admin-permissions',
+ 'organization_member': 'member-basic-permissions'
}
-
- if (selectedRole.value === "organization_admin") {
- showElement(memberAdminContainer);
- hideElement(memberBasicContainer);
- } else if (selectedRole.value === "organization_member") {
- hideElement(memberAdminContainer);
- showElement(memberBasicContainer);
- }
- }
-
- // Initial state
- toggleContainers();
-
- // Add change listener to all radio buttons
- roleRadios.forEach(radio => {
- radio.addEventListener("change", toggleContainers);
- });
+ )
});
}
\ No newline at end of file
From 7542b9a4f2e1d7d6e07b643e3a8cbf094204b1d4 Mon Sep 17 00:00:00 2001
From: CocoByte
Date: Wed, 11 Dec 2024 20:25:37 -0700
Subject: [PATCH 030/231] Made widescreen global for headers and banners
---
src/registrar/templates/base.html | 2 +-
src/registrar/templates/includes/banner-error.html | 2 +-
src/registrar/templates/includes/banner-info.html | 2 +-
.../templates/includes/banner-non-production-alert.html | 2 +-
.../templates/includes/banner-service-disruption.html | 2 +-
src/registrar/templates/includes/banner-site-alert.html | 2 +-
src/registrar/templates/includes/banner-system-outage.html | 2 +-
src/registrar/templates/includes/banner-warning.html | 2 +-
src/registrar/templates/includes/header_basic.html | 2 +-
src/registrar/templates/includes/header_extended.html | 4 ++--
10 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html
index de257f52c..5cee7ec01 100644
--- a/src/registrar/templates/base.html
+++ b/src/registrar/templates/base.html
@@ -97,7 +97,7 @@