mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-22 18:56:15 +02:00
UI
This commit is contained in:
parent
472186e9b4
commit
c5de4b3a1d
6 changed files with 104 additions and 26 deletions
|
@ -1873,6 +1873,41 @@ class MembersTable extends LoadTableBase {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('.members__table', '.members__table-wrapper', '#members__search-field', '#members__search-field-submit', '.members__reset-search', '.members__reset-filters', '.members__no-data', '.members__no-search-results');
|
super('.members__table', '.members__table-wrapper', '#members__search-field', '#members__search-field-submit', '.members__reset-search', '.members__reset-filters', '.members__no-data', '.members__no-search-results');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initShowMoreButtons() {
|
||||||
|
function toggleShowMoreButton(toggleButton, contentDiv, buttonParentRow) {
|
||||||
|
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');
|
||||||
|
} else {
|
||||||
|
hideElement(contentDiv);
|
||||||
|
spanElement.textContent = 'Expand';
|
||||||
|
useElement.setAttribute('xlink:href', '/public/img/sprite.svg#expand_more');
|
||||||
|
buttonParentRow.classList.remove('hide-td-borders');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let toggleButtons = document.querySelectorAll('.usa-button--show-more-button');
|
||||||
|
toggleButtons.forEach((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') {
|
||||||
|
toggleButton.addEventListener('click', function() {
|
||||||
|
toggleShowMoreButton(toggleButton, contentDiv, buttonParentRow);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('Found a toggle button with no associated toggleable content or parent row');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads rows in the members list, as well as updates pagination around the members list
|
* Loads rows in the members list, as well as updates pagination around the members list
|
||||||
* based on the supplied attributes.
|
* based on the supplied attributes.
|
||||||
|
@ -1930,6 +1965,7 @@ class MembersTable extends LoadTableBase {
|
||||||
const invited = 'Invited';
|
const invited = 'Invited';
|
||||||
|
|
||||||
data.members.forEach(member => {
|
data.members.forEach(member => {
|
||||||
|
const member_id = member.source + member.id;
|
||||||
const member_name = member.name;
|
const member_name = member.name;
|
||||||
const member_display = member.member_display;
|
const member_display = member.member_display;
|
||||||
const member_permissions = member.permissions;
|
const member_permissions = member.permissions;
|
||||||
|
@ -1979,9 +2015,10 @@ class MembersTable extends LoadTableBase {
|
||||||
|
|
||||||
let domainsHTML = '';
|
let domainsHTML = '';
|
||||||
if (num_domains > 0) {
|
if (num_domains > 0) {
|
||||||
domainsHTML += "<h3>Domains assigned</h3>";
|
domainsHTML += "<div class='desktop:grid-col-5 margin-bottom-2 desktop:margin-bottom-0'>";
|
||||||
domainsHTML += "<p>This member is assigned to " + num_domains + " domains:";
|
domainsHTML += "<h4 class='margin-y-0 text-primary'>Domains assigned</h4>";
|
||||||
domainsHTML += "<ul>";
|
domainsHTML += "<p class='margin-y-0'>This member is assigned to " + num_domains + " domains:";
|
||||||
|
domainsHTML += "<ul class='usa-list usa-list--unstyled margin-y-0'>";
|
||||||
for (let i = 0; i < num_domains && i < 6; i++) {
|
for (let i = 0; i < num_domains && i < 6; i++) {
|
||||||
domainsHTML += `<li><a href="${domain_urls[i]}">${domain_names[i]}</a></li>`;
|
domainsHTML += `<li><a href="${domain_urls[i]}">${domain_names[i]}</a></li>`;
|
||||||
}
|
}
|
||||||
|
@ -1989,42 +2026,62 @@ class MembersTable extends LoadTableBase {
|
||||||
if (num_domains >= 6) {
|
if (num_domains >= 6) {
|
||||||
domainsHTML += "<p><a href='#'>View assigned domains</a></p>";
|
domainsHTML += "<p><a href='#'>View assigned domains</a></p>";
|
||||||
}
|
}
|
||||||
|
domainsHTML += "</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissionsHTML = '';
|
let permissionsHTML = '';
|
||||||
// only display domains permissions if domains assigned
|
if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)) {
|
||||||
if (domainsHTML) {
|
permissionsHTML += "<p class='margin-top-1 p--blockquote'><strong class='text-base-dark'>Domains:</strong> Can view all organization domains. Can manage domains they are assigned to and edit information about the domain (including DNS settings).</p>";
|
||||||
if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)) {
|
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_MANAGED_DOMAINS)) {
|
||||||
permissionsHTML += "<p><b>Domains:</b> Can view all organization domains. Can manage domains they are assigned to and edit information about the domain (including DNS settings).</p>";
|
permissionsHTML += "<p class='margin-top-1 p--blockquote'><strong class='text-base-dark'>Domains:</strong> Can manage domains they are assigned to and edit information about the domain (including DNS settings).</p>";
|
||||||
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_MANAGED_DOMAINS)) {
|
|
||||||
permissionsHTML += "<p><b>Domains:</b> Can manage domains they are assigned to and edit information about the domain (including DNS settings).</p>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (member_permissions.includes(UserPortfolioPermissionChoices.EDIT_REQUESTS)) {
|
if (member_permissions.includes(UserPortfolioPermissionChoices.EDIT_REQUESTS)) {
|
||||||
permissionsHTML += "<p><b>Domain requests:</b> Can view all organization domain requests. Can create domain requests and modify their own requests.</p>";
|
permissionsHTML += "<p class='margin-top-1 p--blockquote'><strong class='text-base-dark'>Domain requests:</strong> Can view all organization domain requests. Can create domain requests and modify their own requests.</p>";
|
||||||
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS)) {
|
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS)) {
|
||||||
permissionsHTML += "<p><b>Domain requests (view-only):</b> Can view all organization domain requests. Can't create or modify any domain requests.</p>";
|
permissionsHTML += "<p class='margin-top-1 p--blockquote'><strong class='text-base-dark'>Domain requests (view-only):</strong> Can view all organization domain requests. Can't create or modify any domain requests.</p>";
|
||||||
}
|
}
|
||||||
if (member_permissions.includes(UserPortfolioPermissionChoices.EDIT_MEMBERS)) {
|
if (member_permissions.includes(UserPortfolioPermissionChoices.EDIT_MEMBERS)) {
|
||||||
permissionsHTML += "<p><b>Members:</b> Can manage members including inviting new members, removing current members, and assigning domains to members.";
|
permissionsHTML += "<p class='margin-top-1 p--blockquote'><strong class='text-base-dark'>Members:</strong> Can manage members including inviting new members, removing current members, and assigning domains to members.";
|
||||||
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_MEMBERS)) {
|
} else if (member_permissions.includes(UserPortfolioPermissionChoices.VIEW_MEMBERS)) {
|
||||||
permissionsHTML += "<p><b>Members (view-only):</b> Can view all organizational members. Can't manage any members.";
|
permissionsHTML += "<p> class='margin-top-1 p--blockquote'><strong class='text-base-dark'>Members (view-only):</strong> Can view all organizational members. Can't manage any members.";
|
||||||
}
|
}
|
||||||
// if there are no additional permissions, display a no additional permissions message
|
// if there are no additional permissions, display a no additional permissions message
|
||||||
if (!permissionsHTML) {
|
if (!permissionsHTML) {
|
||||||
permissionsHTML += "<p><b>No additional permissions:</b> There are no additional permissions for this member.</p>";
|
permissionsHTML += "<p><b>No additional permissions:</b> There are no additional permissions for this member.</p>";
|
||||||
}
|
}
|
||||||
// add permissions header in all cases
|
// add permissions header in all cases
|
||||||
permissionsHTML = "<h3>Additional permissions for this member</h3>" + permissionsHTML;
|
permissionsHTML = "<div class='desktop:grid-col-7'><h4 class='margin-y-0 text-primary'>Additional permissions for this member</h4>" + permissionsHTML + "</div>";
|
||||||
|
|
||||||
|
let showMoreButton = '';
|
||||||
|
const showMoreRow = document.createElement('tr');
|
||||||
|
if (domainsHTML || permissionsHTML) {
|
||||||
|
showMoreButton = `
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="usa-button--show-more-button usa-button usa-button--unstyled display-block margin-top-2"
|
||||||
|
data-for=${member_id}
|
||||||
|
>
|
||||||
|
<span>Expand</span>
|
||||||
|
<svg class="usa-icon usa-icon--big" aria-hidden="true" focusable="false" role="img" width="24">
|
||||||
|
<use xlink:href="/public/img/sprite.svg#expand_more"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
showMoreRow.innerHTML = `<td colspan='3' headers="header-member" class="padding-top-0"><div class='grid-row'>${domainsHTML} ${permissionsHTML}</div></td>`;
|
||||||
|
showMoreRow.classList.add('show-more-content');
|
||||||
|
showMoreRow.classList.add('display-none');
|
||||||
|
showMoreRow.id = member_id;
|
||||||
|
}
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<th scope="row" role="rowheader" data-label="member email">
|
<th role="rowheader" headers="header-member" data-label="member email" id='row-header-${member_id}'>
|
||||||
${member_display} ${admin_tagHTML} ${domainsHTML} ${permissionsHTML}
|
${member_display} ${admin_tagHTML} ${showMoreButton}
|
||||||
</th>
|
</th>
|
||||||
<td data-sort-value="${last_active_sort_value}" data-label="last_active">
|
<td headers="header-last-active row-header-${member_id}" data-sort-value="${last_active_sort_value}" data-label="last_active">
|
||||||
${last_active_formatted}
|
${last_active_formatted}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td headers="header-action row-header-${member_id}">
|
||||||
<a href="${action_url}">
|
<a href="${action_url}">
|
||||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
||||||
<use xlink:href="/public/img/sprite.svg#${svg_icon}"></use>
|
<use xlink:href="/public/img/sprite.svg#${svg_icon}"></use>
|
||||||
|
@ -2034,8 +2091,13 @@ class MembersTable extends LoadTableBase {
|
||||||
</td>
|
</td>
|
||||||
`;
|
`;
|
||||||
memberList.appendChild(row);
|
memberList.appendChild(row);
|
||||||
|
if (domainsHTML || permissionsHTML) {
|
||||||
|
memberList.appendChild(showMoreRow);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.initShowMoreButtons();
|
||||||
|
|
||||||
// Do not scroll on first page load
|
// Do not scroll on first page load
|
||||||
if (scroll)
|
if (scroll)
|
||||||
ScrollToElement('class', 'members');
|
ScrollToElement('class', 'members');
|
||||||
|
|
|
@ -258,3 +258,11 @@ a.text-secondary,
|
||||||
a.text-secondary:hover {
|
a.text-secondary:hover {
|
||||||
color: $theme-color-error;
|
color: $theme-color-error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.usa-button--show-more-button {
|
||||||
|
font-size: size('ui', 'xs');
|
||||||
|
text-decoration: none;
|
||||||
|
.usa-icon {
|
||||||
|
top: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -56,8 +56,10 @@ th {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
td, th {
|
tr:not(.hide-td-borders) {
|
||||||
border-bottom: 1px solid color('base-lighter');
|
td, th {
|
||||||
|
border-bottom: 1px solid color('base-lighter');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thead th {
|
thead th {
|
||||||
|
|
|
@ -28,3 +28,8 @@ h2 {
|
||||||
.usa-form fieldset {
|
.usa-form fieldset {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p--blockquote {
|
||||||
|
padding-left: units(1);
|
||||||
|
border-left: 2px solid color('base-lighter');
|
||||||
|
}
|
||||||
|
|
|
@ -39,16 +39,16 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ---------- MAIN TABLE ---------- -->
|
<!-- ---------- MAIN TABLE ---------- -->
|
||||||
<div class="members__table-wrapper display-none usa-table-container--scrollable margin-top-0" tabindex="0">
|
<div class="members__table-wrapper display-none margin-top-0">
|
||||||
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked members__table">
|
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked members__table">
|
||||||
<caption class="sr-only">Your registered members</caption>
|
<caption class="sr-only">Your registered members</caption>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th data-sortable="member" scope="col" role="columnheader">Member</th>
|
<th data-sortable="member" role="columnheader" id="header-member">Member</th>
|
||||||
<th data-sortable="last_active" scope="col" role="columnheader">Last Active</th>
|
<th data-sortable="last_active" role="columnheader" id="header-last-active">Last Active</th>
|
||||||
<th
|
<th
|
||||||
scope="col"
|
role="columnheader"
|
||||||
role="columnheader"
|
id="header-action"
|
||||||
>
|
>
|
||||||
<span class="usa-sr-only">Action</span>
|
<span class="usa-sr-only">Action</span>
|
||||||
</th>
|
</th>
|
||||||
|
|
|
@ -175,6 +175,7 @@ def serialize_members(request, portfolio, item, user):
|
||||||
# Serialize member data
|
# Serialize member data
|
||||||
member_json = {
|
member_json = {
|
||||||
"id": item.get("id", ""),
|
"id": item.get("id", ""),
|
||||||
|
"source": item.get("source", ""),
|
||||||
"name": " ".join(filter(None, [item.get("first_name", ""), item.get("last_name", "")])),
|
"name": " ".join(filter(None, [item.get("first_name", ""), item.get("last_name", "")])),
|
||||||
"email": item.get("email_display", ""),
|
"email": item.get("email_display", ""),
|
||||||
"member_display": item.get("member_display", ""),
|
"member_display": item.get("member_display", ""),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue