mirror of https://github.com/snachodog/mybuddy.git
Add a diaper lifetimes box plot graph.
This commit is contained in:
parent
5a2983d30e
commit
b4ac40d2d4
|
@ -17,6 +17,7 @@
|
||||||
aria-expanded="false"><i class="icon icon-graph" aria-hidden="true"></i> Reports</button>
|
aria-expanded="false"><i class="icon icon-graph" aria-hidden="true"></i> Reports</button>
|
||||||
<div class="dropdown-menu" aria-labelledby="reports-dropdown">
|
<div class="dropdown-menu" aria-labelledby="reports-dropdown">
|
||||||
<a class="dropdown-item" href="{% url 'reports:report-diaperchange-types-child' object.slug %}">Diaper Change Types</a>
|
<a class="dropdown-item" href="{% url 'reports:report-diaperchange-types-child' object.slug %}">Diaper Change Types</a>
|
||||||
|
<a class="dropdown-item" href="{% url 'reports:report-diaperchange-lifetimes-child' object.slug %}">Diaper Lifetimes</a>
|
||||||
<a class="dropdown-item" href="{% url 'reports:report-sleep-pattern-child' object.slug %}">Sleep Pattern</a>
|
<a class="dropdown-item" href="{% url 'reports:report-sleep-pattern-child' object.slug %}">Sleep Pattern</a>
|
||||||
<a class="dropdown-item" href="{% url 'reports:report-sleep-totals-child' object.slug %}">Sleep Totals</a>
|
<a class="dropdown-item" href="{% url 'reports:report-sleep-totals-child' object.slug %}">Sleep Totals</a>
|
||||||
<a class="dropdown-item" href="{% url 'reports:report-timeline-child' object.slug %}">Timeline</a>
|
<a class="dropdown-item" href="{% url 'reports:report-timeline-child' object.slug %}">Timeline</a>
|
||||||
|
|
|
@ -17,6 +17,40 @@ from core.utils import duration_string, duration_parts
|
||||||
from .utils import default_graph_layout_options, split_graph_output
|
from .utils import default_graph_layout_options, split_graph_output
|
||||||
|
|
||||||
|
|
||||||
|
def diaperchange_lifetimes(child):
|
||||||
|
"""Create a graph showing how long diapers last (time between changes)."""
|
||||||
|
changes = DiaperChange.objects.filter(child=child).order_by('time')
|
||||||
|
|
||||||
|
durations = []
|
||||||
|
last_change = changes.first()
|
||||||
|
for change in changes[1:]:
|
||||||
|
duration = change.time - last_change.time
|
||||||
|
if duration.seconds > 0:
|
||||||
|
durations.append(duration)
|
||||||
|
last_change = change
|
||||||
|
|
||||||
|
trace = go.Box(
|
||||||
|
y=[round(d.seconds/3600, 2) for d in durations],
|
||||||
|
name='Changes',
|
||||||
|
jitter=0.3,
|
||||||
|
pointpos=-1.8,
|
||||||
|
boxpoints='all'
|
||||||
|
)
|
||||||
|
|
||||||
|
layout_args = default_graph_layout_options()
|
||||||
|
layout_args['title'] = '<b>Diaper Lifetimes</b><br>{}'.format(child)
|
||||||
|
layout_args['yaxis']['title'] = 'Time between changes (hours)'
|
||||||
|
layout_args['yaxis']['zeroline'] = False
|
||||||
|
layout_args['yaxis']['dtick'] = 1
|
||||||
|
|
||||||
|
fig = go.Figure({
|
||||||
|
'data': [trace],
|
||||||
|
'layout': go.Layout(**layout_args)
|
||||||
|
})
|
||||||
|
output = plotly.plot(fig, output_type='div', include_plotlyjs=False)
|
||||||
|
return split_graph_output(output)
|
||||||
|
|
||||||
|
|
||||||
def diaperchange_types(child):
|
def diaperchange_types(child):
|
||||||
"""Create a graph showing types of totals for diaper changes."""
|
"""Create a graph showing types of totals for diaper changes."""
|
||||||
changes = DiaperChange.objects.filter(child=child) \
|
changes = DiaperChange.objects.filter(child=child) \
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends 'reports/report_base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Diaper Lifetimes - {{ object }}{% endblock %}
|
||||||
|
|
||||||
|
{% block javascript %}
|
||||||
|
{{ block.super }}
|
||||||
|
{{ javascript|safe }}
|
||||||
|
{% endblock %}
|
|
@ -6,6 +6,9 @@ from django.conf.urls import url
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
url(r'^reports/changes/lifetimes/(?P<slug>[^/.]+)/$',
|
||||||
|
views.DiaperChangeLifetimesChildReport.as_view(),
|
||||||
|
name='report-diaperchange-lifetimes-child'),
|
||||||
url(r'^reports/changes/types/(?P<slug>[^/.]+)/$',
|
url(r'^reports/changes/types/(?P<slug>[^/.]+)/$',
|
||||||
views.DiaperChangeTypesChildReport.as_view(),
|
views.DiaperChangeTypesChildReport.as_view(),
|
||||||
name='report-diaperchange-types-child'),
|
name='report-diaperchange-types-child'),
|
||||||
|
|
|
@ -5,9 +5,24 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from core.models import Child, DiaperChange
|
from core.models import Child
|
||||||
|
|
||||||
from .graphs import diaperchange_types, sleep_pattern, sleep_totals, timeline
|
from .graphs import (diaperchange_types, diaperchange_lifetimes, sleep_pattern,
|
||||||
|
sleep_totals, timeline)
|
||||||
|
|
||||||
|
|
||||||
|
class DiaperChangeLifetimesChildReport(PermissionRequiredMixin, DetailView):
|
||||||
|
"""Graph of diaper changes by day and type."""
|
||||||
|
model = Child
|
||||||
|
permission_required = ('core.view_child',)
|
||||||
|
template_name = 'reports/diaperchange_lifetimes.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(DiaperChangeLifetimesChildReport, self).get_context_data(
|
||||||
|
**kwargs)
|
||||||
|
child = context['object']
|
||||||
|
context['html'], context['javascript'] = diaperchange_lifetimes(child)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
|
class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
|
||||||
|
|
Loading…
Reference in New Issue