imrpove statistics rendering + filters
This commit is contained in:
parent
0ee72f30c5
commit
8a6f72ca83
|
@ -33,6 +33,9 @@ class LogQuerySet(models.QuerySet):
|
|||
def after(self, date):
|
||||
return self.filter(date__gte=date) if isinstance(date, tz.datetime) else self.filter(date__date__gte=date)
|
||||
|
||||
def before(self, date):
|
||||
return self.filter(date__lte=date) if isinstance(date, tz.datetime) else self.filter(date__date__lte=date)
|
||||
|
||||
def on_air(self):
|
||||
return self.filter(type=Log.TYPE_ON_AIR)
|
||||
|
||||
|
|
|
@ -6,15 +6,20 @@
|
|||
{% block content-container %}
|
||||
<div class="container">
|
||||
|
||||
{# TODO: date subtitle #}
|
||||
{% comment %}
|
||||
<nav class="navbar" role="menu">
|
||||
{% with "admin:tools-stats" as url_name %}
|
||||
{% include "aircox/widgets/dates_menu.html" %}
|
||||
{% endwith %}
|
||||
</nav>
|
||||
{% endcomment %}
|
||||
|
||||
<form method="GET" class="box mt-3 mb-3">
|
||||
<h3 class="title is-3">{% translate "Filter by date" %}</h3>
|
||||
<div class="flex-row gap-3" style="align-items: flex-end">
|
||||
<div class="field mb-0">
|
||||
<label class="label">{% translate "from" %}</label>
|
||||
<input type="date" class="input" name="min_date" value="{{ min_date|date:"Y-m-d" }}"/>
|
||||
</div>
|
||||
<div class="field mb-0">
|
||||
<label class="label">{% translate "... to" %}</label>
|
||||
<input type="date" class="input" name="max_date" value="{{ max_date|date:"Y-m-d" }}"/>
|
||||
</div>
|
||||
<button class="button">{% translate "Apply" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
<a-statistics class="column">
|
||||
<template v-slot="{counts}">
|
||||
<table class="table is-hoverable is-fullwidth">
|
||||
|
@ -26,49 +31,58 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for object in object_list %}
|
||||
{% with object|is_diffusion as is_diff %}
|
||||
{% if is_diff %}
|
||||
<tr class="bg-main">
|
||||
<td>{{ object.start|time:"H:i" }} - {{ object.end|time:"H:i" }}</td>
|
||||
<td colspan="2">
|
||||
<a href="{% url "episode-detail" slug=object.episode.slug %}" target="new">{{ object.episode|default:"" }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% with object|get_tracks as tracks %}
|
||||
{% for track in tracks %}
|
||||
<tr {% if is_diff %}class="bg-main-light"{% endif %}>
|
||||
{% if forloop.first %}
|
||||
<td rowspan="{{ tracks|length }}">{{ object.start|time:"H:i" }} {% if object|is_diffusion %} - {{ object.end|time:"H:i" }}{% endif %}</td>
|
||||
{% endif %}
|
||||
|
||||
<td>
|
||||
{% if object.source %}{{ object.source }} / {% endif %}
|
||||
{% include "aircox/widgets/track_item.html" with object=track %}
|
||||
</td>
|
||||
{% with track.tags.all|join:', ' as tags %}
|
||||
<td>
|
||||
{% if tags and tags.strip %}
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" checked value="{{ tags|escape }}" name="data">
|
||||
{{ tags }}
|
||||
</label>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endwith %}
|
||||
{% regroup object_list by date.date as by_date %}
|
||||
{% for date, objects in by_date %}
|
||||
<tr>
|
||||
<th colspan="3">
|
||||
{{ date|date:"l - d F Y" }}
|
||||
</th>
|
||||
</tr>
|
||||
{% empty %}
|
||||
{% for object in objects %}
|
||||
{% with object|is_diffusion as is_diff %}
|
||||
{% if is_diff %}
|
||||
<tr class="bg-main-light">
|
||||
<td colspan="3">{% translate "No tracks" %}</td>
|
||||
<tr class="bg-main">
|
||||
<td>{{ object.start|time:"H:i" }} - {{ object.end|time:"H:i" }}</td>
|
||||
<td colspan="2">
|
||||
<a href="{% url "episode-detail" slug=object.episode.slug %}" target="new">{{ object.episode|default:"" }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
|
||||
{% endwith %}
|
||||
{% with object|get_tracks as tracks %}
|
||||
{% for track in tracks %}
|
||||
<tr {% if is_diff %}class="bg-main-light"{% endif %}>
|
||||
{% if forloop.first %}
|
||||
<td rowspan="{{ tracks|length }}">{{ object.start|time:"H:i" }} {% if object|is_diffusion %} - {{ object.end|time:"H:i" }}{% endif %}</td>
|
||||
{% endif %}
|
||||
|
||||
<td>
|
||||
{% if object.source %}{{ object.source }} / {% endif %}
|
||||
{% include "aircox/widgets/track_item.html" with object=track %}
|
||||
</td>
|
||||
{% with track.tags.all|join:', ' as tags %}
|
||||
<td>
|
||||
{% if tags and tags.strip %}
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" checked value="{{ tags|escape }}" name="data">
|
||||
{{ tags }}
|
||||
</label>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endwith %}
|
||||
</tr>
|
||||
{% empty %}
|
||||
{% if is_diff %}
|
||||
<tr class="bg-main-light">
|
||||
<td colspan="3">{% translate "No tracks" %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
|
|
|
@ -42,7 +42,7 @@ class DashboardView(DashboardBaseView, TemplateView):
|
|||
class StatisticsView(DashboardBaseView, LogListView):
|
||||
template_name = "aircox/dashboard/statistics.html"
|
||||
date = None
|
||||
redirect_date_url = "dashboard-statistics"
|
||||
# redirect_date_url = "dashboard-statistics"
|
||||
|
||||
# TOOD: test_func & perms check
|
||||
|
||||
|
|
|
@ -17,35 +17,32 @@ __all__ = ("LogListMixin", "LogListView", "LogListAPIView")
|
|||
class LogListMixin(GetDateMixin):
|
||||
model = Log
|
||||
min_date = None
|
||||
max_date = None
|
||||
|
||||
def get_date(self):
|
||||
date = super().get_date()
|
||||
def get_date(self, param):
|
||||
date = super().get_date(param)
|
||||
if date is not None and not self.request.user.is_staff:
|
||||
return min(date, datetime.date.today())
|
||||
return date
|
||||
|
||||
def filter_qs(self, query):
|
||||
if self.min_date:
|
||||
query = query.after(self.min_date)
|
||||
if self.max_date:
|
||||
query = query.before(self.max_date)
|
||||
if not self.min_date and not self.max_date and self.date:
|
||||
return query.date(self.date)
|
||||
return query
|
||||
|
||||
def get_queryset(self):
|
||||
# only get logs for tracks: log for diffusion will be retrieved
|
||||
# by the diffusions' queryset.
|
||||
qs = super().get_queryset().on_air().filter(track__isnull=False).filter(date__lte=tz.now())
|
||||
return (
|
||||
qs.date(self.date)
|
||||
if self.date is not None
|
||||
else qs.after(self.min_date)
|
||||
if self.min_date is not None
|
||||
else qs
|
||||
)
|
||||
query = super().get_queryset().on_air().filter(track__isnull=False).filter(date__lte=tz.now())
|
||||
return self.filter_qs(query)
|
||||
|
||||
def get_diffusions_queryset(self):
|
||||
qs = Diffusion.objects.station(self.station).on_air().filter(start__lte=tz.now()).before()
|
||||
|
||||
return (
|
||||
qs.date(self.date)
|
||||
if self.date is not None
|
||||
else qs.after(self.min_date)
|
||||
if self.min_date is not None
|
||||
else qs
|
||||
)
|
||||
query = Diffusion.objects.station(self.station).on_air().filter(start__lte=tz.now()).before()
|
||||
return self.filter_qs(query)
|
||||
|
||||
def get_object_list(self, logs, full=False):
|
||||
"""Return diffusions merged to the provided logs iterable.
|
||||
|
@ -55,7 +52,6 @@ class LogListMixin(GetDateMixin):
|
|||
diffs = self.get_diffusions_queryset()
|
||||
if self.request.user.is_staff and full:
|
||||
return sorted(list(logs) + list(diffs), key=lambda obj: obj.start)
|
||||
print(">>>>", len(logs), len(diffs), Log.merge_diffusions(logs, diffs))
|
||||
return Log.merge_diffusions(logs, diffs)
|
||||
|
||||
|
||||
|
@ -64,11 +60,31 @@ class LogListView(AttachedToMixin, BaseView, LogListMixin, ListView):
|
|||
`request.GET`, defaults to today)."""
|
||||
|
||||
redirect_date_url = "log-list"
|
||||
date_delta = tz.timedelta(days=7)
|
||||
|
||||
def get_date(self):
|
||||
date = super().get_date()
|
||||
def get_date(self, param):
|
||||
date = super().get_date(param)
|
||||
return datetime.date.today() if date is None else date
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
min_date = self.get_date("min_date")
|
||||
max_date = self.get_date("max_date")
|
||||
|
||||
# ensure right values for min and max
|
||||
min_date, max_date = min(min_date, max_date), max(min_date, max_date)
|
||||
|
||||
# limit logs list size using date delta
|
||||
if min_date and max_date:
|
||||
max_date = min(min_date + self.date_delta, max_date)
|
||||
elif min_date:
|
||||
max_date = min_date + self.date_delta
|
||||
elif max_date:
|
||||
min_date = max_date - self.date_delta
|
||||
|
||||
self.min_date = min_date
|
||||
self.max_date = max_date
|
||||
return super().get(request, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
today = datetime.date.today()
|
||||
# `super()...` must be called before updating kwargs, in order
|
||||
|
@ -76,6 +92,9 @@ class LogListView(AttachedToMixin, BaseView, LogListMixin, ListView):
|
|||
kwargs = super().get_context_data(**kwargs)
|
||||
kwargs.update(
|
||||
{
|
||||
"min_date": self.min_date or today,
|
||||
"max_date": self.max_date or today,
|
||||
"today": datetime.date.today(),
|
||||
"date": self.date,
|
||||
"dates": (today - datetime.timedelta(days=i) for i in range(0, 7)),
|
||||
"object_list": self.get_object_list(self.object_list),
|
||||
|
@ -101,8 +120,8 @@ class LogListAPIView(LogListMixin, BaseAPIView, ListAPIView):
|
|||
def list(self, *args, **kwargs):
|
||||
return super().list(*args, **kwargs)
|
||||
|
||||
def get_date(self):
|
||||
date = super().get_date()
|
||||
def get_date(self, param):
|
||||
date = super().get_date(param)
|
||||
if date is None:
|
||||
self.min_date = tz.now() - tz.timedelta(minutes=30)
|
||||
return date
|
||||
|
|
|
@ -12,9 +12,9 @@ class GetDateMixin:
|
|||
date = None
|
||||
redirect_date_url = None
|
||||
|
||||
def get_date(self):
|
||||
date = self.request.GET.get("date")
|
||||
return str_to_date(date, "-") if date is not None else self.kwargs["date"] if "date" in self.kwargs else None
|
||||
def get_date(self, param):
|
||||
date = self.request.GET.get(param)
|
||||
return str_to_date(date, "-") if date else self.kwargs[param] if param in self.kwargs else None
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
if self.redirect_date_url and self.request.GET.get("date"):
|
||||
|
@ -23,7 +23,7 @@ class GetDateMixin:
|
|||
date=self.request.GET["date"].replace("-", "/"),
|
||||
)
|
||||
|
||||
self.date = self.get_date()
|
||||
self.date = self.get_date("date")
|
||||
return super().get(*args, **kwargs)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user