mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-13 13:09:41 +02:00
wip
This commit is contained in:
parent
cc7f588dad
commit
be8a618791
12 changed files with 212 additions and 22 deletions
|
@ -1168,7 +1168,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const statusCheckboxes = document.querySelectorAll('input[name="filter-status"]');
|
const statusCheckboxes = document.querySelectorAll('input[name="filter-status"]');
|
||||||
const statusIndicator = document.querySelector('.domain__filter-indicator');
|
const statusIndicator = document.querySelector('.domain__filter-indicator');
|
||||||
const statusToggle = document.querySelector('.usa-button--filter');
|
const statusToggle = document.querySelector('.usa-button--filter');
|
||||||
const noPortfolioFlag = document.getElementById('no-portfolio-js-flag');
|
|
||||||
const portfolioElement = document.getElementById('portfolio-js-value');
|
const portfolioElement = document.getElementById('portfolio-js-value');
|
||||||
const portfolioValue = portfolioElement ? portfolioElement.getAttribute('data-portfolio') : null;
|
const portfolioValue = portfolioElement ? portfolioElement.getAttribute('data-portfolio') : null;
|
||||||
|
|
||||||
|
@ -1226,7 +1225,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
let markupForSuborganizationRow = '';
|
let markupForSuborganizationRow = '';
|
||||||
|
|
||||||
if (!noPortfolioFlag) {
|
if (portfolioValue) {
|
||||||
markupForSuborganizationRow = `
|
markupForSuborganizationRow = `
|
||||||
<td>
|
<td>
|
||||||
<span class="${suborganization ? 'ellipsis ellipsis--30 vertical-align-middle' : ''}" aria-label="${suborganization}" title="${suborganization}">${suborganization}</span>
|
<span class="${suborganization ? 'ellipsis ellipsis--30 vertical-align-middle' : ''}" aria-label="${suborganization}" title="${suborganization}">${suborganization}</span>
|
||||||
|
@ -1485,6 +1484,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const tableHeaders = document.querySelectorAll('.domain-requests__table th[data-sortable]');
|
const tableHeaders = document.querySelectorAll('.domain-requests__table th[data-sortable]');
|
||||||
const tableAnnouncementRegion = document.querySelector('.domain-requests__table-wrapper .usa-table__announcement-region');
|
const tableAnnouncementRegion = document.querySelector('.domain-requests__table-wrapper .usa-table__announcement-region');
|
||||||
const resetSearchButton = document.querySelector('.domain-requests__reset-search');
|
const resetSearchButton = document.querySelector('.domain-requests__reset-search');
|
||||||
|
const portfolioElement = document.getElementById('portfolio-js-value');
|
||||||
|
const portfolioValue = portfolioElement ? portfolioElement.getAttribute('data-portfolio') : null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete is actually a POST API that requires a csrf token. The token will be waiting for us in the template as a hidden input.
|
* Delete is actually a POST API that requires a csrf token. The token will be waiting for us in the template as a hidden input.
|
||||||
|
@ -1533,7 +1534,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
* @param {*} scroll - control for the scrollToElement functionality
|
* @param {*} scroll - control for the scrollToElement functionality
|
||||||
* @param {*} searchTerm - the search term
|
* @param {*} searchTerm - the search term
|
||||||
*/
|
*/
|
||||||
function loadDomainRequests(page, sortBy = currentSortBy, order = currentOrder, scroll = scrollToTable, searchTerm = currentSearchTerm) {
|
function loadDomainRequests(page, sortBy = currentSortBy, order = currentOrder, scroll = scrollToTable, searchTerm = currentSearchTerm, portfolio = portfolioValue) {
|
||||||
// fetch json of page of domain requests, given params
|
// fetch json of page of domain requests, given params
|
||||||
let baseUrl = document.getElementById("get_domain_requests_json_url");
|
let baseUrl = document.getElementById("get_domain_requests_json_url");
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
|
@ -1545,7 +1546,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(`${baseUrlValue}?page=${page}&sort_by=${sortBy}&order=${order}&search_term=${searchTerm}`)
|
// fetch json of page of requests, given params
|
||||||
|
let url = `${baseUrlValue}?page=${page}&sort_by=${sortBy}&order=${order}&search_term=${searchTerm}`
|
||||||
|
if (portfolio)
|
||||||
|
url += `&portfolio=${portfolio}`
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
|
@ -1601,10 +1607,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const actionLabel = request.action_label;
|
const actionLabel = request.action_label;
|
||||||
const submissionDate = request.last_submitted_date ? new Date(request.last_submitted_date).toLocaleDateString('en-US', options) : `<span class="text-base">Not submitted</span>`;
|
const submissionDate = request.last_submitted_date ? new Date(request.last_submitted_date).toLocaleDateString('en-US', options) : `<span class="text-base">Not submitted</span>`;
|
||||||
|
|
||||||
// Even if the request is not deletable, we may need this empty string for the td if the deletable column is displayed
|
// Delete markup will either be a simple trigger or a 3 dots menu with a hidden trigger (in the case of portfolio requests page)
|
||||||
|
// Even if the request is not deletable, we may need these empty strings for the td if the deletable column is displayed
|
||||||
let modalTrigger = '';
|
let modalTrigger = '';
|
||||||
|
|
||||||
// If the request is deletable, create modal body and insert it
|
// If the request is deletable, create modal body and insert it. This is true for both requests and portfolio requests pages
|
||||||
if (request.is_deletable) {
|
if (request.is_deletable) {
|
||||||
let modalHeading = '';
|
let modalHeading = '';
|
||||||
let modalDescription = '';
|
let modalDescription = '';
|
||||||
|
@ -1692,7 +1699,44 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
`
|
`
|
||||||
|
|
||||||
domainRequestsSectionWrapper.appendChild(modal);
|
domainRequestsSectionWrapper.appendChild(modal);
|
||||||
|
|
||||||
|
// Request is deletable, modal and modalTrigger are built. Now test is portfolio requests page and enhace the modalTrigger markup
|
||||||
|
if (portfolioValue) {
|
||||||
|
modalTrigger = `
|
||||||
|
<div class="usa-accordion usa-accordion--more-actions margin-right-2">
|
||||||
|
<div class="usa-accordion__heading">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="usa-button usa-button--unstyled usa-accordion__button usa-button--more-actions"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="more-actions-${request.id}"
|
||||||
|
>
|
||||||
|
<svg class="usa-icon top-2px" aria-hidden="true" focusable="false" role="img" width="24">
|
||||||
|
<use xlink:href="/public/img/sprite.svg#more_vert"></use>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="more-actions-${request.id}" class="usa-accordion__content usa-prose shadow-1 left-auto right-0" hidden>
|
||||||
|
<h2>More options</h2>
|
||||||
|
<a
|
||||||
|
role="button"
|
||||||
|
id="button-toggle-delete-domain-alert-${request.id}"
|
||||||
|
href="#toggle-delete-domain-alert-${request.id}"
|
||||||
|
class="usa-button--unstyled text-no-underline late-loading-modal-trigger"
|
||||||
|
aria-controls="toggle-delete-domain-alert-${request.id}"
|
||||||
|
data-open-modal
|
||||||
|
>
|
||||||
|
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
||||||
|
<use xlink:href="/public/img/sprite.svg#delete"></use>
|
||||||
|
</svg> Delete <span class="usa-sr-only">${domainName}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const row = document.createElement('tr');
|
const row = document.createElement('tr');
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
|
@ -1817,6 +1861,36 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeMoreActionMenu(accordionIsOpen) {
|
||||||
|
if (accordionIsOpen.getAttribute("aria-expanded") === "true") {
|
||||||
|
accordionIsOpen.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('focusin', function(event) {
|
||||||
|
const accordions = document.querySelectorAll('.usa-accordion--more-actions');
|
||||||
|
const openAccordions = document.querySelectorAll('.usa-button--more-actions[aria-expanded="true"]');
|
||||||
|
|
||||||
|
openAccordions.forEach((openAccordionButton) => {
|
||||||
|
const accordion = openAccordionButton.closest('.usa-accordion--more-actions'); // Find the corresponding accordion
|
||||||
|
if (accordion && !accordion.contains(event.target)) {
|
||||||
|
closeMoreActionMenu(openAccordionButton); // Close the accordion if the focus is outside
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', function(event) {
|
||||||
|
const accordions = document.querySelectorAll('.usa-accordion--more-actions');
|
||||||
|
const openAccordions = document.querySelectorAll('.usa-button--more-actions[aria-expanded="true"]');
|
||||||
|
|
||||||
|
openAccordions.forEach((openAccordionButton) => {
|
||||||
|
const accordion = openAccordionButton.closest('.usa-accordion--more-actions'); // Find the corresponding accordion
|
||||||
|
if (accordion && !accordion.contains(event.target)) {
|
||||||
|
closeMoreActionMenu(openAccordionButton); // Close the accordion if the click is outside
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Initial load
|
// Initial load
|
||||||
loadDomainRequests(1);
|
loadDomainRequests(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
@use "uswds-core" as *;
|
@use "uswds-core" as *;
|
||||||
|
|
||||||
.usa-accordion--select {
|
.usa-accordion--select,
|
||||||
|
.usa-accordion--more-actions {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: auto;
|
width: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -192,3 +192,8 @@ abbr[title] {
|
||||||
max-width: 50ch;
|
max-width: 50ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Boost this USWDS utility class for the accordions in the portfolio requests table
|
||||||
|
.left-auto {
|
||||||
|
left: auto!important;
|
||||||
|
}
|
||||||
|
|
|
@ -89,14 +89,16 @@
|
||||||
.usa-nav__primary {
|
.usa-nav__primary {
|
||||||
.usa-nav-link,
|
.usa-nav-link,
|
||||||
.usa-nav-link:hover,
|
.usa-nav-link:hover,
|
||||||
.usa-nav-link:active {
|
.usa-nav-link:active,
|
||||||
|
button {
|
||||||
color: color('primary');
|
color: color('primary');
|
||||||
font-weight: font-weight('normal');
|
font-weight: font-weight('normal');
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.usa-current,
|
.usa-current,
|
||||||
.usa-current:hover,
|
.usa-current:hover,
|
||||||
.usa-current:active {
|
.usa-current:active,
|
||||||
|
button.usa-current {
|
||||||
font-weight: font-weight('bold');
|
font-weight: font-weight('bold');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,11 @@ urlpatterns = [
|
||||||
views.PortfolioDomainRequestsView.as_view(),
|
views.PortfolioDomainRequestsView.as_view(),
|
||||||
name="domain-requests",
|
name="domain-requests",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"no-organization-requests/",
|
||||||
|
views.PortfolioNoDomainRequestsView.as_view(),
|
||||||
|
name="no-portfolio-requests",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"organization/",
|
"organization/",
|
||||||
views.PortfolioOrganizationView.as_view(),
|
views.PortfolioOrganizationView.as_view(),
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
<span id="get_domain_requests_json_url" class="display-none">{{url}}</span>
|
<span id="get_domain_requests_json_url" class="display-none">{{url}}</span>
|
||||||
<section class="section--outlined domain-requests" id="domain-requests">
|
<section class="section--outlined domain-requests" id="domain-requests">
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
{% if not has_domain_requests_portfolio_permission %}
|
{% if not portfolio %}
|
||||||
<div class="mobile:grid-col-12 desktop:grid-col-6">
|
<div class="mobile:grid-col-12 desktop:grid-col-6">
|
||||||
<h2 id="domain-requests-header" class="flex-6">Domain requests</h2>
|
<h2 id="domain-requests-header" class="flex-6">Domain requests</h2>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<!-- Embedding the portfolio value in a data attribute -->
|
||||||
|
<span id="portfolio-js-value" data-portfolio="{{ portfolio.id }}"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="mobile:grid-col-12 desktop:grid-col-6">
|
<div class="mobile:grid-col-12 desktop:grid-col-6">
|
||||||
<section aria-label="Domain requests search component" class="flex-6 margin-y-2">
|
<section aria-label="Domain requests search component" class="flex-6 margin-y-2">
|
||||||
|
@ -45,7 +48,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th data-sortable="requested_domain__name" scope="col" role="columnheader">Domain name</th>
|
<th data-sortable="requested_domain__name" scope="col" role="columnheader">Domain name</th>
|
||||||
<th data-sortable="last_submitted_date" scope="col" role="columnheader">Date submitted</th>
|
<th data-sortable="last_submitted_date" scope="col" role="columnheader">Submitted</th>
|
||||||
<th data-sortable="status" scope="col" role="columnheader">Status</th>
|
<th data-sortable="status" scope="col" role="columnheader">Status</th>
|
||||||
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
|
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
|
||||||
<!-- AJAX will conditionally add a th for delete actions -->
|
<!-- AJAX will conditionally add a th for delete actions -->
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
<div class="section--outlined__header margin-bottom-3 {% if not portfolio %} section--outlined__header--no-portfolio justify-content-space-between{% else %} grid-row{% endif %}">
|
<div class="section--outlined__header margin-bottom-3 {% if not portfolio %} section--outlined__header--no-portfolio justify-content-space-between{% else %} grid-row{% endif %}">
|
||||||
{% if not portfolio %}
|
{% if not portfolio %}
|
||||||
<h2 id="domains-header" class="display-inline-block">Domains</h2>
|
<h2 id="domains-header" class="display-inline-block">Domains</h2>
|
||||||
<span class="display-none" id="no-portfolio-js-flag"></span>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<!-- Embedding the portfolio value in a data attribute -->
|
<!-- Embedding the portfolio value in a data attribute -->
|
||||||
<span id="portfolio-js-value" data-portfolio="{{ portfolio.id }}"></span>
|
<span id="portfolio-js-value" data-portfolio="{{ portfolio.id }}"></span>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<li class="usa-nav__primary-item">
|
<li class="usa-nav__primary-item">
|
||||||
{% if has_domains_portfolio_permission %}
|
{% if has_domains_portfolio_permission %}
|
||||||
{% url 'domains' as url %}
|
{% url 'domains' as url %}
|
||||||
{%else %}
|
{% else %}
|
||||||
{% url 'no-portfolio-domains' as url %}
|
{% url 'no-portfolio-domains' as url %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ url }}" class="usa-nav-link{% if 'domain'|in_path:request.path %} usa-current{% endif %}">
|
<a href="{{ url }}" class="usa-nav-link{% if 'domain'|in_path:request.path %} usa-current{% endif %}">
|
||||||
|
@ -29,14 +29,38 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% if has_domain_requests_portfolio_permission %}
|
|
||||||
<li class="usa-nav__primary-item">
|
<li class="usa-nav__primary-item">
|
||||||
|
{% if has_domain_requests_portfolio_permission %}
|
||||||
{% url 'domain-requests' as url %}
|
{% url 'domain-requests' as url %}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="usa-accordion__button usa-nav__link{% if 'request'|in_path:request.path %} usa-current{% endif %}"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="basic-nav-section-two"
|
||||||
|
>
|
||||||
|
<span>Domain requests</span>
|
||||||
|
</button>
|
||||||
|
<ul id="basic-nav-section-two" class="usa-nav__submenu">
|
||||||
|
<li class="usa-nav__submenu-item">
|
||||||
|
<a href="{{ url }}"
|
||||||
|
><span>Domain requests</span></a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li class="usa-nav__submenu-item">
|
||||||
|
<a href="{% url 'domain-request:' %}"
|
||||||
|
><span>Start a new domain request</span></a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
{% url 'no-portfolio-requests' as url %}
|
||||||
<a href="{{ url }}" class="usa-nav-link{% if 'request'|in_path:request.path %} usa-current{% endif %}">
|
<a href="{{ url }}" class="usa-nav-link{% if 'request'|in_path:request.path %} usa-current{% endif %}">
|
||||||
Domain requests
|
Domain requests
|
||||||
</a>
|
</a>
|
||||||
</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
<li class="usa-nav__primary-item">
|
<li class="usa-nav__primary-item">
|
||||||
<a href="#" class="usa-nav-link">
|
<a href="#" class="usa-nav-link">
|
||||||
Members
|
Members
|
||||||
|
|
30
src/registrar/templates/portfolio_no_domain_requests.html
Normal file
30
src/registrar/templates/portfolio_no_domain_requests.html
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{% extends 'portfolio_base.html' %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %} Domain Requests | {% endblock %}
|
||||||
|
|
||||||
|
{% block portfolio_content %}
|
||||||
|
<h1 id="domains-header">Current domain requests</h1>
|
||||||
|
<section class="section--outlined">
|
||||||
|
<div class="section--outlined__header margin-bottom-3">
|
||||||
|
<h2 id="domains-header" class="display-inline-block">You don’t have access to domain requests.</h2>
|
||||||
|
{% if portfolio_administrators %}
|
||||||
|
<p>If you believe you should have access to a request, reach out to your organization’s administrators.</p>
|
||||||
|
<p>Your organizations administrators:</p>
|
||||||
|
<ul class="margin-top-0">
|
||||||
|
{% for administrator in portfolio_administrators %}
|
||||||
|
{% if administrator.email %}
|
||||||
|
<li>{{ administrator.email }}</li>
|
||||||
|
{% else %}
|
||||||
|
<li>{{ administrator }}</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p><strong>No administrators were found on your organization.</strong></p>
|
||||||
|
<p>If you believe you should have access to a request, email <a href="mailto:help@get.gov" class="usa-link">help@get.gov</a>.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -12,9 +12,9 @@ def get_domain_requests_json(request):
|
||||||
"""Given the current request,
|
"""Given the current request,
|
||||||
get all domain requests that are associated with the request user and exclude the APPROVED ones"""
|
get all domain requests that are associated with the request user and exclude the APPROVED ones"""
|
||||||
|
|
||||||
domain_requests = DomainRequest.objects.filter(creator=request.user).exclude(
|
domain_request_ids = get_domain_requests_ids_from_request(request)
|
||||||
status=DomainRequest.DomainRequestStatus.APPROVED
|
|
||||||
)
|
domain_requests = DomainRequest.objects.filter(id__in=domain_request_ids)
|
||||||
unfiltered_total = domain_requests.count()
|
unfiltered_total = domain_requests.count()
|
||||||
|
|
||||||
# Handle sorting
|
# Handle sorting
|
||||||
|
@ -97,3 +97,21 @@ def get_domain_requests_json(request):
|
||||||
"unfiltered_total": unfiltered_total,
|
"unfiltered_total": unfiltered_total,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_domain_requests_ids_from_request(request):
|
||||||
|
"""Get domain request ids from request.
|
||||||
|
|
||||||
|
If portfolio specified, return domain request ids associated with portfolio.
|
||||||
|
Otherwise, return domain request ids associated with request.user.
|
||||||
|
"""
|
||||||
|
portfolio = request.GET.get("portfolio")
|
||||||
|
if portfolio:
|
||||||
|
domain_requests = DomainRequest.objects.filter(portfolio=portfolio).exclude(
|
||||||
|
status=DomainRequest.DomainRequestStatus.APPROVED
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
domain_requests = DomainRequest.objects.filter(creator=request.user).exclude(
|
||||||
|
status=DomainRequest.DomainRequestStatus.APPROVED
|
||||||
|
)
|
||||||
|
|
||||||
|
return domain_requests.values_list("id", flat=True)
|
|
@ -47,7 +47,36 @@ class PortfolioNoDomainsView(NoPortfolioDomainsPermissionView, View):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
model = Portfolio
|
model = Portfolio
|
||||||
template_name = "no_portfolio_domains.html"
|
template_name = "portfolio_no_domains.html"
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
return render(request, self.template_name, context=self.get_context_data())
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Add additional context data to the template."""
|
||||||
|
# We can override the base class. This view only needs this item.
|
||||||
|
context = {}
|
||||||
|
portfolio = self.request.session.get("portfolio")
|
||||||
|
if portfolio:
|
||||||
|
admin_ids = UserPortfolioPermission.objects.filter(
|
||||||
|
portfolio=portfolio,
|
||||||
|
roles__overlap=[
|
||||||
|
UserPortfolioRoleChoices.ORGANIZATION_ADMIN,
|
||||||
|
],
|
||||||
|
).values_list("user__id", flat=True)
|
||||||
|
|
||||||
|
admin_users = User.objects.filter(id__in=admin_ids)
|
||||||
|
context["portfolio_administrators"] = admin_users
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class PortfolioNoDomainRequestsView(NoPortfolioDomainsPermissionView, View):
|
||||||
|
"""Some users have access to the underlying portfolio, but not any domain requests.
|
||||||
|
This is a custom view which explains that to the user - and denotes who to contact.
|
||||||
|
"""
|
||||||
|
|
||||||
|
model = Portfolio
|
||||||
|
template_name = "portfolio_no_domain_requests.html"
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
return render(request, self.template_name, context=self.get_context_data())
|
return render(request, self.template_name, context=self.get_context_data())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue