mirror of
https://github.com/jlengrand/bugsink.git
synced 2026-03-10 08:01:17 +00:00
Issues list pagination
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load static add_to_qs %}
|
||||
|
||||
{% block title %}Issues · {{ project.name }} · {{ site_title }}{% endblock %}
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for issue in issue_list %}
|
||||
{% for issue in page_obj %}
|
||||
<tr class="bg-slate-50 border-slate-300 border-2 ">
|
||||
<td>
|
||||
<div class="m-1 rounded-full hover:bg-slate-100 cursor-pointer" onclick="toggleContainedCheckbox(this); matchMainCheckboxStateToIssueCheckboxes()">
|
||||
@@ -174,7 +174,42 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end mt-4"> {# the div with a few project-related icons (pjt-members, pjt-settings, my settings, dsn) on the lower RHS #}
|
||||
<div class="flex mt-4"> {# the 'footer' of the page, with the page navigation and the project-related icons #}
|
||||
|
||||
<div class="flex ml-2"> {# pagination #}
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?{% add_to_qs page=1 %}" class="inline-flex" title="First page">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6"><path fill-rule="evenodd" d="M3.22 7.595a.75.75 0 0 0 0 1.06l3.25 3.25a.75.75 0 0 0 1.06-1.06l-2.72-2.72 2.72-2.72a.75.75 0 0 0-1.06-1.06l-3.25 3.25Zm8.25-3.25-3.25 3.25a.75.75 0 0 0 0 1.06l3.25 3.25a.75.75 0 1 0 1.06-1.06l-2.72-2.72 2.72-2.72a.75.75 0 0 0-1.06-1.06Z" clip-rule="evenodd" /></svg></a>
|
||||
|
||||
<a href="?{% add_to_qs page=page_obj.previous_page_number %}" class="inline-flex" title="Previous page">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6"><path fill-rule="evenodd" d="M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /></svg>
|
||||
</a>
|
||||
{% else %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6 text-slate-200"><path fill-rule="evenodd" d="M3.22 7.595a.75.75 0 0 0 0 1.06l3.25 3.25a.75.75 0 0 0 1.06-1.06l-2.72-2.72 2.72-2.72a.75.75 0 0 0-1.06-1.06l-3.25 3.25Zm8.25-3.25-3.25 3.25a.75.75 0 0 0 0 1.06l3.25 3.25a.75.75 0 1 0 1.06-1.06l-2.72-2.72 2.72-2.72a.75.75 0 0 0-1.06-1.06Z" clip-rule="evenodd" /></svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6 text-slate-200"><path fill-rule="evenodd" d="M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /></svg>
|
||||
{% endif %}
|
||||
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
Issues {{ page_obj.start_index }}–{{ page_obj.end_index }} of {{ page_obj.paginator.count }}
|
||||
{% elif page_obj.paginator.count > 0 %}
|
||||
{{ page_obj.paginator.count }} Issues
|
||||
{% endif %}
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?{% add_to_qs page=page_obj.next_page_number %}" class="inline-flex" title="Next page">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6"><path fill-rule="evenodd" d="M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /></svg>
|
||||
</a>
|
||||
<a href="?{% add_to_qs page=page_obj.paginator.num_pages %}" class="inline-flex" title="Last page">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6"><path fill-rule="evenodd" d="M12.78 7.595a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06l2.72-2.72-2.72-2.72a.75.75 0 0 1 1.06-1.06l3.25 3.25Zm-8.25-3.25 3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06l2.72-2.72-2.72-2.72a.75.75 0 0 1 1.06-1.06Z" clip-rule="evenodd" /></svg>
|
||||
</a>
|
||||
{% else %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6 text-slate-200"><path fill-rule="evenodd" d="M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-6 h-6 text-slate-200"><path fill-rule="evenodd" d="M12.78 7.595a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06l2.72-2.72-2.72-2.72a.75.75 0 0 1 1.06-1.06l3.25 3.25Zm-8.25-3.25 3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06l2.72-2.72-2.72-2.72a.75.75 0 0 1 1.06-1.06Z" clip-rule="evenodd" /></svg>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="flex ml-auto justify-end">{# the div with a few project-related icons (pjt-members, pjt-settings, my settings, dsn) on the lower RHS #}
|
||||
|
||||
{% if not app_settings.SINGLE_USER %}{% if member.is_admin or request.user.is_superuser %}
|
||||
<div class="rounded-full hover:bg-slate-100 p-2 cursor-pointer text-slate-700" onclick="followContainedLink(this);" title="Project members">
|
||||
@@ -225,11 +260,12 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div> {# end of the div with a few project-related icons (pjt-members, pjt-settings, my settings, dsn) on the lower RHS #}
|
||||
</div> {# 'footer' (containing the icons as well as the pagination) #}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
|
||||
@@ -236,6 +236,10 @@ def _issue_list_pt_2(request, project, state_filter, unapplied_issue_ids):
|
||||
issue_list = issue_list.filter(
|
||||
Q(calculated_type__icontains=request.GET["q"]) | Q(calculated_value__icontains=request.GET["q"]))
|
||||
|
||||
paginator = Paginator(issue_list, 250)
|
||||
page_number = request.GET.get("page")
|
||||
page_obj = paginator.get_page(page_number)
|
||||
|
||||
return render(request, "issues/issue_list.html", {
|
||||
"project": project,
|
||||
"member": ProjectMembership.objects.get(project=project, user=request.user),
|
||||
@@ -251,6 +255,7 @@ def _issue_list_pt_2(request, project, state_filter, unapplied_issue_ids):
|
||||
"disable_mute_buttons": state_filter in ("resolved", "muted"),
|
||||
"disable_unmute_buttons": state_filter in ("resolved", "open"),
|
||||
"q": request.GET.get("q", ""),
|
||||
"page_obj": page_obj,
|
||||
})
|
||||
|
||||
|
||||
|
||||
2
theme/static/css/dist/styles.css
vendored
2
theme/static/css/dist/styles.css
vendored
File diff suppressed because one or more lines are too long
17
theme/templatetags/add_to_qs.py
Normal file
17
theme/templatetags/add_to_qs.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from copy import copy
|
||||
from django import template
|
||||
from django.utils.http import urlencode
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def add_to_qs(context, **kwargs):
|
||||
if 'request' not in context:
|
||||
# "should not happen", because this tag is only assumed to be used in RequestContext templates, but it's not
|
||||
# something I want to break for. Also: we have an answer that "mostly works" for that case, so let's do that.
|
||||
return urlencode(kwargs)
|
||||
|
||||
query = copy(context['request'].GET.dict())
|
||||
query.update(kwargs)
|
||||
return urlencode(query)
|
||||
Reference in New Issue
Block a user