diff --git a/apps/core/api/viewsets.py b/apps/core/api/viewsets.py
index f0ca9a6..4ea593c 100644
--- a/apps/core/api/viewsets.py
+++ b/apps/core/api/viewsets.py
@@ -1,7 +1,8 @@
+from datetime import date
from dateutil.relativedelta import relativedelta
from django.utils.decorators import method_decorator
-from django.utils.timezone import localtime
+from django.utils.timezone import localdate, localtime
from django.views.decorators.cache import cache_page
from rest_framework.exceptions import ParseError
@@ -22,6 +23,26 @@ def dispatch(self, request, *args, **kwargs):
def get_queryset(self):
qs = super().get_queryset()
+ start_date = None
+ start_search = self.request.query_params.get("start")
+ if start_search:
+ try:
+ start_date = date.fromisoformat(start_search)
+ except ValueError:
+ pass
+
+ end_date = None
+ end_search = self.request.query_params.get("end")
+ if end_search:
+ try:
+ end_date = date.fromisoformat(end_search)
+ except ValueError:
+ pass
+
+ if start_date and end_date:
+ return qs.filter(pk__range=[start_date, end_date])
+
+
if self.filterable:
for filterable in self.filterable:
value = self.request.query_params.get(filterable)
diff --git a/apps/core/forms.py b/apps/core/forms.py
new file mode 100644
index 0000000..cd294a7
--- /dev/null
+++ b/apps/core/forms.py
@@ -0,0 +1,33 @@
+from django import forms
+from django.utils.timezone import localtime
+
+
+class SearchDateForm(forms.Form):
+ """Form to search for data, between start and end dates."""
+ start = forms.DateField(
+ required=False,
+ widget=forms.DateInput(
+ attrs={
+ 'class': 'form-control-sm',
+ 'label': 'start',
+ 'name': 'start',
+ 'type': 'date'
+ }
+ )
+ )
+ end = forms.DateField(
+ required=False,
+ widget=forms.DateInput(
+ attrs={
+ 'class': 'form-control-sm',
+ 'label': 'end',
+ 'name': 'end',
+ 'type': 'date'
+ }
+ )
+ )
+
+ def get_initial_for_field(self, field, field_name):
+ # Set date inputs "max" attribute to current time.
+ field.widget.attrs["max"] = localtime().strftime("%Y-%m-%d")
+ return super().get_initial_for_field(field, field_name)
diff --git a/apps/core/templates/base.html b/apps/core/templates/base.html
index 7ccc7c7..e95d69d 100644
--- a/apps/core/templates/base.html
+++ b/apps/core/templates/base.html
@@ -54,9 +54,9 @@
-
+
diff --git a/apps/core/templates/utility.html b/apps/core/templates/utility.html
index 2434f85..f3cf5dd 100644
--- a/apps/core/templates/utility.html
+++ b/apps/core/templates/utility.html
@@ -34,7 +34,7 @@
const chartLoading = document.getElementById('chart-loading')
const utilityTitle = '{{ title }}'
const xhr = new XMLHttpRequest()
- xhr.open("GET", `/api/${utilityTitle.replace(" ", "_").toLowerCase()}/?format=json`)
+ xhr.open("GET", `/api/${utilityTitle.replace(" ", "_").toLowerCase()}/?format=json&start={{ start }}&end={{ end }}`)
xhr.onreadystatechange = async () => {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
const utilityUsageData = JSON.parse(xhr.responseText)
diff --git a/apps/core/urls.py b/apps/core/urls.py
index 3bd3a28..1724a72 100644
--- a/apps/core/urls.py
+++ b/apps/core/urls.py
@@ -3,4 +3,6 @@
from .views.home import HomeView
-urlpatterns = [path("", HomeView.as_view(), name="home")]
+urlpatterns = [
+ path("", HomeView.as_view(), name="home")
+]
diff --git a/apps/core/views/base.py b/apps/core/views/base.py
index cb79924..7ca67b0 100644
--- a/apps/core/views/base.py
+++ b/apps/core/views/base.py
@@ -1,17 +1,62 @@
+from datetime import timedelta
+
from django.conf import settings
-from django.views.generic.base import TemplateView
+from django.utils.timezone import localdate
+from django.views.generic.edit import FormView
+
+from ..forms import SearchDateForm
-class BaseView(TemplateView):
+class BaseView(FormView):
"""Base view."""
- http_method_names = ("get",)
- # icon = None
+ dates = initial = {}
+ default_start = {}
+ form_class = SearchDateForm
+ http_method_names = ("get", "post")
template_name = "utility.html"
title = None
+ def setup(self, request, *args, **kwargs):
+ # Set default search start and end datetime values.
+
+ today = localdate()
+ self.dates["start"] = None
+ if self.default_start:
+ self.dates["start"] = today - timedelta(**self.default_start)
+ self.dates["end"] = today
+
+ return super().setup(request, *args, **kwargs)
+
+
+ def form_valid(self, form):
+ # When valid, use the submitted form search dates.
+ for when in "start", "end":
+ if form.cleaned_data[when]:
+ self.dates[when] = form.cleaned_data[when]
+
+ return self.render_to_response(self.get_context_data(form=form))
+
def get_context_data(self, **kwargs):
+ # Include start and end dates in context.
context = super().get_context_data(**kwargs)
+
+ for when in "start", "end":
+ if self.dates[when]:
+ context[when] = self.dates[when].strftime("%Y-%m-%d")
+
context["timezone"] = settings.TIME_ZONE
context["title"] = self.title.replace("_", " ").title()
context["website_title"] = settings.WEBSITE_TITLE
+
return context
+
+ def get_initial(self):
+ # Set initial form search date values.
+ initial = super().get_initial()
+ for when in "start", "end":
+ if self.dates[when]:
+ initial[when] = self.dates[when].strftime("%Y-%m-%d")
+ return initial
+
+ def get_success_url(self):
+ return self.request.path
diff --git a/apps/core/views/utility.py b/apps/core/views/utility.py
index d98106a..78cab4a 100644
--- a/apps/core/views/utility.py
+++ b/apps/core/views/utility.py
@@ -18,6 +18,5 @@ def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["color"] = self.color
context["datatable_time_format"] = self.datatable_time_format
- # context["icon"] = self.icon
context["thresholds"] = self.thresholds
return context
diff --git a/apps/electric/views.py b/apps/electric/views.py
index 69f313b..cf782da 100644
--- a/apps/electric/views.py
+++ b/apps/electric/views.py
@@ -5,5 +5,5 @@ class ElectricView(UtilityView):
"""Electric usage view."""
color = "e4a11b"
datatable_time_format = "datetime('DDDD, tt')"
- # icon = "lightbulb"
+ default_start = {"days": 366.5}
thresholds = (1, 0.75, 0.5)
diff --git a/apps/natural_gas/views.py b/apps/natural_gas/views.py
index eb13d90..c9779b4 100644
--- a/apps/natural_gas/views.py
+++ b/apps/natural_gas/views.py
@@ -5,5 +5,4 @@ class NaturalGasView(UtilityView):
"""Natural gas usage view."""
color = "853cfd"
datatable_time_format = "datetime('MMMM y')"
- # icon = "fan"
thresholds = (50, 25, 10)
diff --git a/apps/water/views.py b/apps/water/views.py
index f48cc47..561cc8d 100644
--- a/apps/water/views.py
+++ b/apps/water/views.py
@@ -5,5 +5,4 @@ class WaterView(UtilityView):
"""Water usage view."""
color = "2caffe"
datatable_time_format = "date('DDDD')"
- # icon = "droplet"
thresholds = (100, 75, 50)