diff --git a/core/static_src/scss/core.scss b/core/static_src/scss/core.scss
index 1c6a0a6e..d6b2e132 100644
--- a/core/static_src/scss/core.scss
+++ b/core/static_src/scss/core.scss
@@ -3,3 +3,12 @@
max-width: 150px;
}
}
+
+@include media-breakpoint-up(md) {
+ #view-child {
+ .child-detail-column {
+ position: fixed;
+ width: 100%;
+ }
+ }
+}
diff --git a/reports/static_src/scss/timeline.scss b/core/static_src/scss/timeline.scss
similarity index 99%
rename from reports/static_src/scss/timeline.scss
rename to core/static_src/scss/timeline.scss
index feac627e..65ea501b 100644
--- a/reports/static_src/scss/timeline.scss
+++ b/core/static_src/scss/timeline.scss
@@ -118,7 +118,7 @@ $card-shadow: rgba(0, 0, 0, .175);
}
}
-@media (max-width: 767px) {
+@include media-breakpoint-down(md) {
.timeline {
&::before {
left: 40px;
diff --git a/core/templates/core/child_detail.html b/core/templates/core/child_detail.html
index 7cfa5f67..ef9aa657 100644
--- a/core/templates/core/child_detail.html
+++ b/core/templates/core/child_detail.html
@@ -9,13 +9,53 @@
{% endblock %}
{% block content %}
-
-
-
{{ object }}
-
- Born {{ object.birth_date }}
- Age {{ object.birth_date|timesince }}
-
- {% include 'dashboard/child_button_group.html' %}
+
+
+
+
+
{{ object }}
+
+ Born {{ object.birth_date }}
+ Age {{ object.birth_date|timesince }}
+
+ {% include 'dashboard/child_button_group.html' %}
+
+
+
+
+
+
+ {% if date_previous %}
+
+
+ Previous
+
+ {% endif %}
+ {{ date|date }}
+ {% if date_next %}
+
+
+ Next
+
+ {% endif %}
+
+
+ {% for object in timeline_objects %}
+ -
+
+
+
+
+
+ {{ object.event }}
+
+
+
+
+ {% endfor %}
+
+
{% endblock %}
\ No newline at end of file
diff --git a/reports/graphs/timeline.py b/core/timeline.py
similarity index 96%
rename from reports/graphs/timeline.py
rename to core/timeline.py
index ec18c3c0..68dbf543 100644
--- a/reports/graphs/timeline.py
+++ b/core/timeline.py
@@ -6,9 +6,9 @@ from django.utils import timezone
from core.models import DiaperChange, Feeding, Sleep, TummyTime
-def timeline(child, date):
+def get_objects(child, date):
"""
- Create a time-sorted dictionary for all events for a child.
+ Create a time-sorted dictionary of all events for a child.
:param child: an instance of a Child.
:param date: a DateTime instance for the day to be summarized.
:returns: a list of the day's events.
diff --git a/core/views.py b/core/views.py
index 0ae00811..afb7522f 100644
--- a/core/views.py
+++ b/core/views.py
@@ -3,19 +3,18 @@ from __future__ import unicode_literals
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.urls import reverse
+from django.utils import timezone
from django.views.generic.base import RedirectView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django_filters.views import FilterView
-from .models import Child, DiaperChange, Feeding, Note, Sleep, Timer, TummyTime
-from .forms import (ChildForm, ChildDeleteForm, DiaperChangeForm, FeedingForm,
- SleepForm, TimerForm, TummyTimeForm)
+from core import forms, models, timeline
class ChildList(PermissionRequiredMixin, FilterView):
- model = Child
+ model = models.Child
template_name = 'core/child_list.html'
permission_required = ('core.view_child',)
paginate_by = 10
@@ -23,34 +22,46 @@ class ChildList(PermissionRequiredMixin, FilterView):
class ChildAdd(PermissionRequiredMixin, CreateView):
- model = Child
+ model = models.Child
permission_required = ('core.add_child',)
- form_class = ChildForm
+ form_class = forms.ChildForm
success_url = '/children'
class ChildDetail(PermissionRequiredMixin, DetailView):
- model = Child
+ model = models.Child
permission_required = ('core.view_child',)
+ def get_context_data(self, **kwargs):
+ context = super(ChildDetail, self).get_context_data(**kwargs)
+ date = self.request.GET.get('date', str(timezone.localdate()))
+ date = timezone.datetime.strptime(date, '%Y-%m-%d')
+ date = timezone.localtime(timezone.make_aware(date))
+ context['timeline_objects'] = timeline.get_objects(self.object, date)
+ context['date'] = date
+ context['date_previous'] = date - timezone.timedelta(days=1)
+ if date.date() < timezone.localdate():
+ context['date_next'] = date + timezone.timedelta(days=1)
+ return context
+
class ChildUpdate(PermissionRequiredMixin, UpdateView):
- model = Child
+ model = models.Child
permission_required = ('core.change_child',)
- form_class = ChildForm
+ form_class = forms.ChildForm
success_url = '/children'
class ChildDelete(PermissionRequiredMixin, UpdateView):
- model = Child
- form_class = ChildDeleteForm
+ model = models.Child
+ form_class = forms.ChildDeleteForm
template_name = 'core/child_confirm_delete.html'
permission_required = ('core.delete_child',)
success_url = '/children'
class DiaperChangeList(PermissionRequiredMixin, FilterView):
- model = DiaperChange
+ model = models.DiaperChange
template_name = 'core/diaperchange_list.html'
permission_required = ('core.view_diaperchange',)
paginate_by = 10
@@ -58,27 +69,27 @@ class DiaperChangeList(PermissionRequiredMixin, FilterView):
class DiaperChangeAdd(PermissionRequiredMixin, CreateView):
- model = DiaperChange
+ model = models.DiaperChange
permission_required = ('core.add_diaperchange',)
- form_class = DiaperChangeForm
+ form_class = forms.DiaperChangeForm
success_url = '/changes'
class DiaperChangeUpdate(PermissionRequiredMixin, UpdateView):
- model = DiaperChange
+ model = models.DiaperChange
permission_required = ('core.change_diaperchange',)
- form_class = DiaperChangeForm
+ form_class = forms.DiaperChangeForm
success_url = '/changes'
class DiaperChangeDelete(PermissionRequiredMixin, DeleteView):
- model = DiaperChange
+ model = models.DiaperChange
permission_required = ('core.delete_diaperchange',)
success_url = '/changes'
class FeedingList(PermissionRequiredMixin, FilterView):
- model = Feeding
+ model = models.Feeding
template_name = 'core/feeding_list.html'
permission_required = ('core.view_feeding',)
paginate_by = 10
@@ -86,9 +97,9 @@ class FeedingList(PermissionRequiredMixin, FilterView):
class FeedingAdd(PermissionRequiredMixin, CreateView):
- model = Feeding
+ model = models.Feeding
permission_required = ('core.add_feeding',)
- form_class = FeedingForm
+ form_class = forms.FeedingForm
success_url = '/feedings'
def get_form_kwargs(self):
@@ -99,20 +110,20 @@ class FeedingAdd(PermissionRequiredMixin, CreateView):
class FeedingUpdate(PermissionRequiredMixin, UpdateView):
- model = Feeding
+ model = models.Feeding
permission_required = ('core.change_feeding',)
- form_class = FeedingForm
+ form_class = forms.FeedingForm
success_url = '/feedings'
class FeedingDelete(PermissionRequiredMixin, DeleteView):
- model = Feeding
+ model = models.Feeding
permission_required = ('core.delete_feeding',)
success_url = '/feedings'
class NoteList(PermissionRequiredMixin, FilterView):
- model = Note
+ model = models.Note
template_name = 'core/note_list.html'
permission_required = ('core.view_note',)
paginate_by = 10
@@ -120,27 +131,27 @@ class NoteList(PermissionRequiredMixin, FilterView):
class NoteAdd(PermissionRequiredMixin, CreateView):
- model = Note
+ model = models.Note
permission_required = ('core.add_note',)
fields = ['child', 'note']
success_url = '/notes'
class NoteUpdate(PermissionRequiredMixin, UpdateView):
- model = Note
+ model = models.Note
permission_required = ('core.change_note',)
fields = ['child', 'note']
success_url = '/notes'
class NoteDelete(PermissionRequiredMixin, DeleteView):
- model = Note
+ model = models.Note
permission_required = ('core.delete_note',)
success_url = '/notes'
class SleepList(PermissionRequiredMixin, FilterView):
- model = Sleep
+ model = models.Sleep
template_name = 'core/sleep_list.html'
permission_required = ('core.view_sleep',)
paginate_by = 10
@@ -148,9 +159,9 @@ class SleepList(PermissionRequiredMixin, FilterView):
class SleepAdd(PermissionRequiredMixin, CreateView):
- model = Sleep
+ model = models.Sleep
permission_required = ('core.add_sleep',)
- form_class = SleepForm
+ form_class = forms.SleepForm
success_url = '/sleep'
def get_form_kwargs(self):
@@ -161,20 +172,20 @@ class SleepAdd(PermissionRequiredMixin, CreateView):
class SleepUpdate(PermissionRequiredMixin, UpdateView):
- model = Sleep
+ model = models.Sleep
permission_required = ('core.change_sleep',)
- form_class = SleepForm
+ form_class = forms.SleepForm
success_url = '/sleep'
class SleepDelete(PermissionRequiredMixin, DeleteView):
- model = Sleep
+ model = models.Sleep
permission_required = ('core.delete_sleep',)
success_url = '/sleep'
class TimerList(PermissionRequiredMixin, FilterView):
- model = Timer
+ model = models.Timer
template_name = 'core/timer_list.html'
permission_required = ('core.view_timer',)
paginate_by = 10
@@ -182,14 +193,14 @@ class TimerList(PermissionRequiredMixin, FilterView):
class TimerDetail(PermissionRequiredMixin, DetailView):
- model = Timer
+ model = models.Timer
permission_required = ('core.view_timer',)
class TimerAdd(PermissionRequiredMixin, CreateView):
- model = Timer
+ model = models.Timer
permission_required = ('core.add_timer',)
- form_class = TimerForm
+ form_class = forms.TimerForm
success_url = '/timers'
def get_form_kwargs(self):
@@ -199,9 +210,9 @@ class TimerAdd(PermissionRequiredMixin, CreateView):
class TimerUpdate(PermissionRequiredMixin, UpdateView):
- model = Timer
+ model = models.Timer
permission_required = ('core.change_timer',)
- form_class = TimerForm
+ form_class = forms.TimerForm
success_url = '/timers'
def get_form_kwargs(self):
@@ -218,7 +229,7 @@ class TimerAddQuick(PermissionRequiredMixin, RedirectView):
permission_required = ('core.add_timer',)
def get(self, request, *args, **kwargs):
- instance = Timer.objects.create(user=request.user)
+ instance = models.Timer.objects.create(user=request.user)
instance.save()
self.url = request.GET.get(
'next', reverse('timer-detail', args={instance.id}))
@@ -229,7 +240,7 @@ class TimerRestart(PermissionRequiredMixin, RedirectView):
permission_required = ('core.change_timer',)
def get(self, request, *args, **kwargs):
- instance = Timer.objects.get(id=kwargs['pk'])
+ instance = models.Timer.objects.get(id=kwargs['pk'])
instance.restart()
return super(TimerRestart, self).get(request, *args, **kwargs)
@@ -241,7 +252,7 @@ class TimerStop(PermissionRequiredMixin, RedirectView):
permission_required = ('core.change_timer',)
def get(self, request, *args, **kwargs):
- instance = Timer.objects.get(id=kwargs['pk'])
+ instance = models.Timer.objects.get(id=kwargs['pk'])
instance.stop()
return super(TimerStop, self).get(request, *args, **kwargs)
@@ -250,13 +261,13 @@ class TimerStop(PermissionRequiredMixin, RedirectView):
class TimerDelete(PermissionRequiredMixin, DeleteView):
- model = Timer
+ model = models.Timer
permission_required = ('core.delete_timer',)
success_url = '/'
class TummyTimeList(PermissionRequiredMixin, FilterView):
- model = TummyTime
+ model = models.TummyTime
template_name = 'core/tummytime_list.html'
permission_required = ('core.view_tummytime',)
paginate_by = 10
@@ -264,9 +275,9 @@ class TummyTimeList(PermissionRequiredMixin, FilterView):
class TummyTimeAdd(PermissionRequiredMixin, CreateView):
- model = TummyTime
+ model = models.TummyTime
permission_required = ('core.add_tummytime',)
- form_class = TummyTimeForm
+ form_class = forms.TummyTimeForm
success_url = '/tummy-time'
def get_form_kwargs(self):
@@ -277,13 +288,13 @@ class TummyTimeAdd(PermissionRequiredMixin, CreateView):
class TummyTimeUpdate(PermissionRequiredMixin, UpdateView):
- model = TummyTime
+ model = models.TummyTime
permission_required = ('core.change_tummytime',)
- form_class = TummyTimeForm
+ form_class = forms.TummyTimeForm
success_url = '/tummy-time'
class TummyTimeDelete(PermissionRequiredMixin, DeleteView):
- model = TummyTime
+ model = models.TummyTime
permission_required = ('core.delete_tummytime',)
success_url = '/tummy-time'
diff --git a/dashboard/templates/dashboard/child_button_group.html b/dashboard/templates/dashboard/child_button_group.html
index 8bf1815f..2e3ee7f4 100644
--- a/dashboard/templates/dashboard/child_button_group.html
+++ b/dashboard/templates/dashboard/child_button_group.html
@@ -18,7 +18,6 @@
Diaper Lifetimes
Sleep Pattern
Sleep Totals
-
Timeline
diff --git a/reports/graphs/__init__.py b/reports/graphs/__init__.py
index 01191f82..0957cd42 100644
--- a/reports/graphs/__init__.py
+++ b/reports/graphs/__init__.py
@@ -2,4 +2,3 @@ from .diaperchange_lifetimes import diaperchange_lifetimes # NOQA
from .diaperchange_types import diaperchange_types # NOQA
from .sleep_pattern import sleep_pattern # NOQA
from .sleep_totals import sleep_totals # NOQA
-from .timeline import timeline # NOQA
diff --git a/reports/templates/reports/timeline.html b/reports/templates/reports/timeline.html
deleted file mode 100644
index 858be8e9..00000000
--- a/reports/templates/reports/timeline.html
+++ /dev/null
@@ -1,42 +0,0 @@
-{% extends 'reports/report_base.html' %}
-{% load static %}
-
-{% block title %}Timeline - {{ object }}{% endblock %}
-
-{% block breadcrumbs %}
- {{ block.super }}
-