Merge pull request #3577 from cisagov/nl/3181-labels-for-investigator-and-senior-official

#3181 - dynamic labels for investigator and senior official [-Bob]
This commit is contained in:
CuriousX 2025-03-10 10:20:51 -06:00 committed by GitHub
commit 4b11be6291
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 74 additions and 5 deletions

View file

@ -2758,17 +2758,16 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"investigator",
"portfolio",
"sub_organization",
"senior_official",
]
filter_horizontal = ("current_websites", "alternative_domains", "other_contacts")
# Table ordering
# NOTE: This impacts the select2 dropdowns (combobox)
# Currentl, there's only one for requests on DomainInfo
# Currently, there's only one for requests on DomainInfo
ordering = ["-last_submitted_date", "requested_domain__name"]
change_form_template = "django/admin/domain_request_change_form.html"
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)

View file

@ -0,0 +1,60 @@
/*
This function intercepts all select2 dropdowns and adds aria content.
It relies on an override in detail_table_fieldset.html that provides
a span with a corresponding id for aria-describedby content.
This allows us to avoid overriding aria-label, which is used by select2
to send the current dropdown selection to ANDI.
*/
export function initAriaInjectionsForSelect2Dropdowns() {
document.addEventListener('DOMContentLoaded', function () {
// Find all spans with "--aria-description" in their id
const descriptionSpans = document.querySelectorAll('span[id*="--aria-description"]');
descriptionSpans.forEach(function (span) {
// Extract the base ID from the span's id (remove "--aria-description")
const fieldId = span.id.replace('--aria-description', '');
const field = document.getElementById(fieldId);
if (field) {
// If Select2 is already initialized, apply aria-describedby immediately
if (field.classList.contains('select2-hidden-accessible')) {
applyAriaDescribedBy(field, span.id);
return;
}
// Use MutationObserver to detect Select2 initialization
const observer = new MutationObserver(function (mutations) {
if (document.getElementById(fieldId)?.classList.contains("select2-hidden-accessible")) {
applyAriaDescribedBy(field, span.id);
observer.disconnect(); // Stop observing after applying attributes
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
});
// Function to apply aria-describedby to Select2 UI
function applyAriaDescribedBy(field, descriptionId) {
let select2ElementDetected = false;
const select2Id = "select2-" + field.id + "-container";
// Find the Select2 selection box
const select2SpanThatTriggersAria = document.querySelector(`span[aria-labelledby='${select2Id}']`);
if (select2SpanThatTriggersAria) {
select2SpanThatTriggersAria.setAttribute('aria-describedby', descriptionId);
select2ElementDetected = true;
}
// If no Select2 component was detected, apply aria-describedby directly to the field
if (!select2ElementDetected) {
field.setAttribute('aria-describedby', descriptionId);
}
}
});
}

View file

@ -19,6 +19,7 @@ import { initDynamicDomainInformationFields } from './domain-information-form.js
import { initDynamicDomainFields } from './domain-form.js';
import { initAnalyticsDashboard } from './analytics.js';
import { initButtonLinks } from './button-utils.js';
import { initAriaInjectionsForSelect2Dropdowns } from './andi.js'
// General
initModals();
@ -26,6 +27,7 @@ initCopyToClipboard();
initFilterHorizontalWidget();
initDescriptions();
initSubmitBar();
initAriaInjectionsForSelect2Dropdowns();
initButtonLinks();
// Domain request

View file

@ -160,6 +160,16 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% endblock field_readonly %}
{% block field_other %}
{% comment %}
.gov override - add Aria messages for select2 dropdowns. These messages are hooked-up to their respective DOM
elements via javascript (see andi.js)
{% endcomment %}
{% if "related_widget_wrapper" in field.field.field.widget.template_name %}
<span id="{{ field.field.id_for_label }}--aria-description" class="visually-hidden admin-select--aria-description">
{{ field.field.label }}, edit, has autocomplete. To set the value, use the arrow keys or type the text.
</span>
{% endif %}
{% if field.field.name == "action_needed_reason_email" %}
{{ field.field }}
@ -251,7 +261,6 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% elif field.field.name == "rejection_reason_email" %}
{{ field.field }}
<div class="margin-top-05 text-faded custom-email-placeholder">
&ndash;
</div>
@ -331,7 +340,6 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
</button>
</div>
</div>
{% if original_object.rejection_reason_email %}
<input id="last-sent-rejection-email-content" class="display-none" value="{{original_object.rejection_reason_email}}">
{% else %}