mirror of https://github.com/snachodog/mybuddy.git
Add a sleep totals graph.
This commit is contained in:
parent
e77c2a5639
commit
83aaab5bde
|
@ -23,6 +23,7 @@
|
||||||
{% if perms.core.view_sleep %}
|
{% if perms.core.view_sleep %}
|
||||||
<h6 class="dropdown-header"><i class="fa fa-bed" aria-hidden="true"></i> Sleep</h6>
|
<h6 class="dropdown-header"><i class="fa fa-bed" aria-hidden="true"></i> Sleep</h6>
|
||||||
<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>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -58,19 +58,48 @@ def diaperchange_types(child):
|
||||||
return split_graph_output(output)
|
return split_graph_output(output)
|
||||||
|
|
||||||
|
|
||||||
def sleep_amount(child):
|
def sleep_totals(child):
|
||||||
"""Create a graph showing total time sleeping for each day."""
|
"""Create a graph showing total time sleeping for each day."""
|
||||||
instances = Sleep.objects.filter(child=child).order_by('start')
|
instances = Sleep.objects.filter(child=child).order_by('start')
|
||||||
|
|
||||||
totals = {}
|
totals = {}
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
start_time = timezone.localtime(instance.start)
|
start = timezone.localtime(instance.start)
|
||||||
start_date = start_time.date().isoformat()
|
end = timezone.localtime(instance.end)
|
||||||
|
if start.date() not in totals.keys():
|
||||||
|
totals[start.date()] = timezone.timedelta(seconds=0)
|
||||||
|
if end.date() not in totals.keys():
|
||||||
|
totals[end.date()] = timezone.timedelta(seconds=0)
|
||||||
|
|
||||||
if start_date not in totals.keys():
|
# Account for dates crossing midnight.
|
||||||
totals[start_date] = timezone.timedelta()
|
if start.date() != end.date():
|
||||||
|
totals[start.date()] += end.replace(
|
||||||
|
day=start.day, hour=23, minute=59, second=59) - start
|
||||||
|
totals[end.date()] += end - start.replace(
|
||||||
|
day=end.day, hour=0, minute=0, second=0)
|
||||||
|
else:
|
||||||
|
totals[start.date()] += instance.duration
|
||||||
|
|
||||||
totals[start_date] += instance.duration
|
trace = go.Bar(
|
||||||
|
name='Total sleep',
|
||||||
|
x=list(totals.keys()),
|
||||||
|
y=[td.seconds/3600 for td in totals.values()],
|
||||||
|
hoverinfo='text',
|
||||||
|
text=[duration_string(td) for td in totals.values()]
|
||||||
|
)
|
||||||
|
|
||||||
|
layout_args = default_graph_layout_options()
|
||||||
|
layout_args['barmode'] = 'stack'
|
||||||
|
layout_args['title'] = '<b>Sleep Totals</b><br>{}'.format(child)
|
||||||
|
layout_args['xaxis']['title'] = 'Date'
|
||||||
|
layout_args['yaxis']['title'] = 'Hours of sleep'
|
||||||
|
|
||||||
|
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 sleep_pattern(child):
|
def sleep_pattern(child):
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends 'reports/report_base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Sleep Totals - {{ object }}{% endblock %}
|
||||||
|
|
||||||
|
{% block javascript %}
|
||||||
|
{{ block.super }}
|
||||||
|
{{ javascript|safe }}
|
||||||
|
{% endblock %}
|
|
@ -9,7 +9,11 @@ urlpatterns = [
|
||||||
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'),
|
||||||
|
|
||||||
url(r'^reports/sleep/pattern/(?P<slug>[^/.]+)$',
|
url(r'^reports/sleep/pattern/(?P<slug>[^/.]+)$',
|
||||||
views.SleepPatternChildReport.as_view(),
|
views.SleepPatternChildReport.as_view(),
|
||||||
name='report-sleep-pattern-child'),
|
name='report-sleep-pattern-child'),
|
||||||
|
url(r'^reports/sleep/totals/(?P<slug>[^/.]+)$',
|
||||||
|
views.SleepTotalsChildReport.as_view(),
|
||||||
|
name='report-sleep-totals-child'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.views.generic.detail import DetailView
|
||||||
|
|
||||||
from core.models import Child
|
from core.models import Child
|
||||||
|
|
||||||
from .graphs import diaperchange_types, sleep_pattern
|
from .graphs import diaperchange_types, sleep_pattern, sleep_totals
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
|
class DiaperChangeTypesChildReport(PermissionRequiredMixin, DetailView):
|
||||||
|
@ -38,3 +38,21 @@ class SleepPatternChildReport(PermissionRequiredMixin, DetailView):
|
||||||
child = context['object']
|
child = context['object']
|
||||||
context['html'], context['javascript'] = sleep_pattern(child)
|
context['html'], context['javascript'] = sleep_pattern(child)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class SleepTotalsChildReport(PermissionRequiredMixin, DetailView):
|
||||||
|
"""Graph of total sleep by day."""
|
||||||
|
model = Child
|
||||||
|
permission_required = ('core.view_child',)
|
||||||
|
template_name = 'reports/sleep_totals.html'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(SleepTotalsChildReport, self).__init__()
|
||||||
|
self.html = ''
|
||||||
|
self.javascript = ''
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(SleepTotalsChildReport, self).get_context_data(**kwargs)
|
||||||
|
child = context['object']
|
||||||
|
context['html'], context['javascript'] = sleep_totals(child)
|
||||||
|
return context
|
||||||
|
|
Loading…
Reference in New Issue