mirror of https://github.com/snachodog/mybuddy.git
parent
a2e203a3f8
commit
7b7f17fde6
|
@ -99,7 +99,7 @@ class TemperatureFilter(TimeFieldFilter, TagsFieldFilter):
|
|||
class TimerFilter(StartEndFieldFilter):
|
||||
class Meta(StartEndFieldFilter.Meta):
|
||||
model = models.Timer
|
||||
fields = sorted(StartEndFieldFilter.Meta.fields + ["active", "user"])
|
||||
fields = sorted(StartEndFieldFilter.Meta.fields + ["user"])
|
||||
|
||||
|
||||
class TummyTimeFilter(StartEndFieldFilter, TagsFieldFilter):
|
||||
|
|
|
@ -77,16 +77,12 @@ class CoreModelWithDurationSerializer(CoreModelSerializer):
|
|||
timer = attrs["timer"]
|
||||
attrs.pop("timer")
|
||||
|
||||
if timer.end:
|
||||
end = timer.end
|
||||
else:
|
||||
end = timezone.now()
|
||||
if timer.child:
|
||||
attrs["child"] = timer.child
|
||||
|
||||
# Overwrites values provided directly!
|
||||
attrs["start"] = timer.start
|
||||
attrs["end"] = end
|
||||
attrs["end"] = timezone.now()
|
||||
|
||||
# The "child", "start", and "end" field should all be set at this
|
||||
# point. If one is not, model validation will fail because they are
|
||||
|
@ -103,7 +99,7 @@ class CoreModelWithDurationSerializer(CoreModelSerializer):
|
|||
|
||||
# Only actually stop the timer if all validation passed.
|
||||
if timer:
|
||||
timer.stop(attrs["end"])
|
||||
timer.stop()
|
||||
|
||||
return attrs
|
||||
|
||||
|
@ -232,10 +228,11 @@ class TimerSerializer(CoreModelSerializer):
|
|||
queryset=get_user_model().objects.all(),
|
||||
required=False,
|
||||
)
|
||||
duration = serializers.DurationField(read_only=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = models.Timer
|
||||
fields = ("id", "child", "name", "start", "end", "duration", "active", "user")
|
||||
fields = ("id", "child", "name", "start", "duration", "user")
|
||||
|
||||
def validate(self, attrs):
|
||||
attrs = super(TimerSerializer, self).validate(attrs)
|
||||
|
|
41
api/tests.py
41
api/tests.py
|
@ -47,7 +47,6 @@ class TestBase:
|
|||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
timer.refresh_from_db()
|
||||
self.assertTrue(timer.active)
|
||||
child = models.Child.objects.first()
|
||||
|
||||
self.timer_test_data["child"] = child.id
|
||||
|
@ -55,11 +54,9 @@ class TestBase:
|
|||
self.endpoint, self.timer_test_data, format="json"
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
timer.refresh_from_db()
|
||||
self.assertFalse(timer.active)
|
||||
obj = self.model.objects.get(pk=response.data["id"])
|
||||
self.assertEqual(obj.start, start)
|
||||
self.assertEqual(obj.end, timer.end)
|
||||
self.assertIsNotNone(obj.end)
|
||||
|
||||
def test_post_with_timer_with_child(self):
|
||||
if not self.timer_test_data:
|
||||
|
@ -73,12 +70,10 @@ class TestBase:
|
|||
self.endpoint, self.timer_test_data, format="json"
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
timer.refresh_from_db()
|
||||
self.assertFalse(timer.active)
|
||||
obj = self.model.objects.get(pk=response.data["id"])
|
||||
self.assertEqual(obj.child, timer.child)
|
||||
self.assertIsNotNone(obj.child)
|
||||
self.assertEqual(obj.start, start)
|
||||
self.assertEqual(obj.end, timer.end)
|
||||
self.assertIsNotNone(obj.end)
|
||||
|
||||
|
||||
class BMIAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
|
||||
|
@ -703,19 +698,7 @@ class TimerAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
|
|||
def test_get(self):
|
||||
response = self.client.get(self.endpoint)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
response.data["results"][0],
|
||||
{
|
||||
"id": 1,
|
||||
"child": None,
|
||||
"name": "Fake timer",
|
||||
"start": "2017-11-17T23:30:00-05:00",
|
||||
"end": "2017-11-18T00:30:00-05:00",
|
||||
"duration": "01:00:00",
|
||||
"active": False,
|
||||
"user": 1,
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.data["results"][0]["id"], 1)
|
||||
|
||||
def test_post(self):
|
||||
data = {"name": "New fake timer", "user": 1}
|
||||
|
@ -743,31 +726,19 @@ class TimerAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
|
|||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, entry)
|
||||
self.assertEqual(response.data["name"], entry["name"])
|
||||
|
||||
def test_start_stop_timer(self):
|
||||
def test_start_restart_timer(self):
|
||||
endpoint = "{}{}/".format(self.endpoint, 1)
|
||||
response = self.client.get(endpoint)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response.data["active"])
|
||||
|
||||
response = self.client.patch(f"{endpoint}restart/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["active"])
|
||||
|
||||
# Restart twice is allowed
|
||||
response = self.client.patch(f"{endpoint}restart/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["active"])
|
||||
|
||||
response = self.client.patch(f"{endpoint}stop/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response.data["active"])
|
||||
|
||||
# Stopping twice is allowed, too
|
||||
response = self.client.patch(f"{endpoint}stop/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertFalse(response.data["active"])
|
||||
|
||||
|
||||
class TummyTimeAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
|
||||
|
|
|
@ -118,12 +118,6 @@ class TimerViewSet(viewsets.ModelViewSet):
|
|||
ordering_fields = ("duration", "end", "start")
|
||||
ordering = "-start"
|
||||
|
||||
@action(detail=True, methods=["patch"])
|
||||
def stop(self, request, pk=None):
|
||||
timer = self.get_object()
|
||||
timer.stop()
|
||||
return Response(self.serializer_class(timer).data)
|
||||
|
||||
@action(detail=True, methods=["patch"])
|
||||
def restart(self, request, pk=None):
|
||||
timer = self.get_object()
|
||||
|
|
|
@ -393,9 +393,6 @@
|
|||
{
|
||||
"name": "Fake timer",
|
||||
"start": "2017-11-18T04:30:00Z",
|
||||
"end": "2017-11-18T05:30:00Z",
|
||||
"duration": "01:00:00",
|
||||
"active": false,
|
||||
"user": 1
|
||||
}
|
||||
},
|
||||
|
|
|
@ -216,8 +216,8 @@ class TemperatureAdmin(ImportExportMixin, ExportActionMixin, admin.ModelAdmin):
|
|||
|
||||
@admin.register(models.Timer)
|
||||
class TimerAdmin(admin.ModelAdmin):
|
||||
list_display = ("name", "child", "start", "end", "duration", "active", "user")
|
||||
list_filter = ("child", "active", "user")
|
||||
list_display = ("name", "child", "start", "duration", "user")
|
||||
list_filter = ("child", "user")
|
||||
search_fields = ("child__first_name", "child__last_name", "name", "user")
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ def set_initial_values(kwargs, form_type):
|
|||
if timer_id:
|
||||
timer = models.Timer.objects.get(id=timer_id)
|
||||
kwargs["initial"].update(
|
||||
{"timer": timer, "start": timer.start, "end": timer.end or timezone.now()}
|
||||
{"timer": timer, "start": timer.start, "end": timezone.now()}
|
||||
)
|
||||
|
||||
# Set type and method values for Feeding instance based on last feed.
|
||||
|
@ -83,7 +83,7 @@ class CoreModelForm(forms.ModelForm):
|
|||
instance = super(CoreModelForm, self).save(commit=False)
|
||||
if self.timer_id:
|
||||
timer = models.Timer.objects.get(id=self.timer_id)
|
||||
timer.stop(instance.end)
|
||||
timer.stop()
|
||||
if commit:
|
||||
instance.save()
|
||||
self.save_m2m()
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
from django.db import migrations
|
||||
|
||||
|
||||
def delete_inactive_timers(apps, schema_editor):
|
||||
from core import models
|
||||
|
||||
for timer in models.Timer.objects.filter(active=False):
|
||||
timer.delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("core", "0026_alter_feeding_end_alter_feeding_start_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="timer",
|
||||
options={
|
||||
"default_permissions": ("view", "add", "change", "delete"),
|
||||
"ordering": ["-start"],
|
||||
"verbose_name": "Timer",
|
||||
"verbose_name_plural": "Timers",
|
||||
},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="timer",
|
||||
name="duration",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="timer",
|
||||
name="end",
|
||||
),
|
||||
migrations.RunPython(
|
||||
delete_inactive_timers, reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
|
@ -559,12 +559,6 @@ class Timer(models.Model):
|
|||
start = models.DateTimeField(
|
||||
default=timezone.now, blank=False, verbose_name=_("Start time")
|
||||
)
|
||||
end = models.DateTimeField(
|
||||
blank=True, editable=False, null=True, verbose_name=_("End time")
|
||||
)
|
||||
duration = models.DurationField(
|
||||
editable=False, null=True, verbose_name=_("Duration")
|
||||
)
|
||||
active = models.BooleanField(default=True, editable=False, verbose_name=_("Active"))
|
||||
user = models.ForeignKey(
|
||||
"auth.User",
|
||||
|
@ -577,7 +571,7 @@ class Timer(models.Model):
|
|||
|
||||
class Meta:
|
||||
default_permissions = ("view", "add", "change", "delete")
|
||||
ordering = ["-active", "-start", "-end"]
|
||||
ordering = ["-start"]
|
||||
verbose_name = _("Timer")
|
||||
verbose_name_plural = _("Timers")
|
||||
|
||||
|
@ -600,42 +594,24 @@ class Timer(models.Model):
|
|||
return self.user.get_full_name()
|
||||
return self.user.get_username()
|
||||
|
||||
@classmethod
|
||||
def from_db(cls, db, field_names, values):
|
||||
instance = super(Timer, cls).from_db(db, field_names, values)
|
||||
if not instance.duration:
|
||||
instance.duration = timezone.now() - instance.start
|
||||
return instance
|
||||
def duration(self):
|
||||
return timezone.now() - self.start
|
||||
|
||||
def restart(self):
|
||||
"""Restart the timer."""
|
||||
self.start = timezone.now()
|
||||
self.end = None
|
||||
self.duration = None
|
||||
self.active = True
|
||||
self.save()
|
||||
|
||||
def stop(self, end=None):
|
||||
"""Stop the timer."""
|
||||
if not end:
|
||||
end = timezone.now()
|
||||
self.end = end
|
||||
self.save()
|
||||
def stop(self):
|
||||
"""Stop (delete) the timer."""
|
||||
self.delete()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.active = self.end is None
|
||||
self.name = self.name or None
|
||||
if self.start and self.end:
|
||||
self.duration = self.end - self.start
|
||||
else:
|
||||
self.duration = None
|
||||
super(Timer, self).save(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
validate_time(self.start, "start")
|
||||
if self.end:
|
||||
validate_time(self.end, "end")
|
||||
validate_duration(self)
|
||||
|
||||
|
||||
class TummyTime(models.Model):
|
||||
|
|
|
@ -93,14 +93,8 @@ BabyBuddy.Timer = function ($) {
|
|||
timerElement.find('.timer-minutes').text(parseInt(duration[1]));
|
||||
timerElement.find('.timer-seconds').text(parseInt(duration[2]));
|
||||
lastUpdate = new Date()
|
||||
|
||||
if (data['active']) {
|
||||
runIntervalId = setInterval(Timer.tick, 1000);
|
||||
}
|
||||
else {
|
||||
timerElement.addClass('timer-stopped');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
{% extends 'babybuddy/page.html' %}
|
||||
{% load humanize i18n widget_tweaks %}
|
||||
|
||||
{% block title %}
|
||||
{% blocktrans %}Delete All Inactive Timers{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'core:timer-list' %}">{% trans "Timers" %}</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{% trans "Delete Inactive" %}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form role="form" method="post">
|
||||
{% csrf_token %}
|
||||
<h1>
|
||||
{% blocktrans trimmed with number=timer_count|apnumber|intcomma count counter=timer_count %}
|
||||
Are you sure you want to delete {{ number }} inactive timer?
|
||||
{% plural %}
|
||||
Are you sure you want to delete {{ number }} inactive timers?
|
||||
{% endblocktrans %}
|
||||
</h1>
|
||||
<input type="submit" value="{% trans "Delete" %}" class="btn btn-danger" />
|
||||
<a href={% url "babybuddy:root-router" %} class="btn btn-default">{% trans "Cancel" %}</a>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -13,7 +13,7 @@
|
|||
<div class="p-5 mb-4 bg-dark rounded-3 text-center">
|
||||
<div class="container-fluid py-1">
|
||||
<h1 id="timer-status"
|
||||
class="display-1 {% if not object.active %} timer-stopped{% endif %}">
|
||||
class="display-1">
|
||||
<span class="timer-hours">{{ object.duration|hours }}</span>h
|
||||
<span class="timer-minutes">{{ object.duration|minutes }}</span>m
|
||||
<span class="timer-seconds">{{ object.duration|seconds }}</span>s
|
||||
|
@ -27,9 +27,6 @@
|
|||
|
||||
<p class="lead text-secondary">
|
||||
{% trans "Started" %} {{ object.start }}
|
||||
{% if not object.active %}
|
||||
/ {% trans "Stopped" %} {{ object.end }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
{% blocktrans trimmed with user=object.user_username %}
|
||||
|
@ -80,14 +77,6 @@
|
|||
<label class="visually-hidden">{% trans "Restart timer" %}</label>
|
||||
<button type="submit" class="btn btn-lg btn-secondary"><i class="icon-refresh" aria-hidden="true"></i></button>
|
||||
</form>
|
||||
|
||||
{% if object.active %}
|
||||
<form action="{% url 'core:timer-stop' timer.id %}" role="form" method="post" class="d-inline">
|
||||
{% csrf_token %}
|
||||
<label class="visually-hidden">{% trans "Delete timer" %}</label>
|
||||
<button type="submit" class="btn btn-lg btn-warning"><i class="icon-stop" aria-hidden="true"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -95,9 +84,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
{% if object.active %}
|
||||
<script type="application/javascript">
|
||||
BabyBuddy.Timer.run({{ timer.id }}, 'timer-status');
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -62,11 +62,4 @@
|
|||
</table>
|
||||
</div>
|
||||
{% include 'babybuddy/paginator.html' %}
|
||||
|
||||
{% if object_list and perms.core.delete_timer %}
|
||||
<a href="{% url 'core:timer-delete-inactive' %}" class="btn btn-sm btn-danger">
|
||||
<i class="icon-delete" aria-hidden="true"></i> {% trans "Delete Inactive Timers" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -49,7 +49,7 @@
|
|||
{% endif %}
|
||||
{% if timers %}
|
||||
<div class="dropdown-divider"></div>
|
||||
<h6 class="dropdown-header">{% trans "Active Timers" %}</h6>
|
||||
<h6 class="dropdown-header">{% trans "Timers" %}</h6>
|
||||
{% for timer in timers %}
|
||||
<a class="dropdown-item" href="{% url 'core:timer-detail' timer.id %}">
|
||||
{{ timer.title_with_child }}
|
||||
|
|
|
@ -8,15 +8,14 @@ register = template.Library()
|
|||
|
||||
|
||||
@register.inclusion_tag("core/timer_nav.html", takes_context=True)
|
||||
def timer_nav(context, active=True):
|
||||
def timer_nav(context):
|
||||
"""
|
||||
Get a list of active Timer instances to include in the nav menu.
|
||||
Get a list of Timer instances to include in the nav menu.
|
||||
:param context: Django's context data.
|
||||
:param active: the state of Timers to filter.
|
||||
:returns: a dictionary with timers data.
|
||||
"""
|
||||
request = context["request"] or None
|
||||
timers = Timer.objects.filter(active=active)
|
||||
timers = Timer.objects.filter()
|
||||
children = Child.objects.all()
|
||||
perms = context["perms"] or None
|
||||
# The 'next' parameter is currently not used.
|
||||
|
|
|
@ -122,27 +122,23 @@ class InitialValuesTestCase(FormsTestCaseBase):
|
|||
self.assertEqual(page.context["form"].initial["type"], f_three.type)
|
||||
self.assertEqual(page.context["form"].initial["method"], f_three.method)
|
||||
|
||||
def test_timer_set(self):
|
||||
def test_timer_form_field_set(self):
|
||||
self.timer.stop()
|
||||
|
||||
page = self.c.get("/sleep/add/")
|
||||
self.assertTrue("start" not in page.context["form"].initial)
|
||||
self.assertTrue("end" not in page.context["form"].initial)
|
||||
|
||||
page = self.c.get("/sleep/add/?timer={}".format(self.timer.id))
|
||||
self.assertEqual(page.context["form"].initial["start"], self.timer.start)
|
||||
self.assertEqual(page.context["form"].initial["end"], self.timer.end)
|
||||
|
||||
def test_timer_stop_on_save(self):
|
||||
end = timezone.localtime()
|
||||
timer = models.Timer.objects.create(
|
||||
user=self.user, start=timezone.localtime() - timezone.timedelta(minutes=30)
|
||||
)
|
||||
params = {
|
||||
"child": self.child.id,
|
||||
"start": self.localtime_string(self.timer.start),
|
||||
"end": self.localtime_string(end),
|
||||
"end": self.localtime_string(),
|
||||
}
|
||||
page = self.c.post(
|
||||
"/sleep/add/?timer={}".format(self.timer.id), params, follow=True
|
||||
)
|
||||
page = self.c.post("/sleep/add/?timer={}".format(timer.id), params, follow=True)
|
||||
self.assertEqual(page.status_code, 200)
|
||||
self.timer.refresh_from_db()
|
||||
self.assertFalse(self.timer.active)
|
||||
|
|
|
@ -270,11 +270,9 @@ class TimerTestCase(TestCase):
|
|||
)
|
||||
self.user = get_user_model().objects.first()
|
||||
self.named = models.Timer.objects.create(
|
||||
name="Named", end=timezone.localtime(), user=self.user, child=child
|
||||
)
|
||||
self.unnamed = models.Timer.objects.create(
|
||||
end=timezone.localtime(), user=self.user
|
||||
name="Named", user=self.user, child=child
|
||||
)
|
||||
self.unnamed = models.Timer.objects.create(user=self.user)
|
||||
|
||||
def test_timer_create(self):
|
||||
self.assertEqual(self.named, models.Timer.objects.get(name="Named"))
|
||||
|
@ -302,19 +300,7 @@ class TimerTestCase(TestCase):
|
|||
|
||||
def test_timer_restart(self):
|
||||
self.named.restart()
|
||||
self.assertIsNone(self.named.end)
|
||||
self.assertIsNone(self.named.duration)
|
||||
self.assertTrue(self.named.active)
|
||||
|
||||
def test_timer_stop(self):
|
||||
stop_time = timezone.localtime()
|
||||
self.unnamed.stop(end=stop_time)
|
||||
self.assertEqual(self.unnamed.end, stop_time)
|
||||
self.assertEqual(
|
||||
self.unnamed.duration.seconds,
|
||||
(self.unnamed.end - self.unnamed.start).seconds,
|
||||
)
|
||||
self.assertFalse(self.unnamed.active)
|
||||
self.assertGreaterEqual(timezone.localtime(), self.named.start)
|
||||
|
||||
def test_timer_duration(self):
|
||||
timer = models.Timer.objects.create(user=get_user_model().objects.first())
|
||||
|
@ -322,9 +308,9 @@ class TimerTestCase(TestCase):
|
|||
timer.save()
|
||||
timer.refresh_from_db()
|
||||
|
||||
self.assertEqual(timer.duration.seconds, timezone.timedelta(minutes=30).seconds)
|
||||
timer.stop()
|
||||
self.assertEqual(timer.duration.seconds, timezone.timedelta(minutes=30).seconds)
|
||||
self.assertEqual(
|
||||
timer.duration().seconds, timezone.timedelta(minutes=30).seconds
|
||||
)
|
||||
|
||||
|
||||
class TummyTimeTestCase(TestCase):
|
||||
|
|
|
@ -178,28 +178,11 @@ class ViewsTestCase(TestCase):
|
|||
page = self.c.get("/timers/{}/delete/".format(entry.id))
|
||||
self.assertEqual(page.status_code, 200)
|
||||
|
||||
page = self.c.get("/timers/{}/stop/".format(entry.id))
|
||||
self.assertEqual(page.status_code, 405)
|
||||
page = self.c.post("/timers/{}/stop/".format(entry.id), follow=True)
|
||||
self.assertEqual(page.status_code, 200)
|
||||
|
||||
page = self.c.get("/timers/{}/restart/".format(entry.id))
|
||||
self.assertEqual(page.status_code, 405)
|
||||
page = self.c.post("/timers/{}/restart/".format(entry.id), follow=True)
|
||||
self.assertEqual(page.status_code, 200)
|
||||
|
||||
page = self.c.get("/timers/delete-inactive/", follow=True)
|
||||
self.assertEqual(page.status_code, 200)
|
||||
messages = list(page.context["messages"])
|
||||
self.assertEqual(len(messages), 1)
|
||||
self.assertEqual(str(messages[0]), "No inactive timers exist.")
|
||||
|
||||
entry = models.Timer.objects.first()
|
||||
entry.stop()
|
||||
page = self.c.get("/timers/delete-inactive/")
|
||||
self.assertEqual(page.status_code, 200)
|
||||
self.assertEqual(page.context["timer_count"], 1)
|
||||
|
||||
def test_timeline_views(self):
|
||||
child = models.Child.objects.first()
|
||||
response = self.c.get("/timeline/")
|
||||
|
|
|
@ -72,15 +72,9 @@ urlpatterns = [
|
|||
path("timers/<int:pk>/", views.TimerDetail.as_view(), name="timer-detail"),
|
||||
path("timers/<int:pk>/edit/", views.TimerUpdate.as_view(), name="timer-update"),
|
||||
path("timers/<int:pk>/delete/", views.TimerDelete.as_view(), name="timer-delete"),
|
||||
path("timers/<int:pk>/stop/", views.TimerStop.as_view(), name="timer-stop"),
|
||||
path(
|
||||
"timers/<int:pk>/restart/", views.TimerRestart.as_view(), name="timer-restart"
|
||||
),
|
||||
path(
|
||||
"timers/delete-inactive/",
|
||||
views.TimerDeleteInactive.as_view(),
|
||||
name="timer-delete-inactive",
|
||||
),
|
||||
path("tummy-time/", views.TummyTimeList.as_view(), name="tummytime-list"),
|
||||
path("tummy-time/add/", views.TummyTimeAdd.as_view(), name="tummytime-add"),
|
||||
path(
|
||||
|
|
|
@ -404,7 +404,7 @@ class TimerList(PermissionRequiredMixin, BabyBuddyFilterView):
|
|||
template_name = "core/timer_list.html"
|
||||
permission_required = ("core.view_timer",)
|
||||
paginate_by = 10
|
||||
filterset_fields = ("active", "user")
|
||||
filterset_fields = ("user",)
|
||||
|
||||
|
||||
class TimerDetail(PermissionRequiredMixin, DetailView):
|
||||
|
@ -477,55 +477,12 @@ class TimerRestart(PermissionRequiredMixin, RedirectView):
|
|||
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"
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
|
||||
{% block header %}
|
||||
<a href="{% url "core:timer-list" %}">
|
||||
{% trans "Active Timers" %}
|
||||
{% trans "Timers" %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
{% with instances|length as count %}
|
||||
{% blocktrans trimmed count counter=count %}
|
||||
{{ count }} active timer
|
||||
{{ count }} timer
|
||||
{% plural %}
|
||||
{{ count }} active timers
|
||||
{{ count }} timers
|
||||
{% endblocktrans %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -707,10 +707,10 @@ def card_timer_list(context, child=None):
|
|||
if child:
|
||||
# Get active instances for the selected child _or_ None (no child).
|
||||
instances = models.Timer.objects.filter(
|
||||
Q(active=True), Q(child=child) | Q(child=None)
|
||||
Q(child=child) | Q(child=None)
|
||||
).order_by("-start")
|
||||
else:
|
||||
instances = models.Timer.objects.filter(active=True).order_by("-start")
|
||||
instances = models.Timer.objects.order_by("-start")
|
||||
empty = len(instances) == 0
|
||||
|
||||
return {
|
||||
|
|
|
@ -323,7 +323,7 @@ class TemplateTagsTestCase(TestCase):
|
|||
|
||||
data = cards.card_timer_list(self.context)
|
||||
self.assertIsInstance(data["instances"][0], models.Timer)
|
||||
self.assertEqual(len(data["instances"]), 3)
|
||||
self.assertEqual(len(data["instances"]), 4)
|
||||
|
||||
data = cards.card_timer_list(self.context, child)
|
||||
self.assertIsInstance(data["instances"][0], models.Timer)
|
||||
|
|
22
docs/api.md
22
docs/api.md
|
@ -222,9 +222,7 @@ Note the timer `id` in the response:
|
|||
"child": 1,
|
||||
"name": null,
|
||||
"start": "2022-05-28T19:59:40.013914Z",
|
||||
"end": null,
|
||||
"duration": null,
|
||||
"active": true,
|
||||
"user": 1
|
||||
}
|
||||
```
|
||||
|
@ -252,25 +250,7 @@ Note that `child` and `start` match the timer values (and `end` is auto-populate
|
|||
}
|
||||
```
|
||||
|
||||
Also note that the timer has been stopped:
|
||||
|
||||
```shell
|
||||
curl --location --request GET '[...]/api/timers/5' \
|
||||
--header 'Authorization: Token [...]'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 5,
|
||||
"child": 1,
|
||||
"name": null,
|
||||
"start": "2022-05-28T19:59:40.013914Z",
|
||||
"end": "2022-05-28T20:01:13.549099Z",
|
||||
"duration": "00:01:33.535185",
|
||||
"active": false,
|
||||
"user": 1
|
||||
}
|
||||
```
|
||||
Also note that the timer has been deleted.
|
||||
|
||||
### Response
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ an overview of all elements related to your child, including:
|
|||
- Last sleep is the start of the last nap/sleep, and includes the nap duration below.
|
||||
- Last feeding method is a quick view of how the baby was last fed. This is particularly useful for nursing mothers to remember which breast they started with on the previous feed.
|
||||
- Today's Feeding is a snapshot of the total numbers of daily feeds.
|
||||
- Active timers let you know if you have a timer running.
|
||||
- Timers let you know if you have a timer running.
|
||||
- Statistics is a snapshot of various statistics – these can be scrolled through or select Statistics from the menu bar to see more.
|
||||
- Today's Sleep lists the total number of hours slept for the day.
|
||||
- Today's Naps lists the number of naps taken that day in bold and the total nap time below.
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
if (typeof jQuery === 'undefined') {
|
||||
throw new Error('Baby Buddy requires jQuery.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Baby Buddy Namespace
|
||||
*
|
||||
* Default namespace for the Baby Buddy app.
|
||||
*
|
||||
* @type {{}}
|
||||
*/
|
||||
var BabyBuddy = function () {
|
||||
return {};
|
||||
}();
|
||||
|
||||
/**
|
||||
* Pull to refresh.
|
||||
*
|
||||
* @type {{init: BabyBuddy.PullToRefresh.init, onRefresh: BabyBuddy.PullToRefresh.onRefresh}}
|
||||
*/
|
||||
BabyBuddy.PullToRefresh = function(ptr) {
|
||||
return {
|
||||
init: function () {
|
||||
ptr.init({
|
||||
mainElement: 'body',
|
||||
onRefresh: this.onRefresh
|
||||
});
|
||||
},
|
||||
|
||||
onRefresh: function() {
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
}(PullToRefresh);
|
||||
|
||||
/**
|
||||
* Fix for duplicate form submission from double pressing submit
|
||||
*/
|
||||
function preventDoubleSubmit() {
|
||||
return false;
|
||||
}
|
||||
$('form').off("submit", preventDoubleSubmit);
|
||||
$("form").on("submit", function() {
|
||||
$(this).on("submit", preventDoubleSubmit);
|
||||
});
|
||||
|
||||
/* Baby Buddy Timer
|
||||
*
|
||||
* Uses a supplied ID to run a timer. The element using the ID must have
|
||||
* three children with the following classes:
|
||||
* * timer-seconds
|
||||
* * timer-minutes
|
||||
* * timer-hours
|
||||
*/
|
||||
BabyBuddy.Timer = function ($) {
|
||||
var runIntervalId = null;
|
||||
var timerId = null;
|
||||
var timerElement = null;
|
||||
var lastUpdate = new Date();
|
||||
var hidden = null;
|
||||
|
||||
var Timer = {
|
||||
run: function(timer_id, element_id) {
|
||||
timerId = timer_id;
|
||||
timerElement = $('#' + element_id);
|
||||
|
||||
if (timerElement.length === 0) {
|
||||
console.error('BBTimer: Timer element not found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timerElement.find('.timer-seconds').length === 0
|
||||
|| timerElement.find('.timer-minutes').length === 0
|
||||
|| timerElement.find('.timer-hours').length === 0) {
|
||||
console.error('BBTimer: Element does not contain expected children.');
|
||||
return false;
|
||||
}
|
||||
|
||||
runIntervalId = setInterval(this.tick, 1000);
|
||||
|
||||
// If the page just came in to view, update the timer data with the
|
||||
// current actual duration. This will (potentially) help mobile
|
||||
// phones that lock with the timer page open.
|
||||
if (typeof document.hidden !== "undefined") {
|
||||
hidden = "hidden";
|
||||
}
|
||||
else if (typeof document.msHidden !== "undefined") {
|
||||
hidden = "msHidden";
|
||||
}
|
||||
else if (typeof document.webkitHidden !== "undefined") {
|
||||
hidden = "webkitHidden";
|
||||
}
|
||||
window.addEventListener('focus', Timer.handleVisibilityChange, false);
|
||||
},
|
||||
|
||||
handleVisibilityChange: function() {
|
||||
if (!document[hidden] && (new Date()) - lastUpdate > 1) {
|
||||
Timer.update();
|
||||
}
|
||||
},
|
||||
|
||||
tick: function() {
|
||||
var s = timerElement.find('.timer-seconds');
|
||||
var seconds = Number(s.text());
|
||||
if (seconds < 59) {
|
||||
s.text(seconds + 1);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
s.text(0);
|
||||
}
|
||||
|
||||
var m = timerElement.find('.timer-minutes');
|
||||
var minutes = Number(m.text());
|
||||
if (minutes < 59) {
|
||||
m.text(minutes + 1);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m.text(0);
|
||||
}
|
||||
|
||||
var h = timerElement.find('.timer-hours');
|
||||
var hours = Number(h.text());
|
||||
h.text(hours + 1);
|
||||
},
|
||||
|
||||
update: function() {
|
||||
$.get('/api/timers/' + timerId + '/', function(data) {
|
||||
if (data && 'duration' in data) {
|
||||
clearInterval(runIntervalId);
|
||||
var duration = data.duration.split(/[\s:.]/)
|
||||
if (duration.length === 5) {
|
||||
duration[0] = parseInt(duration[0]) * 24 + parseInt(duration[1]);
|
||||
duration[1] = duration[2];
|
||||
duration[2] = duration[3];
|
||||
}
|
||||
timerElement.find('.timer-hours').text(parseInt(duration[0]));
|
||||
timerElement.find('.timer-minutes').text(parseInt(duration[1]));
|
||||
timerElement.find('.timer-seconds').text(parseInt(duration[2]));
|
||||
lastUpdate = new Date()
|
||||
runIntervalId = setInterval(Timer.tick, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return Timer;
|
||||
}(jQuery);
|
||||
|
||||
/* Baby Buddy Dashboard
|
||||
*
|
||||
* Provides a "watch" function to update the dashboard at one minute intervals
|
||||
* and/or on visibility state changes.
|
||||
*/
|
||||
BabyBuddy.Dashboard = function ($) {
|
||||
var runIntervalId = null;
|
||||
var dashboardElement = null;
|
||||
var hidden = null;
|
||||
|
||||
var Dashboard = {
|
||||
watch: function(element_id, refresh_rate) {
|
||||
dashboardElement = $('#' + element_id);
|
||||
|
||||
if (dashboardElement.length == 0) {
|
||||
console.error('Baby Buddy: Dashboard element not found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof document.hidden !== "undefined") {
|
||||
hidden = "hidden";
|
||||
}
|
||||
else if (typeof document.msHidden !== "undefined") {
|
||||
hidden = "msHidden";
|
||||
}
|
||||
else if (typeof document.webkitHidden !== "undefined") {
|
||||
hidden = "webkitHidden";
|
||||
}
|
||||
|
||||
if (typeof window.addEventListener === "undefined" || typeof document.hidden === "undefined") {
|
||||
if (refresh_rate) {
|
||||
runIntervalId = setInterval(this.update, refresh_rate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
window.addEventListener('focus', Dashboard.handleVisibilityChange, false);
|
||||
if (refresh_rate) {
|
||||
runIntervalId = setInterval(Dashboard.handleVisibilityChange, refresh_rate);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleVisibilityChange: function() {
|
||||
if (!document[hidden]) {
|
||||
Dashboard.update();
|
||||
}
|
||||
},
|
||||
|
||||
update: function() {
|
||||
// TODO: Someday maybe update in place?
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
return Dashboard;
|
||||
}(jQuery);
|
Binary file not shown.
|
@ -1 +1,206 @@
|
|||
if("undefined"==typeof jQuery)throw new Error("Baby Buddy requires jQuery.");var BabyBuddy={};function preventDoubleSubmit(){return!1}BabyBuddy.PullToRefresh=function(e){return{init:function(){e.init({mainElement:"body",onRefresh:this.onRefresh})},onRefresh:function(){window.location.reload()}}}(PullToRefresh),$("form").off("submit",preventDoubleSubmit),$("form").on("submit",function(){$(this).on("submit",preventDoubleSubmit)}),BabyBuddy.Timer=function(e){var n=null,t=null,i=null,d=new Date,r=null,o={run:function(d,u){return t=d,0===(i=e("#"+u)).length?(console.error("BBTimer: Timer element not found."),!1):0===i.find(".timer-seconds").length||0===i.find(".timer-minutes").length||0===i.find(".timer-hours").length?(console.error("BBTimer: Element does not contain expected children."),!1):(n=setInterval(this.tick,1e3),void 0!==document.hidden?r="hidden":void 0!==document.msHidden?r="msHidden":void 0!==document.webkitHidden&&(r="webkitHidden"),void window.addEventListener("focus",o.handleVisibilityChange,!1))},handleVisibilityChange:function(){!document[r]&&new Date-d>1&&o.update()},tick:function(){var e=i.find(".timer-seconds"),n=Number(e.text());if(n<59)e.text(n+1);else{e.text(0);var t=i.find(".timer-minutes"),d=Number(t.text());if(d<59)t.text(d+1);else{t.text(0);var r=i.find(".timer-hours"),o=Number(r.text());r.text(o+1)}}},update:function(){e.get("/api/timers/"+t+"/",function(e){if(e&&"duration"in e){clearInterval(n);var t=e.duration.split(/[\s:.]/);5===t.length&&(t[0]=24*parseInt(t[0])+parseInt(t[1]),t[1]=t[2],t[2]=t[3]),i.find(".timer-hours").text(parseInt(t[0])),i.find(".timer-minutes").text(parseInt(t[1])),i.find(".timer-seconds").text(parseInt(t[2])),d=new Date,e.active?n=setInterval(o.tick,1e3):i.addClass("timer-stopped")}})}};return o}(jQuery),BabyBuddy.Dashboard=function(e){var n=null,t={watch:function(i,d){if(0==e("#"+i).length)return console.error("Baby Buddy: Dashboard element not found."),!1;void 0!==document.hidden?n="hidden":void 0!==document.msHidden?n="msHidden":void 0!==document.webkitHidden&&(n="webkitHidden"),void 0===window.addEventListener||void 0===document.hidden?d&&setInterval(this.update,d):(window.addEventListener("focus",t.handleVisibilityChange,!1),d&&setInterval(t.handleVisibilityChange,d))},handleVisibilityChange:function(){document[n]||t.update()},update:function(){location.reload()}};return t}(jQuery);
|
||||
if (typeof jQuery === 'undefined') {
|
||||
throw new Error('Baby Buddy requires jQuery.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Baby Buddy Namespace
|
||||
*
|
||||
* Default namespace for the Baby Buddy app.
|
||||
*
|
||||
* @type {{}}
|
||||
*/
|
||||
var BabyBuddy = function () {
|
||||
return {};
|
||||
}();
|
||||
|
||||
/**
|
||||
* Pull to refresh.
|
||||
*
|
||||
* @type {{init: BabyBuddy.PullToRefresh.init, onRefresh: BabyBuddy.PullToRefresh.onRefresh}}
|
||||
*/
|
||||
BabyBuddy.PullToRefresh = function(ptr) {
|
||||
return {
|
||||
init: function () {
|
||||
ptr.init({
|
||||
mainElement: 'body',
|
||||
onRefresh: this.onRefresh
|
||||
});
|
||||
},
|
||||
|
||||
onRefresh: function() {
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
}(PullToRefresh);
|
||||
|
||||
/**
|
||||
* Fix for duplicate form submission from double pressing submit
|
||||
*/
|
||||
function preventDoubleSubmit() {
|
||||
return false;
|
||||
}
|
||||
$('form').off("submit", preventDoubleSubmit);
|
||||
$("form").on("submit", function() {
|
||||
$(this).on("submit", preventDoubleSubmit);
|
||||
});
|
||||
|
||||
/* Baby Buddy Timer
|
||||
*
|
||||
* Uses a supplied ID to run a timer. The element using the ID must have
|
||||
* three children with the following classes:
|
||||
* * timer-seconds
|
||||
* * timer-minutes
|
||||
* * timer-hours
|
||||
*/
|
||||
BabyBuddy.Timer = function ($) {
|
||||
var runIntervalId = null;
|
||||
var timerId = null;
|
||||
var timerElement = null;
|
||||
var lastUpdate = new Date();
|
||||
var hidden = null;
|
||||
|
||||
var Timer = {
|
||||
run: function(timer_id, element_id) {
|
||||
timerId = timer_id;
|
||||
timerElement = $('#' + element_id);
|
||||
|
||||
if (timerElement.length === 0) {
|
||||
console.error('BBTimer: Timer element not found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timerElement.find('.timer-seconds').length === 0
|
||||
|| timerElement.find('.timer-minutes').length === 0
|
||||
|| timerElement.find('.timer-hours').length === 0) {
|
||||
console.error('BBTimer: Element does not contain expected children.');
|
||||
return false;
|
||||
}
|
||||
|
||||
runIntervalId = setInterval(this.tick, 1000);
|
||||
|
||||
// If the page just came in to view, update the timer data with the
|
||||
// current actual duration. This will (potentially) help mobile
|
||||
// phones that lock with the timer page open.
|
||||
if (typeof document.hidden !== "undefined") {
|
||||
hidden = "hidden";
|
||||
}
|
||||
else if (typeof document.msHidden !== "undefined") {
|
||||
hidden = "msHidden";
|
||||
}
|
||||
else if (typeof document.webkitHidden !== "undefined") {
|
||||
hidden = "webkitHidden";
|
||||
}
|
||||
window.addEventListener('focus', Timer.handleVisibilityChange, false);
|
||||
},
|
||||
|
||||
handleVisibilityChange: function() {
|
||||
if (!document[hidden] && (new Date()) - lastUpdate > 1) {
|
||||
Timer.update();
|
||||
}
|
||||
},
|
||||
|
||||
tick: function() {
|
||||
var s = timerElement.find('.timer-seconds');
|
||||
var seconds = Number(s.text());
|
||||
if (seconds < 59) {
|
||||
s.text(seconds + 1);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
s.text(0);
|
||||
}
|
||||
|
||||
var m = timerElement.find('.timer-minutes');
|
||||
var minutes = Number(m.text());
|
||||
if (minutes < 59) {
|
||||
m.text(minutes + 1);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m.text(0);
|
||||
}
|
||||
|
||||
var h = timerElement.find('.timer-hours');
|
||||
var hours = Number(h.text());
|
||||
h.text(hours + 1);
|
||||
},
|
||||
|
||||
update: function() {
|
||||
$.get('/api/timers/' + timerId + '/', function(data) {
|
||||
if (data && 'duration' in data) {
|
||||
clearInterval(runIntervalId);
|
||||
var duration = data.duration.split(/[\s:.]/)
|
||||
if (duration.length === 5) {
|
||||
duration[0] = parseInt(duration[0]) * 24 + parseInt(duration[1]);
|
||||
duration[1] = duration[2];
|
||||
duration[2] = duration[3];
|
||||
}
|
||||
timerElement.find('.timer-hours').text(parseInt(duration[0]));
|
||||
timerElement.find('.timer-minutes').text(parseInt(duration[1]));
|
||||
timerElement.find('.timer-seconds').text(parseInt(duration[2]));
|
||||
lastUpdate = new Date()
|
||||
runIntervalId = setInterval(Timer.tick, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return Timer;
|
||||
}(jQuery);
|
||||
|
||||
/* Baby Buddy Dashboard
|
||||
*
|
||||
* Provides a "watch" function to update the dashboard at one minute intervals
|
||||
* and/or on visibility state changes.
|
||||
*/
|
||||
BabyBuddy.Dashboard = function ($) {
|
||||
var runIntervalId = null;
|
||||
var dashboardElement = null;
|
||||
var hidden = null;
|
||||
|
||||
var Dashboard = {
|
||||
watch: function(element_id, refresh_rate) {
|
||||
dashboardElement = $('#' + element_id);
|
||||
|
||||
if (dashboardElement.length == 0) {
|
||||
console.error('Baby Buddy: Dashboard element not found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof document.hidden !== "undefined") {
|
||||
hidden = "hidden";
|
||||
}
|
||||
else if (typeof document.msHidden !== "undefined") {
|
||||
hidden = "msHidden";
|
||||
}
|
||||
else if (typeof document.webkitHidden !== "undefined") {
|
||||
hidden = "webkitHidden";
|
||||
}
|
||||
|
||||
if (typeof window.addEventListener === "undefined" || typeof document.hidden === "undefined") {
|
||||
if (refresh_rate) {
|
||||
runIntervalId = setInterval(this.update, refresh_rate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
window.addEventListener('focus', Dashboard.handleVisibilityChange, false);
|
||||
if (refresh_rate) {
|
||||
runIntervalId = setInterval(Dashboard.handleVisibilityChange, refresh_rate);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleVisibilityChange: function() {
|
||||
if (!document[hidden]) {
|
||||
Dashboard.update();
|
||||
}
|
||||
},
|
||||
|
||||
update: function() {
|
||||
// TODO: Someday maybe update in place?
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
return Dashboard;
|
||||
}(jQuery);
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue