When daterange is 1 day, show hourly data in chart

Show hourly chart starting from ranges of 3 days and less

Use timedelta instead of checking days difference which did not work correctly

Fix hourly chart bug

Add click handler for going from daily to hourly chart view by clicking chart at specific date
This commit is contained in:
CasperVerswijvelt 2021-04-25 22:54:06 +02:00 committed by R. Miles McCain
parent c12a7e9e71
commit b44642e023
4 changed files with 51 additions and 15 deletions

View File

@ -8,7 +8,7 @@ from django.conf import settings
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.db.models.functions import TruncDate from django.db.models.functions import TruncDate, TruncHour
from django.db.utils import NotSupportedError from django.db.utils import NotSupportedError
from django.shortcuts import reverse from django.shortcuts import reverse
from django.utils import timezone from django.utils import timezone
@ -125,8 +125,10 @@ class Service(models.Model):
Session = apps.get_model("analytics", "Session") Session = apps.get_model("analytics", "Session")
Hit = apps.get_model("analytics", "Hit") Hit = apps.get_model("analytics", "Hit")
tz_now = timezone.now()
currently_online = Session.objects.filter( currently_online = Session.objects.filter(
service=self, last_seen__gt=timezone.now() - ACTIVE_USER_TIMEDELTA service=self, last_seen__gt=tz_now - ACTIVE_USER_TIMEDELTA
).count() ).count()
sessions = Session.objects.filter( sessions = Session.objects.filter(
@ -210,6 +212,24 @@ class Service(models.Model):
if session_count == 0: if session_count == 0:
avg_session_duration = None avg_session_duration = None
# Show hourly chart for date ranges of 3 days or less, otherwise daily chart
if (end_time - start_time).days < 3:
session_chart_tooltip_format = "MM/dd HH:mm"
session_chart_granularity = "hourly"
session_chart_data = {
k["hour"]: k["count"]
for k in sessions.annotate(hour=TruncHour("start_time"))
.values("hour")
.annotate(count=models.Count("uuid"))
.order_by("hour")
}
for hour_offset in range(int((end_time - start_time).total_seconds() / 3600) + 1):
hour = (start_time + timezone.timedelta(hours=hour_offset))
if hour not in session_chart_data:
session_chart_data[hour] = 0 if hour <= tz_now else None
else:
session_chart_tooltip_format = "MMM d"
session_chart_granularity = "daily"
session_chart_data = { session_chart_data = {
k["date"]: k["count"] k["date"]: k["count"]
for k in sessions.annotate(date=TruncDate("start_time")) for k in sessions.annotate(date=TruncDate("start_time"))
@ -220,7 +240,7 @@ class Service(models.Model):
for day_offset in range((end_time - start_time).days + 1): for day_offset in range((end_time - start_time).days + 1):
day = (start_time + timezone.timedelta(days=day_offset)).date() day = (start_time + timezone.timedelta(days=day_offset)).date()
if day not in session_chart_data: if day not in session_chart_data:
session_chart_data[day] = 0 session_chart_data[day] = 0 if day <= tz_now.date() else None
return { return {
"currently_online": currently_online, "currently_online": currently_online,
@ -249,6 +269,8 @@ class Service(models.Model):
) )
] ]
), ),
"session_chart_tooltip_format": session_chart_tooltip_format,
"session_chart_granularity": session_chart_granularity,
"online": True, "online": True,
} }

View File

@ -51,7 +51,7 @@
</div> </div>
<hr class="sep h-4"> <hr class="sep h-4">
<div style="bottom: -1px;"> <div style="bottom: -1px;">
{% include 'dashboard/includes/time_chart.html' with data=stats.session_chart_data sparkline=True height=100 name=object.uuid %} {% include 'dashboard/includes/time_chart.html' with data=stats.session_chart_data sparkline=True height=100 name=object.uuid tooltip_format=stats.session_chart_tooltip_format granularity=stats.session_chart_granularity %}
</div> </div>
{% endwith %} {% endwith %}
</a> </a>

View File

@ -6,6 +6,9 @@
}, },
tooltip: { tooltip: {
shared: false, shared: false,
x: {
format: '{{tooltip_format|default:"MMM d"}}',
},
}, },
colors: ["#805AD5"], colors: ["#805AD5"],
chart: { chart: {
@ -34,6 +37,14 @@
stops: [0, 75, 100] stops: [0, 75, 100]
}, },
}, },
{% if granularity == "daily" and click_zoom %}
events: {
markerClick: function(event, chartContext, { seriesIndex, dataPointIndex, w: {config}}) {
const day = config.series[seriesIndex].data[dataPointIndex].x
window.location.href = `?startDate=${day}&endDate=${day}`
},
},
{% endif %}
}, },
grid: { grid: {
padding: { padding: {
@ -63,6 +74,9 @@
}, },
xaxis: { xaxis: {
type: "datetime", type: "datetime",
labels: {
datetimeUTC: false
},
}, },
stroke: { stroke: {
width: 1.5, width: 1.5,

View File

@ -94,7 +94,7 @@
{% endwith %} {% endwith %}
</div> </div>
<div class="card overflow-visible ~neutral !low py-0 mb-6"> <div class="card overflow-visible ~neutral !low py-0 mb-6">
{% include 'dashboard/includes/time_chart.html' with data=stats.session_chart_data %} {% include 'dashboard/includes/time_chart.html' with data=stats.session_chart_data tooltip_format=stats.session_chart_tooltip_format granularity=stats.session_chart_granularity click_zoom=True %}
</div> </div>
{% endif %} {% endif %}
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">