mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-24 18:21:13 +02:00
wip requests
This commit is contained in:
parent
f44d8896cb
commit
699ac294ec
5 changed files with 186 additions and 112 deletions
|
@ -894,11 +894,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
currentPage = page;
|
currentPage = page;
|
||||||
currentSortBy = sortBy;
|
currentSortBy = sortBy;
|
||||||
currentOrder = order;
|
currentOrder = order;
|
||||||
});
|
})
|
||||||
|
.catch(error => console.error('Error fetching domains:', error));
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePagination(currentPage, numPages, hasPrevious, hasNext) {
|
function updatePagination(currentPage, numPages, hasPrevious, hasNext) {
|
||||||
const paginationContainer = document.querySelector('.usa-pagination__list');
|
const paginationContainer = document.querySelector('#domains-pagination .usa-pagination__list');
|
||||||
paginationContainer.innerHTML = '';
|
paginationContainer.innerHTML = '';
|
||||||
|
|
||||||
if (hasPrevious) {
|
if (hasPrevious) {
|
||||||
|
@ -958,3 +959,136 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Load the first page initially
|
// Load the first page initially
|
||||||
loadPage(1);
|
loadPage(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
let currentPage = 1;
|
||||||
|
let currentSortBy = 'id';
|
||||||
|
let currentOrder = 'asc';
|
||||||
|
|
||||||
|
function loadDomainRequestsPage(page, sortBy = currentSortBy, order = currentOrder) {
|
||||||
|
fetch(`/get-domain-requests-json/?page=${page}&sort_by=${sortBy}&order=${order}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tbody = document.querySelector('.dotgov-table__domain-requests tbody');
|
||||||
|
tbody.innerHTML = '';
|
||||||
|
|
||||||
|
data.domain_requests.forEach(request => {
|
||||||
|
const domainName = request.requested_domain ? request.requested_domain.name : `New domain request (${new Date(request.created_at).toLocaleString()} UTC)`;
|
||||||
|
const submissionDate = request.submission_date ? new Date(request.submission_date).toLocaleDateString() : 'Not submitted';
|
||||||
|
const actionUrl = (request.status === 'Started' || request.status === 'Withdrawn') ? `/edit-domain-request/${request.id}` : `/domain-request-status/${request.id}`;
|
||||||
|
const actionLabel = (request.status === 'Started' || request.status === 'Withdrawn') ? 'Edit' : 'Manage';
|
||||||
|
const deleteButton = request.is_deletable ? `
|
||||||
|
<a role="button" href="/domain-request-delete/${request.id}" class="usa-button--unstyled text-no-underline">
|
||||||
|
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
||||||
|
<use xlink:href="/static/img/sprite.svg#delete"></use>
|
||||||
|
</svg> Delete
|
||||||
|
</a>` : '';
|
||||||
|
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
row.innerHTML = `
|
||||||
|
<th scope="row" role="rowheader" data-label="Domain name">
|
||||||
|
${domainName}
|
||||||
|
</th>
|
||||||
|
<td data-sort-value="${new Date(request.submission_date).getTime()}" data-label="Date submitted">
|
||||||
|
${submissionDate}
|
||||||
|
</td>
|
||||||
|
<td data-label="Status">
|
||||||
|
${request.state_display}
|
||||||
|
<svg
|
||||||
|
class="usa-icon usa-tooltip usa-tooltip--registrar text-middle margin-bottom-05 text-accent-cool no-click-outline-and-cursor-help"
|
||||||
|
data-position="top"
|
||||||
|
title="${request.get_state_help_text}"
|
||||||
|
focusable="true"
|
||||||
|
aria-label="Status Information"
|
||||||
|
role="tooltip"
|
||||||
|
>
|
||||||
|
<use aria-hidden="true" xlink:href="/static/img/sprite.svg#info_outline"></use>
|
||||||
|
</svg>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="${actionUrl}">
|
||||||
|
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
||||||
|
<use xlink:href="/static/img/sprite.svg#${request.state === 'deleted' || request.state === 'on hold' ? 'visibility' : 'settings'}"></use>
|
||||||
|
</svg>
|
||||||
|
${actionLabel} <span class="usa-sr-only">${request.requested_domain ? request.requested_domain.name : 'New domain request'}</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>${deleteButton}</td>
|
||||||
|
`;
|
||||||
|
tbody.appendChild(row);
|
||||||
|
});
|
||||||
|
|
||||||
|
updateDomainRequestsPagination(data.page, data.num_pages, data.has_previous, data.has_next);
|
||||||
|
currentPage = page;
|
||||||
|
currentSortBy = sortBy;
|
||||||
|
currentOrder = order;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching domain requests:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDomainRequestsPagination(currentPage, numPages, hasPrevious, hasNext) {
|
||||||
|
const paginationContainer = document.querySelector('#domain-requests-pagination .usa-pagination__list');
|
||||||
|
paginationContainer.innerHTML = '';
|
||||||
|
|
||||||
|
if (hasPrevious) {
|
||||||
|
const prevPageItem = document.createElement('li');
|
||||||
|
prevPageItem.className = 'usa-pagination__item usa-pagination__arrow';
|
||||||
|
prevPageItem.innerHTML = `
|
||||||
|
<a href="javascript:void(0);" class="usa-pagination__link usa-pagination__previous-page" aria-label="Previous page">
|
||||||
|
<svg class="usa-icon" aria-hidden="true" role="img">
|
||||||
|
<use xlink:href="/static/img/sprite.svg#navigate_before"></use>
|
||||||
|
</svg>
|
||||||
|
<span class="usa-pagination__link-text">Previous</span>
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
prevPageItem.querySelector('a').addEventListener('click', () => loadDomainRequestsPage(currentPage - 1));
|
||||||
|
paginationContainer.appendChild(prevPageItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= numPages; i++) {
|
||||||
|
const pageItem = document.createElement('li');
|
||||||
|
pageItem.className = 'usa-pagination__item usa-pagination__page-no';
|
||||||
|
pageItem.innerHTML = `
|
||||||
|
<a href="javascript:void(0);" class="usa-pagination__button" aria-label="Page ${i}">${i}</a>
|
||||||
|
`;
|
||||||
|
if (i === currentPage) {
|
||||||
|
pageItem.querySelector('a').classList.add('usa-current');
|
||||||
|
pageItem.querySelector('a').setAttribute('aria-current', 'page');
|
||||||
|
}
|
||||||
|
pageItem.querySelector('a').addEventListener('click', () => loadDomainRequestsPage(i));
|
||||||
|
paginationContainer.appendChild(pageItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasNext) {
|
||||||
|
const nextPageItem = document.createElement('li');
|
||||||
|
nextPageItem.className = 'usa-pagination__item usa-pagination__arrow';
|
||||||
|
nextPageItem.innerHTML = `
|
||||||
|
<a href="javascript:void(0);" class="usa-pagination__link usa-pagination__next-page" aria-label="Next page">
|
||||||
|
<span class="usa-pagination__link-text">Next</span>
|
||||||
|
<svg class="usa-icon" aria-hidden="true" role="img">
|
||||||
|
<use xlink:href="/static/img/sprite.svg#navigate_next"></use>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
nextPageItem.querySelector('a').addEventListener('click', () => loadDomainRequestsPage(currentPage + 1));
|
||||||
|
paginationContainer.appendChild(nextPageItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listeners to table headers for sorting
|
||||||
|
document.querySelectorAll('.dotgov-table__domain-requests th[data-sortable]').forEach(header => {
|
||||||
|
header.addEventListener('click', function() {
|
||||||
|
const sortBy = this.getAttribute('data-sortable');
|
||||||
|
const order = currentOrder === 'asc' ? 'desc' : 'asc';
|
||||||
|
loadDomainRequestsPage(1, sortBy, order);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load the first page initially
|
||||||
|
loadDomainRequestsPage(1);
|
||||||
|
});
|
||||||
|
|
|
@ -21,6 +21,7 @@ from registrar.views.admin_views import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from registrar.views.domain_request import Step
|
from registrar.views.domain_request import Step
|
||||||
|
from registrar.views.domain_requests_json import get_domain_requests_json
|
||||||
from registrar.views.domains_json import get_domains_json
|
from registrar.views.domains_json import get_domains_json
|
||||||
from registrar.views.utility import always_404
|
from registrar.views.utility import always_404
|
||||||
from api.views import available, get_current_federal, get_current_full
|
from api.views import available, get_current_federal, get_current_full
|
||||||
|
@ -195,6 +196,7 @@ urlpatterns = [
|
||||||
name="domain-user-delete",
|
name="domain-user-delete",
|
||||||
),
|
),
|
||||||
path('get-domains-json/', get_domains_json, name='get_domains_json'),
|
path('get-domains-json/', get_domains_json, name='get_domains_json'),
|
||||||
|
path('get-domain-requests-json/', get_domain_requests_json, name='get_domain_requests_json'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Djangooidc strips out context data from that context, so we define a custom error
|
# Djangooidc strips out context data from that context, so we define a custom error
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<nav aria-label="Pagination" class="usa-pagination">
|
<nav aria-label="Pagination" class="usa-pagination" id="domains-pagination">
|
||||||
<ul class="usa-pagination__list">
|
<ul class="usa-pagination__list">
|
||||||
<!-- Pagination links will be dynamically populated by JS -->
|
<!-- Pagination links will be dynamically populated by JS -->
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -84,118 +84,19 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody id="domain-requests-tbody">
|
||||||
{% for domain_request in domain_requests %}
|
<!-- AJAX will populate this tbody -->
|
||||||
<tr>
|
|
||||||
<th th scope="row" role="rowheader" data-label="Domain name">
|
|
||||||
{% if domain_request.requested_domain is None %}
|
|
||||||
New domain request
|
|
||||||
{# Add a breakpoint #}
|
|
||||||
<div aria-hidden="true"></div>
|
|
||||||
<span class="text-base font-body-xs">({{ domain_request.created_at }} UTC)</span>
|
|
||||||
{% else %}
|
|
||||||
{{ domain_request.requested_domain.name }}
|
|
||||||
{% endif %}
|
|
||||||
</th>
|
|
||||||
<td data-sort-value="{{ domain_request.submission_date|date:"U" }}" data-label="Date submitted">
|
|
||||||
{% if domain_request.submission_date %}
|
|
||||||
{{ domain_request.submission_date|date }}
|
|
||||||
{% else %}
|
|
||||||
<span class="text-base">Not submitted</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td data-label="Status">{{ domain_request.get_status_display }}</td>
|
|
||||||
<td>
|
|
||||||
{% with prefix="New domain request ("%}
|
|
||||||
{% with date=domain_request.created_at|date:"DATETIME_FORMAT"%}
|
|
||||||
{% with name_default=prefix|add:date|add:" UTC)"%}
|
|
||||||
{% if domain_request.status == domain_request.DomainRequestStatus.STARTED or domain_request.status == domain_request.DomainRequestStatus.ACTION_NEEDED or domain_request.status == domain_request.DomainRequestStatus.WITHDRAWN %}
|
|
||||||
<a href="{% url 'edit-domain-request' domain_request.pk %}">
|
|
||||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#edit"></use>
|
|
||||||
</svg>
|
|
||||||
{% if domain_request.requested_domain is not None%}
|
|
||||||
Edit <span class="usa-sr-only">{{ domain_request.requested_domain.name }}</span>
|
|
||||||
{% else %}
|
|
||||||
Edit <span class="usa-sr-only">{{ name_default }}</span>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
<a href="{% url 'domain-request-status' domain_request.pk %}">
|
|
||||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#settings"></use>
|
|
||||||
</svg>
|
|
||||||
Manage <span class="usa-sr-only">{{ domain_request.requested_domain.name|default:name_default }}</span>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endwith %}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
{% if has_deletable_domain_requests %}
|
|
||||||
<td>
|
|
||||||
{% if domain_request.status == "started" or domain_request.status == "withdrawn" %}
|
|
||||||
<a
|
|
||||||
role="button"
|
|
||||||
id="button-toggle-delete-domain-alert-{{ forloop.counter }}"
|
|
||||||
href="#toggle-delete-domain-alert-{{ forloop.counter }}"
|
|
||||||
class="usa-button--unstyled text-no-underline"
|
|
||||||
aria-controls="toggle-delete-domain-alert-{{ forloop.counter }}"
|
|
||||||
data-open-modal
|
|
||||||
>
|
|
||||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#delete"></use>
|
|
||||||
</svg>
|
|
||||||
{% with prefix="New domain request ("%}
|
|
||||||
{% with date=domain_request.created_at|date:"DATETIME_FORMAT"%}
|
|
||||||
{% with name_default=prefix|add:date|add:" UTC)"%}
|
|
||||||
{% if domain_request.requested_domain is not None %}
|
|
||||||
Delete <span class="usa-sr-only">{{ domain_request.requested_domain.name }}</span>
|
|
||||||
{% else %}
|
|
||||||
Delete <span class="usa-sr-only">{{ name_default }}</span>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endwith %}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="usa-modal"
|
|
||||||
id="toggle-delete-domain-alert-{{ forloop.counter }}"
|
|
||||||
aria-labelledby="Are you sure you want to continue?"
|
|
||||||
aria-describedby="Domain will be removed"
|
|
||||||
data-force-action
|
|
||||||
>
|
|
||||||
<form method="POST" action="{% url "domain-request-delete" pk=domain_request.id %}">
|
|
||||||
{% if domain_request.requested_domain is None %}
|
|
||||||
{% if domain_request.created_at %}
|
|
||||||
{% with prefix="(created " %}
|
|
||||||
{% with formatted_date=domain_request.created_at|date:"DATETIME_FORMAT" %}
|
|
||||||
{% with modal_content=prefix|add:formatted_date|add:" UTC)" %}
|
|
||||||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to delete this domain request?" modal_description="This will remove the domain request "|add:modal_content|add:" from the .gov registrar. This action cannot be undone." modal_button=modal_button|safe %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endwith %}
|
|
||||||
{% else %}
|
|
||||||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to delete New domain request?" modal_description="This will remove the domain request from the .gov registrar. This action cannot be undone." modal_button=modal_button|safe %}
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{% with modal_heading_value=domain_request.requested_domain.name|add:"?" %}
|
|
||||||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to delete" heading_value=modal_heading_value modal_description="This will remove the domain request from the .gov registrar. This action cannot be undone." modal_button=modal_button|safe %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div
|
<div
|
||||||
class="usa-sr-only usa-table__announcement-region"
|
class="usa-sr-only usa-table__announcement-region"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
></div>
|
></div>
|
||||||
|
<nav aria-label="Pagination" class="usa-pagination" id="domain-requests-pagination">
|
||||||
|
<ul class="usa-pagination__list">
|
||||||
|
<!-- Pagination links will be dynamically populated by JS -->
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>You haven't requested any domains.</p>
|
<p>You haven't requested any domains.</p>
|
||||||
<!-- <p><a href="{% url 'domain-request:' %}" class="usa-button">Start a new domain request</a></p> -->
|
<!-- <p><a href="{% url 'domain-request:' %}" class="usa-button">Start a new domain request</a></p> -->
|
||||||
|
|
37
src/registrar/views/domain_requests_json.py
Normal file
37
src/registrar/views/domain_requests_json.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
from registrar.models import DomainRequest
|
||||||
|
|
||||||
|
def get_domain_requests_json(request):
|
||||||
|
"""Given the current request,
|
||||||
|
get all domain requests that are associated with the request user and exclude the APPROVED ones"""
|
||||||
|
|
||||||
|
if not request.user.is_authenticated:
|
||||||
|
return JsonResponse({'error': 'User not authenticated'}, status=401)
|
||||||
|
|
||||||
|
domain_requests = DomainRequest.objects.filter(creator=request.user).exclude(
|
||||||
|
status=DomainRequest.DomainRequestStatus.APPROVED
|
||||||
|
)
|
||||||
|
page_number = request.GET.get('page', 1)
|
||||||
|
paginator = Paginator(domain_requests, 2) # Adjust the number of items per page as needed
|
||||||
|
page_obj = paginator.get_page(page_number)
|
||||||
|
|
||||||
|
domain_requests_data = [
|
||||||
|
{
|
||||||
|
'requested_domain': domain_request.requested_domain.name if domain_request.requested_domain else None,
|
||||||
|
'submission_date': domain_request.submission_date,
|
||||||
|
'status': domain_request.get_status_display(),
|
||||||
|
'created_at': domain_request.created_at,
|
||||||
|
'id': domain_request.id,
|
||||||
|
'is_deletable': domain_request.status in [DomainRequest.DomainRequestStatus.STARTED, DomainRequest.DomainRequestStatus.WITHDRAWN],
|
||||||
|
}
|
||||||
|
for domain_request in page_obj
|
||||||
|
]
|
||||||
|
|
||||||
|
return JsonResponse({
|
||||||
|
'domain_requests': domain_requests_data,
|
||||||
|
'has_next': page_obj.has_next(),
|
||||||
|
'has_previous': page_obj.has_previous(),
|
||||||
|
'page': page_obj.number,
|
||||||
|
'num_pages': paginator.num_pages,
|
||||||
|
})
|
|
@ -16,7 +16,7 @@ def get_domains_json(request):
|
||||||
|
|
||||||
# Handle sorting
|
# Handle sorting
|
||||||
sort_by = request.GET.get('sort_by', 'id') # Default to 'id'
|
sort_by = request.GET.get('sort_by', 'id') # Default to 'id'
|
||||||
order = request.GET.get('order', 'asc') # Default to 'asc'
|
order = request.GET.get('order', 'desc') # Default to 'asc'
|
||||||
|
|
||||||
if sort_by == 'state_display':
|
if sort_by == 'state_display':
|
||||||
# Fetch the objects and sort them in Python
|
# Fetch the objects and sort them in Python
|
||||||
|
@ -27,7 +27,7 @@ def get_domains_json(request):
|
||||||
sort_by = f'-{sort_by}'
|
sort_by = f'-{sort_by}'
|
||||||
objects = objects.order_by(sort_by)
|
objects = objects.order_by(sort_by)
|
||||||
|
|
||||||
paginator = Paginator(objects, 2)
|
paginator = Paginator(objects, 1)
|
||||||
page_number = request.GET.get('page')
|
page_number = request.GET.get('page')
|
||||||
page_obj = paginator.get_page(page_number)
|
page_obj = paginator.get_page(page_number)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue