Merge pull request #3294 from cisagov/nl/2969-visual-table-headers

#2969 - Domains and request table needs visual header - [NL]
This commit is contained in:
CuriousX 2025-01-10 21:03:20 -07:00 committed by GitHub
commit 3c91ea4485
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 28 additions and 40 deletions

View file

@ -382,7 +382,7 @@ export class BaseTable {
* for a member, they will also see the kebab column)
* @param {Object} dataObjects - Data which contains info on domain requests or a user's permission
* Currently returns a dictionary of either:
* - "needsAdditionalColumn": If a new column should be displayed
* - "hasAdditionalActions": If additional elements need to be added to the Action column
* - "UserPortfolioPermissionChoices": A user's portfolio permission choices
*/
customizeTable(dataObjects){ return {}; }
@ -406,7 +406,7 @@ export class BaseTable {
* Returns either: data.members, data.domains or data.domain_requests
* @param {Object} dataObject - The data used to populate the row content
* @param {HTMLElement} tbody - The table body to which the new row is appended to
* @param {Object} customTableOptions - Additional options for customizing row appearance (ie needsAdditionalColumn)
* @param {Object} customTableOptions - Additional options for customizing row appearance (ie hasAdditionalActions)
*/
addRow(dataObject, tbody, customTableOptions) {
throw new Error('addRow must be defined');

View file

@ -52,26 +52,8 @@ export class DomainRequestsTable extends BaseTable {
// Manage "export as CSV" visibility for domain requests
this.toggleExportButton(data.domain_requests);
let needsDeleteColumn = data.domain_requests.some(request => request.is_deletable);
// Remove existing delete th and td if they exist
let existingDeleteTh = document.querySelector('.delete-header');
if (!needsDeleteColumn) {
if (existingDeleteTh)
existingDeleteTh.remove();
} else {
if (!existingDeleteTh) {
const delheader = document.createElement('th');
delheader.setAttribute('scope', 'col');
delheader.setAttribute('role', 'columnheader');
delheader.setAttribute('class', 'delete-header width-5');
delheader.innerHTML = `
<span class="usa-sr-only">Delete Action</span>`;
let tableHeaderRow = this.tableWrapper.querySelector('thead tr');
tableHeaderRow.appendChild(delheader);
}
}
return { 'needsAdditionalColumn': needsDeleteColumn };
let isDeletable = data.domain_requests.some(request => request.is_deletable);
return { 'hasAdditionalActions': isDeletable };
}
addRow(dataObject, tbody, customTableOptions) {
@ -88,6 +70,7 @@ export class DomainRequestsTable extends BaseTable {
<span class="usa-sr-only">Domain request cannot be deleted now. Edit the request for more information.</span>`;
let markupCreatorRow = '';
if (this.portfolioValue) {
markupCreatorRow = `
@ -98,7 +81,7 @@ export class DomainRequestsTable extends BaseTable {
}
if (request.is_deletable) {
// 1st path: Just a modal trigger in any screen size for non-org users
// 1st path (non-org): Just a modal trigger in any screen size for non-org users
modalTrigger = `
<a
role="button"
@ -116,7 +99,7 @@ export class DomainRequestsTable extends BaseTable {
// Request is deletable, modal and modalTrigger are built. Now check if we are on the portfolio requests page (by seeing if there is a portfolio value) and enhance the modalTrigger accordingly
if (this.portfolioValue) {
// 2nd path: Just a modal trigger on mobile for org users or kebab + accordion with nested modal trigger on desktop for org users
// 2nd path (org model): Just a modal trigger on mobile for org users or kebab + accordion with nested modal trigger on desktop for org users
modalTrigger = generateKebabHTML('delete-domain', request.id, 'Delete', domainName);
}
}
@ -133,15 +116,17 @@ export class DomainRequestsTable extends BaseTable {
<td data-label="Status">
${request.status}
</td>
<td>
<a href="${actionUrl}">
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="/public/img/sprite.svg#${request.svg_icon}"></use>
</svg>
${actionLabel} <span class="usa-sr-only">${request.requested_domain ? request.requested_domain : 'New domain request'}</span>
</a>
<td class="${ this.portfolioValue ? '' : "width-quarter"}">
<div class="tablet:display-flex tablet:flex-row">
<a href="${actionUrl}" ${customTableOptions.hasAdditionalActions ? "class='margin-right-2'" : ''}>
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="/public/img/sprite.svg#${request.svg_icon}"></use>
</svg>
${actionLabel} <span class="usa-sr-only">${request.requested_domain ? request.requested_domain : 'New domain request'}</span>
</a>
${customTableOptions.hasAdditionalActions ? modalTrigger : ''}
</div>
</td>
${customTableOptions.needsAdditionalColumn ? '<td>'+modalTrigger+'</td>' : ''}
`;
tbody.appendChild(row);
if (request.is_deletable) DomainRequestsTable.addDomainRequestsModal(request.requested_domain, request.id, request.created_at, tbody);

View file

@ -55,7 +55,7 @@ export class DomainsTable extends BaseTable {
</svg>
</td>
${markupForSuborganizationRow}
<td>
<td class="${ this.portfolioValue ? '' : "width-quarter"}">
<a href="${actionUrl}">
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="/public/img/sprite.svg#${domain.svg_icon}"></use>

View file

@ -61,7 +61,7 @@ export class MembersTable extends BaseTable {
tableHeaderRow.appendChild(extraActionsHeader);
}
return {
'needsAdditionalColumn': hasEditPermission,
'hasAdditionalActions': hasEditPermission,
'UserPortfolioPermissionChoices' : data.UserPortfolioPermissionChoices
};
}
@ -78,7 +78,7 @@ export class MembersTable extends BaseTable {
const num_domains = member.domain_urls.length;
const last_active = this.handleLastActive(member.last_active);
let cancelInvitationButton = member.type === "invitedmember" ? "Cancel invitation" : "Remove member";
const kebabHTML = customTableOptions.needsAdditionalColumn ? generateKebabHTML('remove-member', unique_id, cancelInvitationButton, `for ${member.name}`): '';
const kebabHTML = customTableOptions.hasAdditionalActions ? generateKebabHTML('remove-member', unique_id, cancelInvitationButton, `for ${member.name}`): '';
const row = document.createElement('tr');
@ -129,7 +129,7 @@ export class MembersTable extends BaseTable {
${member.action_label} <span class="usa-sr-only">${member.name}</span>
</a>
</td>
${customTableOptions.needsAdditionalColumn ? '<td>'+kebabHTML+'</td>' : ''}
${customTableOptions.hasAdditionalActions ? '<td>'+kebabHTML+'</td>' : ''}
`;
tbody.appendChild(row);
if (domainsHTML || permissionsHTML) {
@ -137,7 +137,7 @@ export class MembersTable extends BaseTable {
}
// This easter egg is only for fixtures that dont have names as we are displaying their emails
// All prod users will have emails linked to their account
if (customTableOptions.needsAdditionalColumn) MembersTable.addMemberDeleteModal(num_domains, member.email || "Samwise Gamgee", member_delete_url, unique_id, row);
if (customTableOptions.hasAdditionalActions) MembersTable.addMemberDeleteModal(num_domains, member.email || "Samwise Gamgee", member_delete_url, unique_id, row);
}
/**

View file

@ -281,4 +281,8 @@ abbr[title] {
.maxw-fit-content {
max-width: fit-content;
}
.width-quarter {
width: 25%;
}

View file

@ -186,8 +186,7 @@
<th data-sortable="creator" scope="col" role="columnheader">Created by</th>
{% endif %}
<th data-sortable="status" scope="col" role="columnheader">Status</th>
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
<!-- AJAX will conditionally add a th for delete actions -->
<th scope="col" role="columnheader">Action</th>
</tr>
</thead>
<tbody id="domain-requests-tbody">

View file

@ -214,7 +214,7 @@
scope="col"
role="columnheader"
>
<span class="usa-sr-only">Action</span>
Action
</th>
</tr>
</thead>