# -*- coding: utf-8 -*- from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.forms import Form from django.http import HttpResponseRedirect from django.urls import reverse, reverse_lazy from django.utils import timezone from django.utils.translation import gettext as _ from django.views.generic.base import RedirectView, TemplateView from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView from babybuddy.mixins import LoginRequiredMixin, PermissionRequiredMixin from babybuddy.views import BabyBuddyFilterView from core import filters, forms, models, timeline def _prepare_timeline_context_data(context, date, child=None): date = timezone.datetime.strptime(date, "%Y-%m-%d") date = timezone.localtime(timezone.make_aware(date)) context["timeline_objects"] = timeline.get_objects(date, child) context["date"] = date context["date_previous"] = date - timezone.timedelta(days=1) if date.date() < timezone.localdate(): context["date_next"] = date + timezone.timedelta(days=1) pass class CoreAddView(PermissionRequiredMixin, SuccessMessageMixin, CreateView): def get_success_message(self, cleaned_data): cleaned_data["model"] = self.model._meta.verbose_name.title() if "child" in cleaned_data: self.success_message = _("%(model)s entry for %(child)s added!") else: self.success_message = _("%(model)s entry added!") return self.success_message % cleaned_data def get_form_kwargs(self): """ Check for and add "child" and "timer" from request query parameters. - "child" may provide a slug for a Child instance. - "timer" may provided an ID for a Timer instance. These arguments are used in some add views to pre-fill initial data in the form fields. :return: Updated keyword arguments. """ kwargs = super(CoreAddView, self).get_form_kwargs() for parameter in ["child", "timer"]: value = self.request.GET.get(parameter, None) if value: kwargs.update({parameter: value}) return kwargs class CoreUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView): def get_success_message(self, cleaned_data): cleaned_data["model"] = self.model._meta.verbose_name.title() if "child" in cleaned_data: self.success_message = _("%(model)s entry for %(child)s updated.") else: self.success_message = _("%(model)s entry updated.") return self.success_message % cleaned_data class CoreDeleteView(PermissionRequiredMixin, SuccessMessageMixin, DeleteView): def get_success_message(self, cleaned_data): return _("%(model)s entry deleted.") % { "model": self.model._meta.verbose_name.title() } class BMIList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.BMI template_name = "core/bmi_list.html" permission_required = ("core.view_bmi",) paginate_by = 10 filterset_class = filters.BMIFilter class BMIAdd(CoreAddView): model = models.BMI permission_required = ("core.add_bmi",) form_class = forms.BMIForm success_url = reverse_lazy("core:bmi-list") class BMIUpdate(CoreUpdateView): model = models.BMI permission_required = ("core.change_bmi",) form_class = forms.BMIForm success_url = reverse_lazy("core:bmi-list") class BMIDelete(CoreDeleteView): model = models.BMI permission_required = ("core.delete_bmi",) success_url = reverse_lazy("core:bmi-list") class ChildList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Child template_name = "core/child_list.html" permission_required = ("core.view_child",) paginate_by = 10 filterset_fields = ("first_name", "last_name") class ChildAdd(CoreAddView): model = models.Child permission_required = ("core.add_child",) form_class = forms.ChildForm success_url = reverse_lazy("core:child-list") success_message = _("%(first_name)s %(last_name)s added!") class ChildDetail(PermissionRequiredMixin, DetailView): 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())) _prepare_timeline_context_data(context, date, self.object) return context class ChildUpdate(CoreUpdateView): model = models.Child permission_required = ("core.change_child",) form_class = forms.ChildForm success_url = reverse_lazy("core:child-list") class ChildDelete(CoreUpdateView): model = models.Child form_class = forms.ChildDeleteForm template_name = "core/child_confirm_delete.html" permission_required = ("core.delete_child",) success_url = reverse_lazy("core:child-list") def get_success_message(self, cleaned_data): """This class cannot use `CoreDeleteView` because of the confirmation step required so the success message must be overridden.""" success_message = _("%(model)s entry deleted.") % { "model": self.model._meta.verbose_name.title() } return success_message % cleaned_data class DiaperChangeList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.DiaperChange template_name = "core/diaperchange_list.html" permission_required = ("core.view_diaperchange",) paginate_by = 10 filterset_class = filters.DiaperChangeFilter class DiaperChangeAdd(CoreAddView): model = models.DiaperChange permission_required = ("core.add_diaperchange",) form_class = forms.DiaperChangeForm success_url = reverse_lazy("core:diaperchange-list") class DiaperChangeUpdate(CoreUpdateView): model = models.DiaperChange permission_required = ("core.change_diaperchange",) form_class = forms.DiaperChangeForm success_url = reverse_lazy("core:diaperchange-list") class DiaperChangeDelete(CoreDeleteView): model = models.DiaperChange permission_required = ("core.delete_diaperchange",) success_url = reverse_lazy("core:diaperchange-list") class FeedingList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Feeding template_name = "core/feeding_list.html" permission_required = ("core.view_feeding",) paginate_by = 10 filterset_class = filters.FeedingFilter class FeedingAdd(CoreAddView): model = models.Feeding permission_required = ("core.add_feeding",) form_class = forms.FeedingForm success_url = reverse_lazy("core:feeding-list") class FeedingUpdate(CoreUpdateView): model = models.Feeding permission_required = ("core.change_feeding",) form_class = forms.FeedingForm success_url = reverse_lazy("core:feeding-list") class FeedingDelete(CoreDeleteView): model = models.Feeding permission_required = ("core.delete_feeding",) success_url = reverse_lazy("core:feeding-list") class HeadCircumferenceList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.HeadCircumference template_name = "core/head_circumference_list.html" permission_required = ("core.view_head_circumference",) paginate_by = 10 filterset_class = filters.HeadCircumferenceFilter class HeadCircumferenceAdd(CoreAddView): model = models.HeadCircumference template_name = "core/head_circumference_form.html" permission_required = ("core.add_head_circumference",) form_class = forms.HeadCircumferenceForm success_url = reverse_lazy("core:head-circumference-list") class HeadCircumferenceUpdate(CoreUpdateView): model = models.HeadCircumference template_name = "core/head_circumference_form.html" permission_required = ("core.change_head_circumference",) form_class = forms.HeadCircumferenceForm success_url = reverse_lazy("core:head-circumference-list") class HeadCircumferenceDelete(CoreDeleteView): model = models.HeadCircumference template_name = "core/head_circumference_confirm_delete.html" permission_required = ("core.delete_head_circumference",) success_url = reverse_lazy("core:head-circumference-list") class HeightList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Height template_name = "core/height_list.html" permission_required = ("core.view_height",) paginate_by = 10 filterset_class = filters.HeightFilter class HeightAdd(CoreAddView): model = models.Height permission_required = ("core.add_height",) form_class = forms.HeightForm success_url = reverse_lazy("core:height-list") class HeightUpdate(CoreUpdateView): model = models.Height permission_required = ("core.change_height",) form_class = forms.HeightForm success_url = reverse_lazy("core:height-list") class HeightDelete(CoreDeleteView): model = models.Height permission_required = ("core.delete_height",) success_url = reverse_lazy("core:height-list") class NoteList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Note template_name = "core/note_list.html" permission_required = ("core.view_note",) paginate_by = 10 filterset_class = filters.NoteFilter class NoteAdd(CoreAddView): model = models.Note permission_required = ("core.add_note",) form_class = forms.NoteForm success_url = reverse_lazy("core:note-list") class NoteUpdate(CoreUpdateView): model = models.Note permission_required = ("core.change_note",) form_class = forms.NoteForm success_url = reverse_lazy("core:note-list") class NoteDelete(CoreDeleteView): model = models.Note permission_required = ("core.delete_note",) success_url = reverse_lazy("core:note-list") class PumpingList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Pumping template_name = "core/pumping_list.html" permission_required = ("core.view_pumping",) paginate_by = 10 filterset_class = filters.PumpingFilter class PumpingAdd(CoreAddView): model = models.Pumping permission_required = ("core.add_pumping",) form_class = forms.PumpingForm success_url = reverse_lazy("core:pumping-list") success_message = _("%(model)s entry added!") class PumpingUpdate(CoreUpdateView): model = models.Pumping permission_required = ("core.change_pumping",) form_class = forms.PumpingForm success_url = reverse_lazy("core:pumping-list") success_message = _("%(model)s entry for %(child)s updated.") class PumpingDelete(CoreDeleteView): model = models.Pumping permission_required = ("core.delete_pumping",) success_url = reverse_lazy("core:pumping-list") class SleepList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Sleep template_name = "core/sleep_list.html" permission_required = ("core.view_sleep",) paginate_by = 10 filterset_class = filters.SleepFilter class SleepAdd(CoreAddView): model = models.Sleep permission_required = ("core.add_sleep",) form_class = forms.SleepForm success_url = reverse_lazy("core:sleep-list") class SleepUpdate(CoreUpdateView): model = models.Sleep permission_required = ("core.change_sleep",) form_class = forms.SleepForm success_url = reverse_lazy("core:sleep-list") class SleepDelete(CoreDeleteView): model = models.Sleep permission_required = ("core.delete_sleep",) success_url = reverse_lazy("core:sleep-list") class TemperatureList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Temperature template_name = "core/temperature_list.html" permission_required = ("core.view_temperature",) paginate_by = 10 filterset_class = filters.TemperatureFilter class TemperatureAdd(CoreAddView): model = models.Temperature permission_required = ("core.add_temperature",) form_class = forms.TemperatureForm success_url = reverse_lazy("core:temperature-list") success_message = _("%(model)s reading added!") class TemperatureUpdate(CoreUpdateView): model = models.Temperature permission_required = ("core.change_temperature",) form_class = forms.TemperatureForm success_url = reverse_lazy("core:temperature-list") success_message = _("%(model)s reading for %(child)s updated.") class TemperatureDelete(CoreDeleteView): model = models.Temperature permission_required = ("core.delete_temperature",) success_url = reverse_lazy("core:temperature-list") class Timeline(LoginRequiredMixin, TemplateView): template_name = "timeline/timeline.html" # Show the overall timeline or a child timeline if one Child instance. def get(self, request, *args, **kwargs): children = models.Child.objects.count() if children == 1: return HttpResponseRedirect( reverse("core:child", args={models.Child.objects.first().slug}) ) return super(Timeline, self).get(request, *args, **kwargs) def get_context_data(self, **kwargs): context = super(Timeline, self).get_context_data(**kwargs) date = self.request.GET.get("date", str(timezone.localdate())) _prepare_timeline_context_data(context, date) return context class TimerList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Timer template_name = "core/timer_list.html" permission_required = ("core.view_timer",) paginate_by = 10 filterset_fields = ("active", "user") class TimerDetail(PermissionRequiredMixin, DetailView): model = models.Timer permission_required = ("core.view_timer",) class TimerAdd(PermissionRequiredMixin, CreateView): model = models.Timer permission_required = ("core.add_timer",) form_class = forms.TimerForm def get_form_kwargs(self): kwargs = super(TimerAdd, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_success_url(self): return reverse("core:timer-detail", kwargs={"pk": self.object.pk}) class TimerUpdate(CoreUpdateView): model = models.Timer permission_required = ("core.change_timer",) form_class = forms.TimerForm success_url = reverse_lazy("core:timer-list") def get_form_kwargs(self): kwargs = super(TimerUpdate, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_success_url(self): instance = self.get_object() return reverse("core:timer-detail", kwargs={"pk": instance.pk}) class TimerAddQuick(PermissionRequiredMixin, RedirectView): http_method_names = ["post"] permission_required = ("core.add_timer",) def post(self, request, *args, **kwargs): instance = models.Timer.objects.create(user=request.user) # Find child from child pk in POST child_id = request.POST.get("child", False) child = models.Child.objects.get(pk=child_id) if child_id else None if child: instance.child = child # Add child relationship if there is only Child instance. elif models.Child.count() == 1: instance.child = models.Child.objects.first() instance.save() self.url = request.GET.get( "next", reverse("core:timer-detail", args={instance.id}) ) return super(TimerAddQuick, self).get(request, *args, **kwargs) class TimerRestart(PermissionRequiredMixin, RedirectView): http_method_names = ["post"] permission_required = ("core.change_timer",) def post(self, request, *args, **kwargs): instance = models.Timer.objects.get(id=kwargs["pk"]) instance.restart() messages.success(request, "{} restarted.".format(instance)) return super(TimerRestart, self).get(request, *args, **kwargs) def get_redirect_url(self, *args, **kwargs): return reverse("core:timer-detail", kwargs={"pk": kwargs["pk"]}) class TimerStop(PermissionRequiredMixin, SuccessMessageMixin, RedirectView): http_method_names = ["post"] permission_required = ("core.change_timer",) success_message = _("%(timer)s stopped.") def post(self, request, *args, **kwargs): instance = models.Timer.objects.get(id=kwargs["pk"]) instance.stop() messages.success(request, "{} stopped.".format(instance)) return super(TimerStop, self).get(request, *args, **kwargs) def get_redirect_url(self, *args, **kwargs): return reverse("core:timer-detail", kwargs={"pk": kwargs["pk"]}) class TimerDelete(CoreDeleteView): model = models.Timer permission_required = ("core.delete_timer",) success_url = reverse_lazy("core:timer-list") class TimerDeleteInactive(PermissionRequiredMixin, SuccessMessageMixin, FormView): permission_required = ("core.delete_timer",) form_class = Form template_name = "core/timer_confirm_delete_inactive.html" success_url = reverse_lazy("core:timer-list") success_message = _("All inactive timers deleted.") def get_context_data(self, **kwargs): kwargs = super().get_context_data(**kwargs) kwargs["timer_count"] = self.get_instances().count() return kwargs def get(self, request, *args, **kwargs): # Redirect back to list if there are no inactive timers. if self.get_instances().count() == 0: messages.warning(request, _("No inactive timers exist.")) return HttpResponseRedirect(self.success_url) return super().get(request, *args, **kwargs) def form_valid(self, form): self.get_instances().delete() return super().form_valid(form) @staticmethod def get_instances(): return models.Timer.objects.filter(active=False) class TummyTimeList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.TummyTime template_name = "core/tummytime_list.html" permission_required = ("core.view_tummytime",) paginate_by = 10 filterset_class = filters.TummyTimeFilter class TummyTimeAdd(CoreAddView): model = models.TummyTime permission_required = ("core.add_tummytime",) form_class = forms.TummyTimeForm success_url = reverse_lazy("core:tummytime-list") class TummyTimeUpdate(CoreUpdateView): model = models.TummyTime permission_required = ("core.change_tummytime",) form_class = forms.TummyTimeForm success_url = reverse_lazy("core:tummytime-list") class TummyTimeDelete(CoreDeleteView): model = models.TummyTime permission_required = ("core.delete_tummytime",) success_url = reverse_lazy("core:tummytime-list") class WeightList(PermissionRequiredMixin, BabyBuddyFilterView): model = models.Weight template_name = "core/weight_list.html" permission_required = ("core.view_weight",) paginate_by = 10 filterset_class = filters.WeightFilter class WeightAdd(CoreAddView): model = models.Weight permission_required = ("core.add_weight",) form_class = forms.WeightForm success_url = reverse_lazy("core:weight-list") class WeightUpdate(CoreUpdateView): model = models.Weight permission_required = ("core.change_weight",) form_class = forms.WeightForm success_url = reverse_lazy("core:weight-list") class WeightDelete(CoreDeleteView): model = models.Weight permission_required = ("core.delete_weight",) success_url = reverse_lazy("core:weight-list")