mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-23 19:20:47 +02:00
Merge branch 'main' into ad/3256-new-changes-on-name-servers-page
This commit is contained in:
commit
06870bc8cd
10 changed files with 92 additions and 27 deletions
|
@ -5284,7 +5284,10 @@ const setUpModal = baseComponent => {
|
||||||
overlayDiv.classList.add(OVERLAY_CLASSNAME);
|
overlayDiv.classList.add(OVERLAY_CLASSNAME);
|
||||||
|
|
||||||
// Set attributes
|
// Set attributes
|
||||||
modalWrapper.setAttribute("role", "dialog");
|
// DOTGOV
|
||||||
|
// Removes the dialog role as this causes a double readout bug with screenreaders
|
||||||
|
// modalWrapper.setAttribute("role", "dialog");
|
||||||
|
// END DOTGOV
|
||||||
modalWrapper.setAttribute("id", modalID);
|
modalWrapper.setAttribute("id", modalID);
|
||||||
if (ariaLabelledBy) {
|
if (ariaLabelledBy) {
|
||||||
modalWrapper.setAttribute("aria-labelledby", ariaLabelledBy);
|
modalWrapper.setAttribute("aria-labelledby", ariaLabelledBy);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { hideElement, showElement, addOrRemoveSessionBoolean } from './helpers-admin.js';
|
import { hideElement, showElement, addOrRemoveSessionBoolean, announceForScreenReaders } from './helpers-admin.js';
|
||||||
import { handlePortfolioSelection } from './helpers-portfolio-dynamic-fields.js';
|
import { handlePortfolioSelection } from './helpers-portfolio-dynamic-fields.js';
|
||||||
|
|
||||||
function displayModalOnDropdownClick(linkClickedDisplaysModal, statusDropdown, actionButton, valueToCheck){
|
function displayModalOnDropdownClick(linkClickedDisplaysModal, statusDropdown, actionButton, valueToCheck){
|
||||||
|
@ -684,3 +684,33 @@ export function initDynamicDomainRequestFields(){
|
||||||
handleSuborgFieldsAndButtons();
|
handleSuborgFieldsAndButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function initFilterFocusListeners() {
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
let filters = document.querySelectorAll("#changelist-filter li a"); // Get list of all filter links
|
||||||
|
let clickedFilter = false; // Used to determine if we are truly navigating away or not
|
||||||
|
|
||||||
|
// Restore focus from localStorage
|
||||||
|
let lastClickedFilterId = localStorage.getItem("admin_filter_focus_id");
|
||||||
|
if (lastClickedFilterId) {
|
||||||
|
let focusedElement = document.getElementById(lastClickedFilterId);
|
||||||
|
if (focusedElement) {
|
||||||
|
//Focus the element
|
||||||
|
focusedElement.setAttribute("tabindex", "0");
|
||||||
|
focusedElement.focus({ preventScroll: true });
|
||||||
|
|
||||||
|
// Announce focus change for screen readers
|
||||||
|
announceForScreenReaders("Filter refocused on " + focusedElement.textContent);
|
||||||
|
localStorage.removeItem("admin_filter_focus_id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture clicked filter and store its ID
|
||||||
|
filters.forEach(filter => {
|
||||||
|
filter.addEventListener("click", function() {
|
||||||
|
localStorage.setItem("admin_filter_focus_id", this.id);
|
||||||
|
clickedFilter = true; // Mark that a filter was clicked
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -32,3 +32,22 @@ export function getParameterByName(name, url) {
|
||||||
if (!results[2]) return '';
|
if (!results[2]) return '';
|
||||||
return decodeURIComponent(results[2].replace(/\+/g, ' '));
|
return decodeURIComponent(results[2].replace(/\+/g, ' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a temporary live region to announce messages for screen readers.
|
||||||
|
*/
|
||||||
|
export function announceForScreenReaders(message) {
|
||||||
|
let liveRegion = document.createElement("div");
|
||||||
|
liveRegion.setAttribute("aria-live", "assertive");
|
||||||
|
liveRegion.setAttribute("role", "alert");
|
||||||
|
liveRegion.setAttribute("class", "usa-sr-only");
|
||||||
|
document.body.appendChild(liveRegion);
|
||||||
|
|
||||||
|
// Delay the update slightly to ensure it's recognized
|
||||||
|
setTimeout(() => {
|
||||||
|
liveRegion.textContent = message;
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(liveRegion);
|
||||||
|
}, 1000);
|
||||||
|
}, 100);
|
||||||
|
}
|
|
@ -10,7 +10,8 @@ import {
|
||||||
initRejectedEmail,
|
initRejectedEmail,
|
||||||
initApprovedDomain,
|
initApprovedDomain,
|
||||||
initCopyRequestSummary,
|
initCopyRequestSummary,
|
||||||
initDynamicDomainRequestFields } from './domain-request-form.js';
|
initDynamicDomainRequestFields,
|
||||||
|
initFilterFocusListeners } from './domain-request-form.js';
|
||||||
import { initDomainFormTargetBlankButtons } from './domain-form.js';
|
import { initDomainFormTargetBlankButtons } from './domain-form.js';
|
||||||
import { initDynamicPortfolioFields } from './portfolio-form.js';
|
import { initDynamicPortfolioFields } from './portfolio-form.js';
|
||||||
import { initDynamicDomainInformationFields } from './domain-information-form.js';
|
import { initDynamicDomainInformationFields } from './domain-information-form.js';
|
||||||
|
@ -34,6 +35,7 @@ initRejectedEmail();
|
||||||
initApprovedDomain();
|
initApprovedDomain();
|
||||||
initCopyRequestSummary();
|
initCopyRequestSummary();
|
||||||
initDynamicDomainRequestFields();
|
initDynamicDomainRequestFields();
|
||||||
|
initFilterFocusListeners();
|
||||||
|
|
||||||
// Domain
|
// Domain
|
||||||
initDomainFormTargetBlankButtons();
|
initDomainFormTargetBlankButtons();
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { initDomainManagersPage } from './domain-managers.js';
|
||||||
import { initDomainDSData } from './domain-dsdata.js';
|
import { initDomainDSData } from './domain-dsdata.js';
|
||||||
import { initDomainDNSSEC } from './domain-dnssec.js';
|
import { initDomainDNSSEC } from './domain-dnssec.js';
|
||||||
import { initFormErrorHandling } from './form-errors.js';
|
import { initFormErrorHandling } from './form-errors.js';
|
||||||
|
import { initButtonLinks } from '../getgov-admin/button-utils.js';
|
||||||
|
|
||||||
initDomainValidators();
|
initDomainValidators();
|
||||||
|
|
||||||
|
@ -50,3 +51,5 @@ initFormErrorHandling();
|
||||||
initPortfolioMemberPageRadio();
|
initPortfolioMemberPageRadio();
|
||||||
initPortfolioNewMemberPageToggle();
|
initPortfolioNewMemberPageToggle();
|
||||||
initAddNewMemberPageListeners();
|
initAddNewMemberPageListeners();
|
||||||
|
|
||||||
|
initButtonLinks();
|
||||||
|
|
13
src/registrar/templates/admin/filter.html
Normal file
13
src/registrar/templates/admin/filter.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% comment %} Override of this file: https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/filter.html {% endcomment %}
|
||||||
|
{% load i18n %}
|
||||||
|
<details data-filter-title="{{ title }}" open>
|
||||||
|
<summary>
|
||||||
|
{% blocktranslate with filter_title=title %} By {{ filter_title }} {% endblocktranslate %}
|
||||||
|
</summary>
|
||||||
|
<ul>
|
||||||
|
{% for choice in choices %}
|
||||||
|
<li {% if choice.selected %} class="selected"{% endif %}>
|
||||||
|
<a id="{{ title|lower|cut:' ' }}-filter-{{ choice.display|slugify }}" href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</details>
|
|
@ -9,16 +9,12 @@
|
||||||
{% for choice in choices %}
|
{% for choice in choices %}
|
||||||
{% if choice.reset %}
|
{% if choice.reset %}
|
||||||
<li{% if choice.selected %} class="selected"{% endif %}">
|
<li{% if choice.selected %} class="selected"{% endif %}">
|
||||||
<a href="{{ choice.query_string|iriencode }}" title="{{ choice.display }}">{{ choice.display }}</a>
|
<a id="{{ title|lower|cut:' ' }}-filter-{{ choice.display|slugify }}" href="{{ choice.query_string|iriencode }}" title="{{ choice.display }}">{{ choice.display }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% else %}
|
||||||
{% endfor %}
|
<li{% if choice.selected %} class="selected"{% endif %}>
|
||||||
|
|
||||||
{% for choice in choices %}
|
|
||||||
{% if not choice.reset %}
|
|
||||||
<li{% if choice.selected %} class="selected"{% endif %}">
|
|
||||||
{% if choice.selected and choice.exclude_query_string %}
|
{% if choice.selected and choice.exclude_query_string %}
|
||||||
<a role="menuitemcheckbox" class="choice-filter choice-filter--checked" href="{{ choice.exclude_query_string|iriencode }}">{{ choice.display }}
|
<a id="{{ title|lower|cut:' ' }}-filter-{{ choice.display|slugify }}" role="menuitemcheckbox" class="choice-filter choice-filter--checked" href="{{ choice.exclude_query_string|iriencode }}">{{ choice.display }}
|
||||||
<svg class="usa-icon position-absolute z-0 left-0" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
<svg class="usa-icon position-absolute z-0 left-0" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#check_box_outline_blank"></use>
|
<use xlink:href="{%static 'img/sprite.svg'%}#check_box_outline_blank"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -26,9 +22,8 @@
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#check"></use>
|
<use xlink:href="{%static 'img/sprite.svg'%}#check"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% elif not choice.selected and choice.include_query_string %}
|
||||||
{% if not choice.selected and choice.include_query_string %}
|
<a id="{{ title|lower|cut:' ' }}-filter-{{ choice.display|slugify }}" role="menuitemcheckbox" class="choice-filter" href="{{ choice.include_query_string|iriencode }}">{{ choice.display }}
|
||||||
<a role="menuitemcheckbox" class="choice-filter" href="{{ choice.include_query_string|iriencode }}">{{ choice.display }}
|
|
||||||
<svg class="usa-icon position-absolute z-0 left-0" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
<svg class="usa-icon position-absolute z-0 left-0" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#check_box_outline_blank"></use>
|
<use xlink:href="{%static 'img/sprite.svg'%}#check_box_outline_blank"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -38,4 +33,4 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
|
@ -18,10 +18,10 @@
|
||||||
<h1>Manage your domains</h1>
|
<h1>Manage your domains</h1>
|
||||||
|
|
||||||
<p class="margin-top-4">
|
<p class="margin-top-4">
|
||||||
<a href="{% url 'domain-request:start' %}" class="usa-button"
|
<button data-href="{% url 'domain-request:start' %}" class="usa-button use-button-as-link"
|
||||||
>
|
>
|
||||||
Start a new domain request
|
Start a new domain request
|
||||||
</a>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% include "includes/domains_table.html" with user_domain_count=user_domain_count %}
|
{% include "includes/domains_table.html" with user_domain_count=user_domain_count %}
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
<div class="mobile:grid-col-12 tablet:grid-col-6">
|
<div class="mobile:grid-col-12 tablet:grid-col-6">
|
||||||
|
|
||||||
<p class="float-right-tablet tablet:margin-y-0">
|
<p class="float-right-tablet tablet:margin-y-0">
|
||||||
<a href="{% url 'domain-request:start' %}" class="usa-button"
|
<button data-href="{% url 'domain-request:start' %}" class="usa-button use-button-as-link"
|
||||||
>
|
>
|
||||||
Start a new domain request
|
Start a new domain request
|
||||||
</a>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -215,14 +215,14 @@ class TestDomainInvitationAdmin(WebTest):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Assert that the filters are added
|
# Assert that the filters are added
|
||||||
self.assertContains(response, "invited", count=5)
|
self.assertContains(response, "invited", count=6)
|
||||||
self.assertContains(response, "Invited", count=2)
|
self.assertContains(response, "Invited", count=2)
|
||||||
self.assertContains(response, "retrieved", count=2)
|
self.assertContains(response, "retrieved", count=3)
|
||||||
self.assertContains(response, "Retrieved", count=2)
|
self.assertContains(response, "Retrieved", count=2)
|
||||||
|
|
||||||
# Check for the HTML context specificially
|
# Check for the HTML context specificially
|
||||||
invited_html = '<a href="?status__exact=invited">Invited</a>'
|
invited_html = '<a id="status-filter-invited" href="?status__exact=invited">Invited</a>'
|
||||||
retrieved_html = '<a href="?status__exact=retrieved">Retrieved</a>'
|
retrieved_html = '<a id="status-filter-retrieved" href="?status__exact=retrieved">Retrieved</a>'
|
||||||
|
|
||||||
self.assertContains(response, invited_html, count=1)
|
self.assertContains(response, invited_html, count=1)
|
||||||
self.assertContains(response, retrieved_html, count=1)
|
self.assertContains(response, retrieved_html, count=1)
|
||||||
|
@ -1269,14 +1269,14 @@ class TestPortfolioInvitationAdmin(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Assert that the filters are added
|
# Assert that the filters are added
|
||||||
self.assertContains(response, "invited", count=4)
|
self.assertContains(response, "invited", count=5)
|
||||||
self.assertContains(response, "Invited", count=2)
|
self.assertContains(response, "Invited", count=2)
|
||||||
self.assertContains(response, "retrieved", count=2)
|
self.assertContains(response, "retrieved", count=3)
|
||||||
self.assertContains(response, "Retrieved", count=2)
|
self.assertContains(response, "Retrieved", count=2)
|
||||||
|
|
||||||
# Check for the HTML context specificially
|
# Check for the HTML context specificially
|
||||||
invited_html = '<a href="?status__exact=invited">Invited</a>'
|
invited_html = '<a id="status-filter-invited" href="?status__exact=invited">Invited</a>'
|
||||||
retrieved_html = '<a href="?status__exact=retrieved">Retrieved</a>'
|
retrieved_html = '<a id="status-filter-retrieved" href="?status__exact=retrieved">Retrieved</a>'
|
||||||
|
|
||||||
self.assertContains(response, invited_html, count=1)
|
self.assertContains(response, invited_html, count=1)
|
||||||
self.assertContains(response, retrieved_html, count=1)
|
self.assertContains(response, retrieved_html, count=1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue