mirror of
https://github.com/bugsink/bugsink.git
synced 2026-05-06 23:10:00 -05:00
Event-list: pagination
This commit is contained in:
@@ -108,7 +108,7 @@
|
||||
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "stacktrace" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">Stacktrace</div></a>
|
||||
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/details/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "event-details" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">Event Details</div></a>
|
||||
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/breadcrumbs/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "breadcrumbs" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">Breadcrumbs</div></a>
|
||||
{# <a href="/issues/issue/{{ issue.id }}/events/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "event-list" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">Event List</div></a>#}
|
||||
<a href="/issues/issue/{{ issue.id }}/events/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "event-list" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">Event List</div></a>
|
||||
<a href="/issues/issue/{{ issue.id }}/grouping/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "grouping" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">Grouping</div></a>
|
||||
<a href="/issues/issue/{{ issue.id }}/history/"><div class="p-4 font-bold hover:bg-slate-200 {% if tab == "history" %}text-cyan-500 border-cyan-500 border-b-4{% else %}text-slate-500 border-slate-400 hover:border-b-4{% endif %}">History</div></a>
|
||||
</div>
|
||||
@@ -134,7 +134,6 @@
|
||||
<a href="/admin/issues/issue/{{ issue.id }}/change/">Issue Admin</a>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>{# bottom nav bar #}
|
||||
</div>{# the whole of the big tabbed view #}
|
||||
|
||||
@@ -1,7 +1,171 @@
|
||||
{% extends "issues/base.html" %}
|
||||
{% load issues %}
|
||||
|
||||
{% block tab_content %}
|
||||
{% for event in event_list %}
|
||||
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/">{{ event.id }}</a><br>
|
||||
{% comment %}
|
||||
|
||||
<div class="...">
|
||||
<span class="...">
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page=1">« first</a>
|
||||
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
|
||||
{% endif %}
|
||||
|
||||
<span>
|
||||
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}">next</a>
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endcomment %}
|
||||
|
||||
<div class="flex">
|
||||
<div class="overflow-hidden">
|
||||
<div class="italic">
|
||||
Showing {{ page_obj.start_index }} - {{ page_obj.end_index }} of {{ page_obj.paginator.count }}
|
||||
{% if project.digested_event_count != project.event_count %}
|
||||
available events ({{ project.digested_event_count }} total observed).
|
||||
{% else %}
|
||||
total events.
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto flex-none">
|
||||
{# UI / UX question: is it a good idea to reuse-with-different-meaning (pages, not events) for this? #}
|
||||
{# adapted copy/pasta from _event_nav #}
|
||||
<div class="flex place-content-end">
|
||||
{% if page_obj.has_previous %} {# no need for 'is_first': if you can go to the left, you can go all the way to the left too #}
|
||||
<a href="?page=1" class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring inline-flex items-center justify-center">
|
||||
<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>
|
||||
{% else %}
|
||||
<div class="font-bold text-slate-300 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md inline-flex items-center justify-center">
|
||||
<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" />
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page={{ page_obj.previous_page_number }}" class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring inline-flex items-center justify-center">
|
||||
<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 %}
|
||||
<div class="font-bold text-slate-300 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md inline-flex items-center justify-center">
|
||||
<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>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}" class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring inline-flex items-center justify-center">
|
||||
<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>
|
||||
{% else %}
|
||||
<div class="font-bold text-slate-300 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md inline-flex items-center justify-center">
|
||||
<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>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}" class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring inline-flex items-center justify-center">
|
||||
<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 %}
|
||||
<div class="font-bold text-slate-300 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md inline-flex items-center justify-center">
|
||||
<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>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-4">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
|
||||
<td class="p-4 align-top text-slate-800 font-bold">
|
||||
#
|
||||
</td>
|
||||
|
||||
<td class="p-4 align-top text-slate-800 font-bold">
|
||||
ID
|
||||
</td>
|
||||
|
||||
<td class="p-4 align-top text-slate-800 font-bold">
|
||||
Timestamp
|
||||
</td>
|
||||
|
||||
<td class="p-4 w-full align-top text-slate-800 font-bold">
|
||||
Title
|
||||
</td>
|
||||
|
||||
<td class="p-4 align-top text-slate-800 font-bold">
|
||||
Release
|
||||
</td>
|
||||
|
||||
<td class="p-4 align-top text-slate-800 font-bold">
|
||||
Environment
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% comment %}
|
||||
TODO
|
||||
release
|
||||
environment
|
||||
|
||||
{% endcomment %}
|
||||
|
||||
{% for event in page_obj %}
|
||||
<tr class="border-slate-200 border-2 ">
|
||||
|
||||
<td class="p-4 font-bold text-slate-500 align-top">
|
||||
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/">{{ event.digest_order }}</a>
|
||||
</td>
|
||||
|
||||
<td class="p-4 font-bold text-slate-500 align-top"> {# how useful is this really? #}
|
||||
<a href="/issues/issue/{{ issue.id }}/event/{{ event.id }}/">{{ event.id|truncatechars:9 }}</a>
|
||||
</td>
|
||||
|
||||
<td class="p-4 font-mono whitespace-nowrap align-top">
|
||||
{{ event.timestamp|date:"j M G:i:s" }}.<span class="text-xs">{{ event.timestamp|date:"u"|slice:":3" }}</span>
|
||||
</td>
|
||||
|
||||
{% comment %}
|
||||
In the current setup, event title wraps to the next line if needed, there's no clipping.
|
||||
I tried to get 'just use dots' to work for that, but I did not get that to work in a table. Perhaps it's actually
|
||||
anti-thetical to the table layout. Perhaps if we used a flexbox layout, it would work better.
|
||||
Anyway, overflow-to-next-line is also fine (at least for now)
|
||||
{% endcomment %}
|
||||
|
||||
<td class="w-full p-4 font-mono align-top">
|
||||
{{ event.title }}
|
||||
</td>
|
||||
|
||||
<td class="p-4 font-mono align-top">
|
||||
<span {% if event.release|issha %}class="font-mono"{% endif %}>{{ event.release|shortsha }}</span>
|
||||
</td>
|
||||
|
||||
<td class="p-4 font-mono align-top">
|
||||
{{ event.environment|truncatechars:30 }}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{# note: no "empty" case; event-less issues are not something I expect to really support (for some definition of "really") #}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -10,6 +10,7 @@ from django.template.defaultfilters import date
|
||||
from django.urls import reverse
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404
|
||||
from django.core.paginator import Paginator
|
||||
|
||||
from bugsink.decorators import project_membership_required, issue_membership_required, atomic_for_request_method
|
||||
from bugsink.transaction import durable_atomic
|
||||
@@ -479,6 +480,10 @@ def issue_event_list(request, issue):
|
||||
return _handle_post(request, issue)
|
||||
|
||||
event_list = issue.event_set.all()
|
||||
paginator = Paginator(event_list, 250) # in general "big is good" because it allows a lot "at a glance".
|
||||
|
||||
page_number = request.GET.get("page")
|
||||
page_obj = paginator.get_page(page_number)
|
||||
|
||||
last_event = issue.event_set.order_by("timestamp").last() # the template needs this for the tabs, we pick the last
|
||||
return render(request, "issues/event_list.html", {
|
||||
@@ -490,6 +495,7 @@ def issue_event_list(request, issue):
|
||||
"is_event_page": False,
|
||||
"parsed_data": json.loads(last_event.data),
|
||||
"mute_options": GLOBAL_MUTE_OPTIONS,
|
||||
"page_obj": page_obj,
|
||||
})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user