mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-24 19:48:36 +02:00
Merge branch 'main' into nl/3176-page-titles
This commit is contained in:
commit
d66bd5df67
13 changed files with 167 additions and 88 deletions
|
@ -2274,11 +2274,12 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
@admin.display(description=_("Requested Domain"))
|
||||
def custom_requested_domain(self, obj):
|
||||
# Example: Show different icons based on `status`
|
||||
url = reverse("admin:registrar_domainrequest_changelist") + f"{obj.id}"
|
||||
text = obj.requested_domain
|
||||
if obj.portfolio:
|
||||
return format_html('<a href="{}"><img src="/public/admin/img/icon-yes.svg"> {}</a>', url, text)
|
||||
return format_html('<a href="{}">{}</a>', url, text)
|
||||
return format_html(
|
||||
f'<img class="padding-right-05" src="/public/admin/img/icon-yes.svg" aria-hidden="true">{escape(text)}'
|
||||
)
|
||||
return text
|
||||
|
||||
custom_requested_domain.admin_order_field = "requested_domain__name" # type: ignore
|
||||
|
||||
|
|
15
src/registrar/assets/src/js/getgov-admin/button-utils.js
Normal file
15
src/registrar/assets/src/js/getgov-admin/button-utils.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Initializes buttons to behave like links by navigating to their data-url attribute
|
||||
* Example usage: <button class="use-button-as-link" data-url="/some/path">Click me</button>
|
||||
*/
|
||||
export function initButtonLinks() {
|
||||
document.querySelectorAll('button.use-button-as-link').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
// Equivalent to button.getAttribute("data-href")
|
||||
const href = this.dataset.href;
|
||||
if (href) {
|
||||
window.location.href = href;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -16,6 +16,7 @@ import { initDynamicPortfolioFields } from './portfolio-form.js';
|
|||
import { initDynamicDomainInformationFields } from './domain-information-form.js';
|
||||
import { initDynamicDomainFields } from './domain-form.js';
|
||||
import { initAnalyticsDashboard } from './analytics.js';
|
||||
import { initButtonLinks } from './button-utils.js';
|
||||
|
||||
// General
|
||||
initModals();
|
||||
|
@ -23,6 +24,7 @@ initCopyToClipboard();
|
|||
initFilterHorizontalWidget();
|
||||
initDescriptions();
|
||||
initSubmitBar();
|
||||
initButtonLinks();
|
||||
|
||||
// Domain request
|
||||
initIneligibleModal();
|
||||
|
|
|
@ -69,13 +69,14 @@ export class MembersTable extends BaseTable {
|
|||
const kebabHTML = customTableOptions.hasAdditionalActions ? generateKebabHTML('remove-member', unique_id, cancelInvitationButton, `Expand for more options for ${member.name}`): '';
|
||||
|
||||
const row = document.createElement('tr');
|
||||
row.classList.add('hide-td-borders');
|
||||
let admin_tagHTML = ``;
|
||||
if (member.is_admin)
|
||||
admin_tagHTML = `<span class="usa-tag margin-left-1 bg-primary-dark text-semibold">Admin</span>`
|
||||
|
||||
// generate html blocks for domains and permissions for the member
|
||||
let domainsHTML = this.generateDomainsHTML(num_domains, member.domain_names, member.domain_urls, member.action_url);
|
||||
let permissionsHTML = this.generatePermissionsHTML(member.is_admin, member.permissions, customTableOptions.UserPortfolioPermissionChoices);
|
||||
let domainsHTML = this.generateDomainsHTML(num_domains, member.domain_names, member.domain_urls, member.action_url, unique_id);
|
||||
let permissionsHTML = this.generatePermissionsHTML(member.is_admin, member.permissions, customTableOptions.UserPortfolioPermissionChoices, unique_id);
|
||||
|
||||
// domainsHTML block and permissionsHTML block need to be wrapped with hide/show toggle, Expand
|
||||
let showMoreButton = '';
|
||||
|
@ -96,20 +97,26 @@ export class MembersTable extends BaseTable {
|
|||
</button>
|
||||
`;
|
||||
|
||||
showMoreRow.innerHTML = `<td colspan='4' headers="header-member row-header-${unique_id}" class="padding-top-0"><div class='grid-row grid-gap-2'>${domainsHTML} ${permissionsHTML}</div></td>`;
|
||||
showMoreRow.classList.add('show-more-content');
|
||||
showMoreRow.classList.add('display-none');
|
||||
showMoreRow.innerHTML = `
|
||||
<td colspan='4' headers="header-member row-header-${unique_id}" class="padding-top-0">
|
||||
${showMoreButton}
|
||||
<div class='grid-row grid-gap-2 show-more-content display-none'>
|
||||
${domainsHTML}
|
||||
${permissionsHTML}
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
showMoreRow.id = unique_id;
|
||||
}
|
||||
|
||||
row.innerHTML = `
|
||||
<th role="rowheader" headers="header-member" data-label="member email" id='row-header-${unique_id}'>
|
||||
${member.member_display} ${admin_tagHTML} ${showMoreButton}
|
||||
<th class="padding-bottom-0" role="rowheader" headers="header-member" data-label="Member" id='row-header-${unique_id}'>
|
||||
${member.member_display} ${admin_tagHTML}
|
||||
</th>
|
||||
<td headers="header-last-active row-header-${unique_id}" data-sort-value="${last_active.sort_value}" data-label="last_active">
|
||||
<td class="padding-bottom-0" headers="header-last-active row-header-${unique_id}" data-sort-value="${last_active.sort_value}" data-label="Last active">
|
||||
${last_active.display_value}
|
||||
</td>
|
||||
<td headers="header-action row-header-${unique_id}" class="width--action-column">
|
||||
<td class="padding-bottom-0" headers="header-action row-header-${unique_id}" class="width--action-column">
|
||||
<div class="tablet:display-flex tablet:flex-row flex-align-center">
|
||||
<a href="${member.action_url}" ${customTableOptions.hasAdditionalActions ? "class='margin-right-2'" : ''}>
|
||||
<svg class="usa-icon top-1px" aria-hidden="true" focusable="false" role="img" width="24">
|
||||
|
@ -146,16 +153,15 @@ export class MembersTable extends BaseTable {
|
|||
*
|
||||
* @param {HTMLElement} toggleButton - The button that toggles the content visibility.
|
||||
* @param {HTMLElement} contentDiv - The content div whose visibility is toggled.
|
||||
* @param {HTMLElement} buttonParentRow - The parent row element containing the button.
|
||||
*/
|
||||
function toggleShowMoreButton(toggleButton, contentDiv, buttonParentRow) {
|
||||
function toggleShowMoreButton(toggleButton, contentDiv) {
|
||||
const spanElement = toggleButton.querySelector('span');
|
||||
const useElement = toggleButton.querySelector('use');
|
||||
if (contentDiv.classList.contains('display-none')) {
|
||||
showElement(contentDiv);
|
||||
spanElement.textContent = 'Close';
|
||||
useElement.setAttribute('xlink:href', '/public/img/sprite.svg#expand_less');
|
||||
buttonParentRow.classList.add('hide-td-borders');
|
||||
toggleButton.classList.add('margin-bottom-2');
|
||||
|
||||
let ariaLabelText = "Close additional information";
|
||||
let ariaLabelPlaceholder = toggleButton.getAttribute("aria-label-placeholder");
|
||||
|
@ -169,7 +175,7 @@ export class MembersTable extends BaseTable {
|
|||
hideElement(contentDiv);
|
||||
spanElement.textContent = 'Expand';
|
||||
useElement.setAttribute('xlink:href', '/public/img/sprite.svg#expand_more');
|
||||
buttonParentRow.classList.remove('hide-td-borders');
|
||||
toggleButton.classList.remove('margin-bottom-2');
|
||||
|
||||
let ariaLabelText = "Expand for additional information";
|
||||
let ariaLabelPlaceholder = toggleButton.getAttribute("aria-label-placeholder");
|
||||
|
@ -182,14 +188,11 @@ export class MembersTable extends BaseTable {
|
|||
|
||||
let toggleButtons = document.querySelectorAll('.usa-button--show-more-button');
|
||||
toggleButtons.forEach((toggleButton) => {
|
||||
|
||||
// get contentDiv for element specified in data-for attribute of toggleButton
|
||||
let dataFor = toggleButton.dataset.for;
|
||||
let contentDiv = document.getElementById(dataFor);
|
||||
let buttonParentRow = toggleButton.parentElement.parentElement;
|
||||
if (contentDiv && contentDiv.tagName.toLowerCase() === 'tr' && contentDiv.classList.contains('show-more-content') && buttonParentRow && buttonParentRow.tagName.toLowerCase() === 'tr') {
|
||||
let contentDiv = buttonParentRow.querySelector(".show-more-content");
|
||||
if (contentDiv && buttonParentRow && buttonParentRow.tagName.toLowerCase() === 'tr') {
|
||||
toggleButton.addEventListener('click', function() {
|
||||
toggleShowMoreButton(toggleButton, contentDiv, buttonParentRow);
|
||||
toggleShowMoreButton(toggleButton, contentDiv);
|
||||
});
|
||||
} else {
|
||||
console.warn('Found a toggle button with no associated toggleable content or parent row');
|
||||
|
@ -240,33 +243,40 @@ export class MembersTable extends BaseTable {
|
|||
* @param {number} num_domains - The number of domains the member is assigned to.
|
||||
* @param {Array} domain_names - An array of domain names.
|
||||
* @param {Array} domain_urls - An array of corresponding domain URLs.
|
||||
* @param {Array} unique_id - A unique row id.
|
||||
* @returns {string} - A string of HTML displaying the domains assigned to the member.
|
||||
*/
|
||||
generateDomainsHTML(num_domains, domain_names, domain_urls, action_url) {
|
||||
generateDomainsHTML(num_domains, domain_names, domain_urls, action_url, unique_id) {
|
||||
// Initialize an empty string for the HTML
|
||||
let domainsHTML = '';
|
||||
|
||||
// Only generate HTML if the member has one or more assigned domains
|
||||
|
||||
domainsHTML += "<div class='desktop:grid-col-4 margin-bottom-2 desktop:margin-bottom-0'>";
|
||||
domainsHTML += "<h4 class='font-body-xs margin-y-0'>Domains assigned</h4>";
|
||||
domainsHTML += `<h4 id='domains-assigned--heading-${unique_id}' class='font-body-xs margin-y-0'>Domains assigned</h4>`;
|
||||
domainsHTML += `<section aria-labelledby='domains-assigned--heading-${unique_id}' tabindex='0'>`
|
||||
if (num_domains > 0) {
|
||||
domainsHTML += `<p class='font-body-xs text-base-darker margin-y-0'>This member is assigned to ${num_domains} domain${num_domains > 1 ? 's' : ''}:</p>`;
|
||||
domainsHTML += "<ul class='usa-list usa-list--unstyled margin-y-0'>";
|
||||
if (num_domains > 1) {
|
||||
domainsHTML += "<ul class='usa-list usa-list--unstyled margin-y-0'>";
|
||||
|
||||
// Display up to 6 domains with their URLs
|
||||
for (let i = 0; i < num_domains && i < 6; i++) {
|
||||
domainsHTML += `<li><a class="font-body-xs" href="${domain_urls[i]}">${domain_names[i]}</a></li>`;
|
||||
// Display up to 6 domains with their URLs
|
||||
for (let i = 0; i < num_domains && i < 6; i++) {
|
||||
domainsHTML += `<li><a class="font-body-xs" href="${domain_urls[i]}">${domain_names[i]}</a></li>`;
|
||||
}
|
||||
|
||||
domainsHTML += "</ul>";
|
||||
} else {
|
||||
// We don't display this in a list for better screenreader support, when only one item exists.
|
||||
domainsHTML += `<a class="font-body-xs" href="${domain_urls[0]}">${domain_names[0]}</a>`;
|
||||
}
|
||||
|
||||
domainsHTML += "</ul>";
|
||||
} else {
|
||||
domainsHTML += `<p class='font-body-xs text-base-darker margin-y-0'>This member is assigned to 0 domains.</p>`;
|
||||
}
|
||||
|
||||
// If there are more than 6 domains, display a "View assigned domains" link
|
||||
domainsHTML += `<p class="font-body-xs"><a href="${action_url}/domains">View domain assignments</a></p>`;
|
||||
|
||||
domainsHTML += "</section>"
|
||||
domainsHTML += "</div>";
|
||||
|
||||
return domainsHTML;
|
||||
|
@ -365,7 +375,7 @@ export class MembersTable extends BaseTable {
|
|||
* - VIEW_ALL_REQUESTS
|
||||
* - EDIT_MEMBERS
|
||||
* - VIEW_MEMBERS
|
||||
*
|
||||
* @param {String} unique_id
|
||||
* @returns {string} - A string of HTML representing the user's additional permissions.
|
||||
* If the user has no specific permissions, it returns a default message
|
||||
* indicating no additional permissions.
|
||||
|
@ -380,51 +390,51 @@ export class MembersTable extends BaseTable {
|
|||
* - If no relevant permissions are found, the function returns a message stating that the user has no additional permissions.
|
||||
* - The resulting HTML always includes a header "Additional permissions for this member" and appends the relevant permission descriptions.
|
||||
*/
|
||||
generatePermissionsHTML(is_admin, member_permissions, UserPortfolioPermissionChoices) {
|
||||
let permissionsHTML = '';
|
||||
|
||||
// Define shared classes across elements for easier refactoring
|
||||
let sharedParagraphClasses = "font-body-xs text-base-darker margin-top-1 p--blockquote";
|
||||
|
||||
// Member access
|
||||
if (is_admin) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Member access: <strong>Admin</strong></p>`;
|
||||
} else {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Member access: <strong>Basic</strong></p>`;
|
||||
}
|
||||
|
||||
// Check domain-related permissions
|
||||
generatePermissionsHTML(is_admin, member_permissions, UserPortfolioPermissionChoices, unique_id) {
|
||||
// 1. Role
|
||||
const memberAccessValue = is_admin ? "Admin" : "Basic";
|
||||
|
||||
// 2. Domain access
|
||||
let domainValue = "No access";
|
||||
if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Domains: <strong>Viewer</strong></p>`;
|
||||
domainValue = "Viewer";
|
||||
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_MANAGED_DOMAINS)) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Domains: <strong>Viewer, limited</strong></p>`;
|
||||
domainValue = "Viewer, limited";
|
||||
}
|
||||
|
||||
// Check request-related permissions
|
||||
|
||||
// 3. Request access
|
||||
let requestValue = "No access";
|
||||
if (member_permissions.includes(UserPortfolioPermissionChoices.EDIT_REQUESTS)) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Domain requests: <strong>Creator</strong></p>`;
|
||||
requestValue = "Creator";
|
||||
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS)) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Domain requests: <strong>Viewer</strong></p>`;
|
||||
} else {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Domain requests: <strong>No access</strong></p>`;
|
||||
requestValue = "Viewer";
|
||||
}
|
||||
|
||||
// Check member-related permissions
|
||||
|
||||
// 4. Member access
|
||||
let memberValue = "No access";
|
||||
if (member_permissions.includes(UserPortfolioPermissionChoices.EDIT_MEMBERS)) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Members: <strong>Manager</strong></p>`;
|
||||
memberValue = "Manager";
|
||||
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_MEMBERS)) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Members: <strong>Viewer</strong></p>`;
|
||||
} else {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>Members: <strong>No access</strong></p>`;
|
||||
memberValue = "Viewer";
|
||||
}
|
||||
|
||||
// If no specific permissions are assigned, display a message indicating no additional permissions
|
||||
if (!permissionsHTML) {
|
||||
permissionsHTML += `<p class='${sharedParagraphClasses}'>No additional permissions: <strong>There are no additional permissions for this member</strong>.</p>`;
|
||||
}
|
||||
|
||||
// Add a permissions header and wrap the entire output in a container
|
||||
permissionsHTML = `<div class='desktop:grid-col-8'><h4 class='font-body-xs margin-y-0'>Member access and permissions</h4>${permissionsHTML}</div>`;
|
||||
|
||||
// Helper function for faster element refactoring
|
||||
const createPermissionItem = (label, value) => {
|
||||
return `<p class="font-body-xs text-base-darker margin-top-1 p--blockquote">${label}: <strong>${value}</strong></p>`;
|
||||
};
|
||||
const permissionsHTML = `
|
||||
<div class="desktop:grid-col-8">
|
||||
<h4 id="member-access--heading-${unique_id}" class="font-body-xs margin-y-0">
|
||||
Member access and permissions
|
||||
</h4>
|
||||
<section aria-labelledby="member-access--heading-${unique_id}" tabindex="0">
|
||||
${createPermissionItem("Member access", memberAccessValue)}
|
||||
${createPermissionItem("Domains", domainValue)}
|
||||
${createPermissionItem("Domain requests", requestValue)}
|
||||
${createPermissionItem("Members", memberValue)}
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return permissionsHTML;
|
||||
}
|
||||
|
|
|
@ -498,7 +498,7 @@ input[type=submit].button--dja-toolbar:focus, input[type=submit].button--dja-too
|
|||
font-size: 13px;
|
||||
}
|
||||
|
||||
.object-tools li button {
|
||||
.object-tools li button, button.addlink {
|
||||
font-family: Source Sans Pro Web, Helvetica Neue, Helvetica, Roboto, Arial, sans-serif;
|
||||
text-transform: none !important;
|
||||
font-size: 14px !important;
|
||||
|
@ -520,6 +520,14 @@ input[type=submit].button--dja-toolbar:focus, input[type=submit].button--dja-too
|
|||
}
|
||||
}
|
||||
|
||||
// Mimic the style for <a>
|
||||
.object-tools > p > button.addlink {
|
||||
background-image: url(../admin/img/tooltag-add.svg) !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: right 7px center !important;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.usa-modal--django-admin .usa-prose ul > li {
|
||||
list-style-type: inherit;
|
||||
// Styling based off of the <p> styling in django admin
|
||||
|
@ -984,3 +992,7 @@ ul.add-list-reset {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#result_list > tbody tr > th > a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
{% if has_absolute_url %}
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% translate "History" %}</a>
|
||||
<button data-href="{% add_preserved_filters history_url %}" class="historylink use-button-as-link">{% translate "History" %}</button>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ absolute_url }}" class="viewsitelink">{% translate "View on site" %}</a>
|
||||
<button data-href="{{ absolute_url }}" class="viewsitelink use-button-as-link">{% translate "View on site" %}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
|
@ -30,18 +30,18 @@
|
|||
{% endif %}
|
||||
|
||||
<li>
|
||||
<a href="{% add_preserved_filters history_url %}">{% translate "History" %}</a>
|
||||
<button data-href="{% add_preserved_filters history_url %}" class="historylink use-button-as-link">{% translate "History" %}</button>
|
||||
</li>
|
||||
|
||||
{% if opts.model_name == 'domainrequest' %}
|
||||
<li>
|
||||
<a id="id-copy-to-clipboard-summary" class="usa-button--dja" type="button" href="#">
|
||||
<button id="id-copy-to-clipboard-summary" class="usa-button--dja">
|
||||
<svg class="usa-icon">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#content_copy"></use>
|
||||
</svg>
|
||||
<!-- the span is targeted in JS, do not remove -->
|
||||
<span>{% translate "Copy request summary" %}</span>
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
{% if has_add_permission %}
|
||||
<p class="margin-0 padding-0">
|
||||
{% url cl.opts|admin_urlname:'add' as add_url %}
|
||||
<a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink">
|
||||
<button data-href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink use-button-as-link">
|
||||
{% blocktranslate with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktranslate %}
|
||||
</a>
|
||||
</button>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -19,11 +19,11 @@ Load our custom filters to extract info from the django generated markup.
|
|||
|
||||
{% if results.0|contains_checkbox %}
|
||||
{# .gov - hardcode the select all checkbox #}
|
||||
<th scope="col" class="action-checkbox-column" title="Toggle all">
|
||||
<th scope="col" class="action-checkbox-column" title="Toggle">
|
||||
<div class="text">
|
||||
<span>
|
||||
<input type="checkbox" id="action-toggle">
|
||||
<label for="action-toggle" class="usa-sr-only">Toggle all</label>
|
||||
<input type="checkbox" id="action-toggle">
|
||||
</span>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
|
@ -34,9 +34,9 @@ Load our custom filters to extract info from the django generated markup.
|
|||
{% if header.sortable %}
|
||||
{% if header.sort_priority > 0 %}
|
||||
<div class="sortoptions">
|
||||
<a class="sortremove" href="{{ header.url_remove }}" title="{% translate "Remove from sorting" %}"></a>
|
||||
<a class="sortremove" href="{{ header.url_remove }}" aria-label="{{ header.text }}" title="{% translate "Remove from sorting" %}"></a>
|
||||
{% if num_sorted_fields > 1 %}<span class="sortpriority" title="{% blocktranslate with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktranslate %}">{{ header.sort_priority }}</span>{% endif %}
|
||||
<a href="{{ header.url_toggle }}" class="toggle {% if header.ascending %}ascending{% else %}descending{% endif %}" title="{% translate "Toggle sorting" %}"></a>
|
||||
<a href="{{ header.url_toggle }}" aria-label="{{ header.text }} sorting {% if header.ascending %}ascending{% else %}descending{% endif %}" class="toggle {% if header.ascending %}ascending{% else %}descending{% endif %}" title="{% translate "Toggle sorting" %}"></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -61,10 +61,10 @@ Load our custom filters to extract info from the django generated markup.
|
|||
{% endif %}
|
||||
<tr>
|
||||
{% with result_value=result.0|extract_value %}
|
||||
{% with result_label=result.1|extract_a_text %}
|
||||
{% with result_label=result.1|extract_a_text checkbox_id="select-"|add:result_value %}
|
||||
<td>
|
||||
<input type="checkbox" name="_selected_action" value="{{ result_value|default:'value' }}" id="{{ result_value|default:'value' }}-{{ result_label|default:'label' }}" class="action-select">
|
||||
<label class="usa-sr-only" for="{{ result_value|default:'value' }}-{{ result_label|default:'label' }}">{{ result_label|default:'label' }}</label>
|
||||
<label class="usa-sr-only" for="{{ checkbox_id }}">Select row {{ result_label|default:'label' }}</label>
|
||||
<input type="checkbox" name="_selected_action" value="{{ result_value|default:'value' }}" id="{{ checkbox_id }}" class="action-select">
|
||||
</td>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{% load i18n %}
|
||||
{% load admin_urls %}
|
||||
|
||||
{% if has_export_permission %}
|
||||
{% comment %} Uses the initButtonLinks {% endcomment %}
|
||||
<li><button class="export_link use-button-as-link" data-href="{% url opts|admin_urlname:"export" %}">{% trans "Export" %}</button></li>
|
||||
{% endif %}
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
{% if has_import_permission %}
|
||||
{% if not IS_PRODUCTION %}
|
||||
<li><a href='{% url opts|admin_urlname:"import" %}' class="import_link">{% trans "Import" %}</a></li>
|
||||
<li><button class="import_link use-button-as-link" data-href="{% url opts|admin_urlname:"import" %}">{% trans "Import" %}</button></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
26
src/registrar/templates/admin/search_form.html
Normal file
26
src/registrar/templates/admin/search_form.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
{% comment %} This is an override of the django search bar to add better accessibility compliance.
|
||||
There are no blocks defined here, so we had to copy the code.
|
||||
https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/search_form.html
|
||||
{% endcomment %}
|
||||
{% load i18n static %}
|
||||
{% if cl.search_fields %}
|
||||
<div id="toolbar"><form id="changelist-search" method="get" role="search">
|
||||
<div><!-- DIV needed for valid HTML -->
|
||||
{% comment %} .gov override - removed for="searchbar" {% endcomment %}
|
||||
<label><img src="{% static "admin/img/search.svg" %}" alt="Search"></label>
|
||||
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar"{% if cl.search_help_text %} aria-describedby="searchbar_helptext"{% endif %}>
|
||||
<input type="submit" value="{% translate 'Search' %}">
|
||||
{% if show_result_count %}
|
||||
<span class="small quiet">{% blocktranslate count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktranslate %} (<a href="?{% if cl.is_popup %}{{ is_popup_var }}=1{% if cl.add_facets %}&{% endif %}{% endif %}{% if cl.add_facets %}{{ is_facets_var }}{% endif %}">{% if cl.show_full_result_count %}{% blocktranslate with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktranslate %}{% else %}{% translate "Show all" %}{% endif %}</a>)</span>
|
||||
{% endif %}
|
||||
{% for pair in cl.params.items %}
|
||||
{% if pair.0 != search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}">{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if cl.search_help_text %}
|
||||
<br class="clear">
|
||||
{% comment %} .gov override - added for="searchbar" {% endcomment %}
|
||||
<label class="help" id="searchbar_helptext" for="searchbar">{{ cl.search_help_text }}</label>
|
||||
{% endif %}
|
||||
</form></div>
|
||||
{% endif %}
|
|
@ -68,10 +68,12 @@ Learn more about:
|
|||
NEED ASSISTANCE?
|
||||
If you have questions about this domain request or need help choosing a new domain name, reply to this email.
|
||||
{% endif %}
|
||||
{% if reason != domain_request.RejectionReasons.REQUESTOR_NOT_ELIGIBLE and reason != domain_request.RejectionReasons.ORG_NOT_ELIGIBLE %}
|
||||
|
||||
THANK YOU
|
||||
.Gov helps the public identify official, trusted information. Thank you for requesting a .gov domain.
|
||||
|
||||
{% endif %}
|
||||
----------------------------------------------------------------
|
||||
|
||||
The .gov team
|
||||
|
|
|
@ -25,11 +25,15 @@ def extract_a_text(value):
|
|||
pattern = r"<a\b[^>]*>(.*?)</a>"
|
||||
match = re.search(pattern, value)
|
||||
if match:
|
||||
extracted_text = match.group(1)
|
||||
else:
|
||||
extracted_text = ""
|
||||
# Get the content and strip any nested HTML tags
|
||||
content = match.group(1)
|
||||
# Remove any nested HTML tags (like <img>)
|
||||
text_pattern = r"<[^>]+>"
|
||||
text_only = re.sub(text_pattern, "", content)
|
||||
# Clean up any extra whitespace
|
||||
return text_only.strip()
|
||||
|
||||
return extracted_text
|
||||
return ""
|
||||
|
||||
|
||||
@register.filter
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue