2024-05-17 13:03:20 +00:00
|
|
|
from django.views.generic import (
|
|
|
|
TemplateView,
|
|
|
|
ListView,
|
|
|
|
UpdateView,
|
|
|
|
DetailView,
|
|
|
|
CreateView,
|
|
|
|
DeleteView,
|
|
|
|
View,
|
|
|
|
)
|
2020-12-27 17:49:54 +00:00
|
|
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
from django.urls import reverse_lazy
|
2021-02-21 10:24:25 +00:00
|
|
|
from django.http import HttpResponseRedirect, HttpResponse
|
|
|
|
from django.utils import timezone
|
2021-02-21 19:13:22 +00:00
|
|
|
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
|
|
|
from django.utils.decorators import method_decorator
|
2024-11-21 06:34:09 +00:00
|
|
|
from django.templatetags.static import static
|
2020-12-27 17:49:54 +00:00
|
|
|
|
|
|
|
from .models import Status, Activity, Mood, StatusMedia, StatusActivity
|
|
|
|
from .forms import StatusForm
|
2021-03-03 07:39:26 +00:00
|
|
|
from .statistics import moodstats, activitystats, moodpies, activitymood, activitypies
|
2020-12-27 17:49:54 +00:00
|
|
|
|
2021-01-06 12:59:37 +00:00
|
|
|
from common.helpers import get_upload_path
|
2021-03-01 17:05:14 +00:00
|
|
|
from common.templatetags.images import hvhtml, bkhtml
|
2020-12-29 16:26:48 +00:00
|
|
|
from msgio.models import NotificationDailySchedule, Notification
|
2020-12-27 17:49:54 +00:00
|
|
|
|
2021-02-21 10:24:25 +00:00
|
|
|
from dateutil import relativedelta
|
|
|
|
|
2021-02-21 19:13:22 +00:00
|
|
|
from datetime import datetime
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
import json
|
|
|
|
|
|
|
|
|
2020-12-27 17:49:54 +00:00
|
|
|
class StatusListView(LoginRequiredMixin, ListView):
|
|
|
|
template_name = "mood/status_list.html"
|
|
|
|
model = Status
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Status List"
|
|
|
|
context["subtitle"] = "Just a list of your mood entries."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(reverse_lazy("mood:status_create"), "New Status", "plus")
|
|
|
|
]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_queryset(self):
|
2024-11-28 15:59:31 +00:00
|
|
|
status_list = Status.objects.filter(user=self.request.user).order_by(
|
|
|
|
"timestamp"
|
|
|
|
)
|
2024-11-28 15:15:56 +00:00
|
|
|
|
|
|
|
if "from" in self.request.GET:
|
|
|
|
from_timestamp = datetime.strptime(self.request.GET["from"], "%Y-%m-%d")
|
2024-11-28 15:59:31 +00:00
|
|
|
status_list = status_list.filter(timestamp__gte=from_timestamp)
|
2024-11-28 15:15:56 +00:00
|
|
|
|
|
|
|
if "to" in self.request.GET:
|
|
|
|
to_timestamp = datetime.strptime(self.request.GET["to"], "%Y-%m-%d")
|
|
|
|
to_timestamp = to_timestamp.replace(hour=23, minute=59, second=59)
|
2024-11-28 17:35:45 +00:00
|
|
|
status_list = status_list.filter(timestamp__lte=to_timestamp)
|
2024-11-28 15:15:56 +00:00
|
|
|
|
|
|
|
return status_list
|
2020-12-27 17:49:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
class StatusViewView(LoginRequiredMixin, DetailView):
|
|
|
|
template_name = "mood/status_view.html"
|
|
|
|
model = Status
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "View Status"
|
|
|
|
context["subtitle"] = "View the details of your mood entry."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(
|
|
|
|
reverse_lazy("mood:status_edit", kwargs={"id": self.kwargs["id"]}),
|
|
|
|
"Edit Status",
|
|
|
|
"pen",
|
|
|
|
)
|
|
|
|
]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_object(self):
|
|
|
|
return get_object_or_404(Status, user=self.request.user, id=self.kwargs["id"])
|
|
|
|
|
|
|
|
|
|
|
|
class StatusCreateView(LoginRequiredMixin, CreateView):
|
|
|
|
template_name = "mood/status_edit.html"
|
|
|
|
form_class = StatusForm
|
|
|
|
model = Status
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Create Status"
|
|
|
|
context["subtitle"] = "How are you feeling today?"
|
2024-11-21 06:47:17 +00:00
|
|
|
context["scripts"] = [static("frontend/js/dropdown-to-buttons.js")]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
form.instance.user = self.request.user
|
|
|
|
|
|
|
|
ret = super().form_valid(form)
|
|
|
|
|
|
|
|
for activity in form.cleaned_data["activities"]:
|
|
|
|
if activity.user == self.request.user:
|
|
|
|
StatusActivity.objects.create(activity=activity, status=form.instance)
|
|
|
|
|
|
|
|
for attachment in form.cleaned_data["uploads"]:
|
2021-01-06 12:59:37 +00:00
|
|
|
dba = StatusMedia(status=form.instance)
|
|
|
|
dba.file.save(get_upload_path(form.instance, attachment.name), attachment)
|
|
|
|
dba.save()
|
2020-12-27 17:49:54 +00:00
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:status_view", kwargs={"id": self.object.id})
|
|
|
|
|
|
|
|
|
|
|
|
class StatusEditView(LoginRequiredMixin, UpdateView):
|
|
|
|
template_name = "mood/status_edit.html"
|
|
|
|
form_class = StatusForm
|
|
|
|
model = Status
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Update Status"
|
|
|
|
context["subtitle"] = "Change a status you created before."
|
2024-11-21 06:47:17 +00:00
|
|
|
context["scripts"] = [static("frontend/js/dropdown-to-buttons.js")]
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(
|
|
|
|
reverse_lazy("mood:status_delete", kwargs={"id": self.kwargs["id"]}),
|
|
|
|
"Delete Status",
|
|
|
|
"trash-alt",
|
|
|
|
)
|
|
|
|
]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_object(self):
|
|
|
|
return get_object_or_404(Status, user=self.request.user, id=self.kwargs["id"])
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
for attachment in form.cleaned_data["uploads"]:
|
2021-01-06 12:59:37 +00:00
|
|
|
dba = StatusMedia(status=form.instance)
|
|
|
|
dba.file.save(get_upload_path(form.instance, attachment.name), attachment)
|
|
|
|
dba.save()
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2020-12-27 17:49:54 +00:00
|
|
|
for activity in form.cleaned_data["activities"]:
|
2020-12-28 21:32:32 +00:00
|
|
|
if activity.user == self.request.user:
|
2024-06-02 18:27:02 +00:00
|
|
|
if activity not in form.instance.activity_set:
|
2024-05-17 13:03:20 +00:00
|
|
|
StatusActivity.objects.create(
|
|
|
|
activity=activity, status=form.instance
|
|
|
|
)
|
2020-12-27 17:49:54 +00:00
|
|
|
|
|
|
|
for statusactivity in form.instance.statusactivity_set.all():
|
2024-06-02 18:27:02 +00:00
|
|
|
if statusactivity.activity not in form.cleaned_data["activities"]:
|
2020-12-27 17:49:54 +00:00
|
|
|
statusactivity.delete()
|
|
|
|
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:status_view", kwargs={"id": self.object.id})
|
|
|
|
|
|
|
|
|
|
|
|
class StatusDeleteView(LoginRequiredMixin, DeleteView):
|
|
|
|
template_name = "mood/status_delete.html"
|
|
|
|
model = Status
|
|
|
|
|
|
|
|
def get_object(self):
|
|
|
|
return get_object_or_404(Status, user=self.request.user, id=self.kwargs["id"])
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:status_list")
|
|
|
|
|
|
|
|
|
|
|
|
class ActivityListView(LoginRequiredMixin, ListView):
|
|
|
|
template_name = "mood/activity_list.html"
|
|
|
|
model = Activity
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Activities"
|
|
|
|
context["subtitle"] = "The activities you have defined."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(reverse_lazy("mood:activity_create"), "Create Activity", "pen")
|
|
|
|
]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_queryset(self):
|
|
|
|
return Activity.objects.filter(user=self.request.user)
|
|
|
|
|
|
|
|
|
|
|
|
class ActivityEditView(LoginRequiredMixin, UpdateView):
|
|
|
|
template_name = "mood/activity_edit.html"
|
|
|
|
model = Activity
|
2024-11-18 05:55:01 +00:00
|
|
|
fields = ["name", "icon", "color", "hidden"]
|
2020-12-27 17:49:54 +00:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Edit Activity"
|
|
|
|
context["subtitle"] = "Make changes to the activity."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["scripts"] = [
|
2024-11-20 20:27:56 +00:00
|
|
|
static("colorfield/jscolor/jscolor.js"),
|
|
|
|
static("colorfield/colorfield.js"),
|
|
|
|
static("frontend/js/fontawesome-iconpicker.min.js"),
|
|
|
|
static("frontend/js/iconpicker-loader.js"),
|
2024-05-17 13:03:20 +00:00
|
|
|
]
|
2024-11-20 20:27:56 +00:00
|
|
|
context["styles"] = [static("frontend/css/fontawesome-iconpicker.min.css")]
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(
|
|
|
|
reverse_lazy("mood:activity_delete", kwargs={"id": self.kwargs["id"]}),
|
|
|
|
"Delete Activity",
|
|
|
|
"trash-alt",
|
|
|
|
)
|
|
|
|
]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_object(self):
|
|
|
|
return get_object_or_404(Activity, user=self.request.user, id=self.kwargs["id"])
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:activity_list")
|
|
|
|
|
|
|
|
|
|
|
|
class ActivityCreateView(LoginRequiredMixin, CreateView):
|
|
|
|
template_name = "mood/activity_edit.html"
|
|
|
|
model = Activity
|
|
|
|
fields = ["name", "icon", "color"]
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Create Activity"
|
|
|
|
context["subtitle"] = "Add a new activity."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["scripts"] = [
|
2024-11-20 20:27:56 +00:00
|
|
|
static("colorfield/jscolor/jscolor.js"),
|
|
|
|
static("colorfield/colorfield.js"),
|
|
|
|
static("frontend/js/fontawesome-iconpicker.min.js"),
|
|
|
|
static("frontend/js/iconpicker-loader.js"),
|
2024-05-17 13:03:20 +00:00
|
|
|
]
|
2024-11-20 20:27:56 +00:00
|
|
|
context["styles"] = [static("frontend/css/fontawesome-iconpicker.min.css")]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
obj = form.save(commit=False)
|
|
|
|
obj.user = self.request.user
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:activity_list")
|
|
|
|
|
|
|
|
|
|
|
|
class ActivityDeleteView(LoginRequiredMixin, DeleteView):
|
|
|
|
template_name = "mood/activity_delete.html"
|
|
|
|
model = Activity
|
|
|
|
|
|
|
|
def get_object(self):
|
|
|
|
return get_object_or_404(Activity, user=self.request.user, id=self.kwargs["id"])
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:activity_list")
|
|
|
|
|
|
|
|
|
|
|
|
class MoodListView(LoginRequiredMixin, ListView):
|
|
|
|
template_name = "mood/mood_list.html"
|
|
|
|
model = Mood
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Moods"
|
|
|
|
context["subtitle"] = "The different moods you have defined."
|
|
|
|
return context
|
|
|
|
|
|
|
|
def get_queryset(self):
|
|
|
|
return Mood.objects.filter(user=self.request.user)
|
|
|
|
|
|
|
|
|
|
|
|
class MoodEditView(LoginRequiredMixin, UpdateView):
|
|
|
|
template_name = "mood/mood_edit.html"
|
|
|
|
model = Mood
|
|
|
|
fields = ["name", "icon", "color", "value"]
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Edit Mood"
|
|
|
|
context["subtitle"] = "Make changes to the mood."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["scripts"] = [
|
2024-11-21 06:47:17 +00:00
|
|
|
static("colorfield/jscolor/jscolor.js"),
|
|
|
|
static("colorfield/colorfield.js"),
|
|
|
|
static("frontend/js/fontawesome-iconpicker.min.js"),
|
|
|
|
static("frontend/js/iconpicker-loader.js"),
|
2024-05-17 13:03:20 +00:00
|
|
|
]
|
2024-11-21 06:47:17 +00:00
|
|
|
context["styles"] = [static("frontend/css/fontawesome-iconpicker.min.css")]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_object(self):
|
|
|
|
return get_object_or_404(Mood, user=self.request.user, id=self.kwargs["id"])
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:mood_list")
|
|
|
|
|
|
|
|
|
|
|
|
class MoodCreateView(LoginRequiredMixin, CreateView):
|
|
|
|
template_name = "mood/mood_edit.html"
|
|
|
|
model = Mood
|
|
|
|
fields = ["name", "icon", "color", "value"]
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Create Activity"
|
|
|
|
context["subtitle"] = "Add a new activity."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["scripts"] = [
|
2024-11-20 20:27:56 +00:00
|
|
|
static("colorfield/jscolor/jscolor.js"),
|
|
|
|
static("colorfield/colorfield.js"),
|
|
|
|
static("frontend/js/fontawesome-iconpicker.min.js"),
|
|
|
|
static("frontend/js/iconpicker-loader.js"),
|
2024-05-17 13:03:20 +00:00
|
|
|
]
|
2024-11-20 20:27:56 +00:00
|
|
|
context["styles"] = [static("frontend/css/fontawesome-iconpicker.min.css")]
|
2020-12-27 17:49:54 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
obj = form.save(commit=False)
|
|
|
|
obj.user = self.request.user
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
def get_success_url(self):
|
2020-12-29 16:26:48 +00:00
|
|
|
return reverse_lazy("mood:activity_list")
|
|
|
|
|
|
|
|
|
|
|
|
class NotificationListView(LoginRequiredMixin, ListView):
|
|
|
|
template_name = "mood/notification_list.html"
|
|
|
|
model = NotificationDailySchedule
|
|
|
|
fields = ["time"]
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Notifications"
|
|
|
|
context["subtitle"] = "The daily reminders you have set up."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(reverse_lazy("mood:notification_create"), "New Notification", "plus")
|
|
|
|
]
|
2020-12-29 16:26:48 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_queryset(self):
|
2024-05-17 13:03:20 +00:00
|
|
|
return NotificationDailySchedule.objects.filter(
|
|
|
|
notification__recipient=self.request.user, notification__app="mood"
|
|
|
|
)
|
2020-12-29 16:26:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
class NotificationCreateView(LoginRequiredMixin, CreateView):
|
|
|
|
template_name = "mood/notification_edit.html"
|
|
|
|
model = NotificationDailySchedule
|
|
|
|
fields = ["time"]
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Create Notification"
|
|
|
|
context["subtitle"] = "Add a new daily notification."
|
|
|
|
return context
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
2024-05-17 13:03:20 +00:00
|
|
|
notification = Notification.objects.create(
|
|
|
|
content="Hi, it's time for a new Kumify entry! Go to %KUMIFYURL% to document your mood!",
|
|
|
|
recipient=self.request.user,
|
|
|
|
app="mood",
|
|
|
|
)
|
2020-12-29 16:26:48 +00:00
|
|
|
obj = form.save(commit=False)
|
|
|
|
obj.notification = notification
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:notification_list")
|
|
|
|
|
|
|
|
|
|
|
|
class NotificationEditView(LoginRequiredMixin, UpdateView):
|
|
|
|
template_name = "mood/notification_edit.html"
|
|
|
|
model = NotificationDailySchedule
|
|
|
|
fields = ["time"]
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Edit Notification"
|
|
|
|
context["subtitle"] = "Change the time of a daily notification."
|
2024-05-17 13:03:20 +00:00
|
|
|
context["buttons"] = [
|
|
|
|
(
|
|
|
|
reverse_lazy("mood:notification_delete", args=[self.kwargs["id"]]),
|
|
|
|
"Delete Notification",
|
|
|
|
)
|
|
|
|
]
|
2020-12-29 16:26:48 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("mood:notification_list")
|
|
|
|
|
|
|
|
def get_object(self):
|
2024-05-17 13:03:20 +00:00
|
|
|
return get_object_or_404(
|
|
|
|
NotificationDailySchedule,
|
|
|
|
notification__recipient=self.request.user,
|
|
|
|
id=self.kwargs["id"],
|
|
|
|
)
|
2020-12-29 16:26:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
class NotificationDeleteView(LoginRequiredMixin, DeleteView):
|
2021-01-01 15:55:45 +00:00
|
|
|
template_name = "mood/notification_delete.html"
|
2020-12-29 16:26:48 +00:00
|
|
|
model = NotificationDailySchedule
|
|
|
|
|
|
|
|
def get_object(self):
|
2024-05-17 13:03:20 +00:00
|
|
|
return get_object_or_404(
|
|
|
|
NotificationDailySchedule,
|
|
|
|
notification__recipient=self.request.user,
|
|
|
|
id=self.kwargs["id"],
|
|
|
|
)
|
2020-12-29 16:26:48 +00:00
|
|
|
|
|
|
|
def delete(self, request, *args, **kwargs):
|
|
|
|
self.object = self.get_object()
|
|
|
|
success_url = self.get_success_url()
|
|
|
|
self.object.notification.delete()
|
|
|
|
return HttpResponseRedirect(success_url)
|
|
|
|
|
|
|
|
def get_success_url(self):
|
2021-02-21 10:24:25 +00:00
|
|
|
return reverse_lazy("mood:notification_list")
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-02-21 10:24:25 +00:00
|
|
|
class MoodStatisticsView(LoginRequiredMixin, TemplateView):
|
|
|
|
template_name = "mood/statistics.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2021-02-21 19:59:39 +00:00
|
|
|
startdate = self.request.GET.get("start")
|
|
|
|
enddate = self.request.GET.get("end")
|
|
|
|
|
|
|
|
if enddate:
|
|
|
|
maxdate = datetime.strptime(enddate, "%Y-%m-%d")
|
|
|
|
else:
|
|
|
|
maxdate = timezone.now()
|
|
|
|
|
|
|
|
if startdate:
|
|
|
|
mindate = datetime.strptime(startdate, "%Y-%m-%d")
|
|
|
|
else:
|
2024-11-20 06:18:40 +00:00
|
|
|
mindate = maxdate - relativedelta.relativedelta(weeks=1) # noqa: F841
|
2024-06-02 18:27:02 +00:00
|
|
|
# TODO: Do something with this...?
|
2021-02-21 19:59:39 +00:00
|
|
|
|
2021-02-21 10:24:25 +00:00
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["title"] = "Statistics"
|
2021-02-26 06:26:52 +00:00
|
|
|
context["activities"] = activitystats(self.request.user)
|
2021-02-21 10:24:25 +00:00
|
|
|
return context
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-02-21 10:24:25 +00:00
|
|
|
class MoodCSVView(LoginRequiredMixin, View):
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="text/csv")
|
|
|
|
res["content-disposition"] = 'filename="mood.csv"'
|
|
|
|
|
2021-02-21 19:13:22 +00:00
|
|
|
startdate = request.GET.get("start")
|
|
|
|
enddate = request.GET.get("end")
|
|
|
|
|
2021-02-26 06:38:17 +00:00
|
|
|
maxdate = None
|
|
|
|
mindate = None
|
|
|
|
|
2021-02-21 19:13:22 +00:00
|
|
|
if enddate:
|
|
|
|
maxdate = datetime.strptime(enddate, "%Y-%m-%d")
|
2021-02-26 06:38:17 +00:00
|
|
|
|
|
|
|
if not startdate:
|
|
|
|
mindate = maxdate - relativedelta.relativedelta(weeks=1)
|
2021-02-21 19:13:22 +00:00
|
|
|
|
|
|
|
if startdate:
|
|
|
|
mindate = datetime.strptime(startdate, "%Y-%m-%d")
|
2021-02-26 06:38:17 +00:00
|
|
|
|
|
|
|
if not enddate:
|
|
|
|
maxdate = mindate + relativedelta.relativedelta(weeks=1)
|
|
|
|
|
|
|
|
if not maxdate:
|
|
|
|
maxdate = timezone.now()
|
2021-02-21 19:13:22 +00:00
|
|
|
mindate = maxdate - relativedelta.relativedelta(weeks=1)
|
2021-02-21 10:24:25 +00:00
|
|
|
|
|
|
|
output = "date,value"
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
for status in Status.objects.filter(
|
|
|
|
user=request.user, timestamp__gte=mindate, timestamp__lte=maxdate
|
|
|
|
):
|
2021-02-21 19:13:22 +00:00
|
|
|
if status.mood:
|
|
|
|
date = status.timestamp.strftime("%Y-%m-%d %H:%M")
|
|
|
|
output += f"\n{date},{status.mood.value}"
|
2021-02-21 10:24:25 +00:00
|
|
|
|
|
|
|
res.write(output)
|
2021-02-21 19:13:22 +00:00
|
|
|
return res
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-02-21 19:13:22 +00:00
|
|
|
class MoodPlotView(LoginRequiredMixin, View):
|
|
|
|
@method_decorator(xframe_options_sameorigin)
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="text/html")
|
|
|
|
|
2021-03-01 17:05:14 +00:00
|
|
|
res.write(hvhtml(moodstats(request.user)))
|
|
|
|
return res
|
2021-02-21 19:13:22 +00:00
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-03-01 17:05:14 +00:00
|
|
|
class MoodPiesView(LoginRequiredMixin, View):
|
|
|
|
@method_decorator(xframe_options_sameorigin)
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super().dispatch(*args, **kwargs)
|
2021-02-21 19:13:22 +00:00
|
|
|
|
2021-03-01 17:05:14 +00:00
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="text/html")
|
2021-02-21 19:13:22 +00:00
|
|
|
|
2021-03-01 17:05:14 +00:00
|
|
|
res.write(bkhtml(moodpies(request.user)))
|
2021-03-03 07:39:26 +00:00
|
|
|
return res
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-03-03 07:39:26 +00:00
|
|
|
class ActivityStatisticsView(LoginRequiredMixin, TemplateView):
|
|
|
|
template_name = "mood/statistics_activity.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
activity = get_object_or_404(Activity, user=self.request.user, id=kwargs["id"])
|
|
|
|
context["title"] = "Activity Statistics for %s" % activity.name
|
|
|
|
return context
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-03-03 07:39:26 +00:00
|
|
|
class ActivityPlotView(LoginRequiredMixin, View):
|
|
|
|
@method_decorator(xframe_options_sameorigin)
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="text/html")
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
res.write(
|
|
|
|
hvhtml(
|
|
|
|
activitymood(
|
|
|
|
get_object_or_404(Activity, user=request.user, id=kwargs["id"])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
2021-03-03 07:39:26 +00:00
|
|
|
return res
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2021-03-03 07:39:26 +00:00
|
|
|
class ActivityPiesView(LoginRequiredMixin, View):
|
|
|
|
@method_decorator(xframe_options_sameorigin)
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="text/html")
|
|
|
|
|
2024-05-17 13:03:20 +00:00
|
|
|
res.write(
|
|
|
|
bkhtml(
|
|
|
|
activitypies(
|
|
|
|
get_object_or_404(Activity, user=request.user, id=kwargs["id"])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
class MoodCountHeatmapJSONView(LoginRequiredMixin, View):
|
|
|
|
"""Returns a JSON object with the mood entries for a given time period.
|
|
|
|
|
|
|
|
This is used in conjunction with the Cal-Heatmap library to display a
|
|
|
|
heatmap of mood entries.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="application/json")
|
|
|
|
|
|
|
|
start = request.GET.get("start")
|
|
|
|
end = request.GET.get("end")
|
|
|
|
|
|
|
|
if end:
|
|
|
|
maxdate = datetime.strptime(end, "%Y-%m-%d")
|
2024-11-28 14:35:08 +00:00
|
|
|
maxdate = maxdate.replace(hour=23, minute=59, second=59)
|
2024-05-17 13:03:20 +00:00
|
|
|
else:
|
|
|
|
maxdate = timezone.now()
|
|
|
|
|
|
|
|
if start:
|
|
|
|
mindate = datetime.strptime(start, "%Y-%m-%d")
|
|
|
|
else:
|
|
|
|
mindate = maxdate - relativedelta.relativedelta(years=1)
|
|
|
|
|
2024-11-20 06:18:40 +00:00
|
|
|
data = Status.objects.filter(
|
|
|
|
user=request.user, timestamp__gte=mindate, timestamp__lte=maxdate
|
2024-05-17 13:03:20 +00:00
|
|
|
)
|
|
|
|
|
2024-11-20 06:18:40 +00:00
|
|
|
output = {}
|
|
|
|
|
|
|
|
for entry in data:
|
|
|
|
date = entry.timestamp.strftime("%Y-%m-%d")
|
|
|
|
|
2024-11-28 15:59:31 +00:00
|
|
|
if date not in output:
|
|
|
|
output[date] = {"count": 0, "total": 0, "moodcount": 0}
|
2024-11-28 14:01:13 +00:00
|
|
|
|
|
|
|
if entry.mood:
|
|
|
|
output[date]["total"] += entry.mood.value
|
2024-11-28 15:59:31 +00:00
|
|
|
output[date]["moodcount"] += 1
|
|
|
|
|
2024-11-28 14:01:13 +00:00
|
|
|
output[date]["count"] += 1
|
|
|
|
|
|
|
|
output = [
|
|
|
|
{
|
|
|
|
"date": key,
|
|
|
|
"count": value["count"],
|
|
|
|
"average": (
|
2024-11-28 15:59:31 +00:00
|
|
|
(value["total"] / value["moodcount"])
|
|
|
|
if value["moodcount"] > 0
|
|
|
|
else 0
|
2024-11-28 14:01:13 +00:00
|
|
|
),
|
|
|
|
}
|
|
|
|
for key, value in output.items()
|
|
|
|
]
|
|
|
|
|
|
|
|
res.write(json.dumps(output))
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
class MoodHeatmapValuesJSONView(LoginRequiredMixin, View):
|
|
|
|
"""Returns a JSON object with the available mood values.
|
|
|
|
|
|
|
|
This is used to display the correct colors in the heatmap.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
res = HttpResponse(content_type="application/json")
|
|
|
|
|
|
|
|
data = Mood.objects.filter(user=request.user)
|
|
|
|
|
|
|
|
output = {
|
|
|
|
entry.value: {"name": entry.name, "icon": entry.icon, "color": entry.color}
|
|
|
|
for entry in data
|
|
|
|
}
|
2024-05-17 13:03:20 +00:00
|
|
|
|
2024-11-20 06:18:40 +00:00
|
|
|
res.write(json.dumps(output))
|
2024-05-17 13:03:20 +00:00
|
|
|
|
|
|
|
return res
|