mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-13 04:59:59 +02:00
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:
commit
4b11be6291
4 changed files with 74 additions and 5 deletions
|
@ -2758,17 +2758,16 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
||||||
"investigator",
|
"investigator",
|
||||||
"portfolio",
|
"portfolio",
|
||||||
"sub_organization",
|
"sub_organization",
|
||||||
|
"senior_official",
|
||||||
]
|
]
|
||||||
|
|
||||||
filter_horizontal = ("current_websites", "alternative_domains", "other_contacts")
|
filter_horizontal = ("current_websites", "alternative_domains", "other_contacts")
|
||||||
|
|
||||||
# Table ordering
|
# Table ordering
|
||||||
# NOTE: This impacts the select2 dropdowns (combobox)
|
# 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"]
|
ordering = ["-last_submitted_date", "requested_domain__name"]
|
||||||
|
|
||||||
change_form_template = "django/admin/domain_request_change_form.html"
|
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fieldsets(self, request, obj=None):
|
||||||
fieldsets = super().get_fieldsets(request, obj)
|
fieldsets = super().get_fieldsets(request, obj)
|
||||||
|
|
||||||
|
|
60
src/registrar/assets/src/js/getgov-admin/andi.js
Normal file
60
src/registrar/assets/src/js/getgov-admin/andi.js
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import { initDynamicDomainInformationFields } from './domain-information-form.js
|
||||||
import { initDynamicDomainFields } from './domain-form.js';
|
import { initDynamicDomainFields } from './domain-form.js';
|
||||||
import { initAnalyticsDashboard } from './analytics.js';
|
import { initAnalyticsDashboard } from './analytics.js';
|
||||||
import { initButtonLinks } from './button-utils.js';
|
import { initButtonLinks } from './button-utils.js';
|
||||||
|
import { initAriaInjectionsForSelect2Dropdowns } from './andi.js'
|
||||||
|
|
||||||
// General
|
// General
|
||||||
initModals();
|
initModals();
|
||||||
|
@ -26,6 +27,7 @@ initCopyToClipboard();
|
||||||
initFilterHorizontalWidget();
|
initFilterHorizontalWidget();
|
||||||
initDescriptions();
|
initDescriptions();
|
||||||
initSubmitBar();
|
initSubmitBar();
|
||||||
|
initAriaInjectionsForSelect2Dropdowns();
|
||||||
initButtonLinks();
|
initButtonLinks();
|
||||||
|
|
||||||
// Domain request
|
// Domain request
|
||||||
|
|
|
@ -160,6 +160,16 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
|
||||||
{% endblock field_readonly %}
|
{% endblock field_readonly %}
|
||||||
|
|
||||||
{% block field_other %}
|
{% 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" %}
|
{% if field.field.name == "action_needed_reason_email" %}
|
||||||
{{ field.field }}
|
{{ 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" %}
|
{% elif field.field.name == "rejection_reason_email" %}
|
||||||
{{ field.field }}
|
{{ field.field }}
|
||||||
|
|
||||||
<div class="margin-top-05 text-faded custom-email-placeholder">
|
<div class="margin-top-05 text-faded custom-email-placeholder">
|
||||||
–
|
–
|
||||||
</div>
|
</div>
|
||||||
|
@ -331,7 +340,6 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if original_object.rejection_reason_email %}
|
{% if original_object.rejection_reason_email %}
|
||||||
<input id="last-sent-rejection-email-content" class="display-none" value="{{original_object.rejection_reason_email}}">
|
<input id="last-sent-rejection-email-content" class="display-none" value="{{original_object.rejection_reason_email}}">
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue