Browse Source

In the checks list, indicate a started check with a progress spinner under the status icon (cc: #338)

pull/394/head
Pēteris Caune 4 years ago
parent
commit
149096811d
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
10 changed files with 75 additions and 15 deletions
  1. +2
    -2
      CHANGELOG.md
  2. +3
    -3
      hc/api/models.py
  3. +2
    -2
      hc/api/tests/test_check_model.py
  4. +2
    -2
      hc/front/templatetags/hc_extras.py
  5. +3
    -2
      hc/front/views.py
  6. +48
    -0
      static/css/base.css
  7. +6
    -0
      static/js/checks.js
  8. +1
    -1
      templates/front/details.html
  9. +1
    -1
      templates/front/log_status_text.html
  10. +7
    -2
      templates/front/my_checks_desktop.html

+ 2
- 2
CHANGELOG.md View File

@ -1,7 +1,7 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## Unreleased
## v1.16.0-dev - Unreleased
### Improvements ### Improvements
- Paused ping handling can be controlled via API (#376) - Paused ping handling can be controlled via API (#376)
@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file.
- The /api/v1/checks/ endpoint now accepts either UUID or `unique_key` (#370) - The /api/v1/checks/ endpoint now accepts either UUID or `unique_key` (#370)
- Added /api/v1/checks/uuid/flips/ endpoint (#349) - Added /api/v1/checks/uuid/flips/ endpoint (#349)
- In the cron expression dialog, show a human-friendly version of the expression - In the cron expression dialog, show a human-friendly version of the expression
- Indicate a started check with a progress spinner under status icon (#338)
### Bug Fixes ### Bug Fixes
- Removing Pager Team integration, project appears to be discontinued - Removing Pager Team integration, project appears to be discontinued


+ 3
- 3
hc/api/models.py View File

@ -119,7 +119,7 @@ class Check(models.Model):
if self.last_duration and self.last_duration < MAX_DELTA: if self.last_duration and self.last_duration < MAX_DELTA:
return self.last_duration return self.last_duration
def get_grace_start(self):
def get_grace_start(self, with_started=True):
""" Return the datetime when the grace period starts. """ Return the datetime when the grace period starts.
If the check is currently new, paused or down, return None. If the check is currently new, paused or down, return None.
@ -142,7 +142,7 @@ class Check(models.Model):
it = croniter(self.schedule, last_local) it = croniter(self.schedule, last_local)
result = it.next(datetime) result = it.next(datetime)
if self.last_start and self.status != "down":
if with_started and self.last_start and self.status != "down":
result = min(result, self.last_start) result = min(result, self.last_start)
if result != NEVER: if result != NEVER:
@ -175,7 +175,7 @@ class Check(models.Model):
if self.status in ("new", "paused", "down"): if self.status in ("new", "paused", "down"):
return self.status return self.status
grace_start = self.get_grace_start()
grace_start = self.get_grace_start(with_started=with_started)
grace_end = grace_start + self.grace grace_end = grace_start + self.grace
if now >= grace_end: if now >= grace_end:
return "down" return "down"


+ 2
- 2
hc/api/tests/test_check_model.py View File

@ -119,8 +119,8 @@ class CheckModelTestCase(BaseTestCase):
check.last_start = timezone.now() - timedelta(minutes=5) check.last_start = timezone.now() - timedelta(minutes=5)
self.assertEqual(check.get_status(with_started=True), "started") self.assertEqual(check.get_status(with_started=True), "started")
# Starting a check starts the grace period:
self.assertEqual(check.get_status(), "grace")
# A started check still is considered "up":
self.assertEqual(check.get_status(), "up")
def test_get_status_handles_up_then_started_and_expired(self): def test_get_status_handles_up_then_started_and_expired(self):
check = Check(status="up") check = Check(status="up")


+ 2
- 2
hc/front/templatetags/hc_extras.py View File

@ -87,7 +87,7 @@ def last_ping_key(check):
def not_down_key(check): def not_down_key(check):
return check.get_status(with_started=True) != "down"
return check.get_status() != "down"
@register.filter @register.filter
@ -126,7 +126,7 @@ def down_title(check):
""" """
s = "%s%s" % (check.name_then_code(), settings.SITE_NAME) s = "%s%s" % (check.name_then_code(), settings.SITE_NAME)
if check.get_status(with_started=True) == "down":
if check.get_status() == "down":
s = "DOWN – " + s s = "DOWN – " + s
return s return s


+ 3
- 2
hc/front/views.py View File

@ -207,8 +207,9 @@ def status(request, code):
details.append( details.append(
{ {
"code": str(check.code), "code": str(check.code),
"status": check.get_status(with_started=True),
"status": check.get_status(),
"last_ping": LAST_PING_TMPL.render(ctx), "last_ping": LAST_PING_TMPL.render(ctx),
"started": check.last_start is not None,
} }
) )
@ -594,7 +595,7 @@ def copy(request, code):
def status_single(request, code): def status_single(request, code):
check = _get_check_for_user(request, code) check = _get_check_for_user(request, code)
status = check.get_status(with_started=True)
status = check.get_status()
events = _get_events(check, 20) events = _get_events(check, 20)
updated = "1" updated = "1"
if len(events): if len(events):


+ 48
- 0
static/css/base.css View File

@ -168,3 +168,51 @@ pre {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.spinner {
display: none;
width: 24px;
height: 8px;
margin: 4px auto 0 auto;
}
.spinner.started {
display: block;
}
.spinner > div {
float: left;
width: 4px;
height: 4px;
margin: 0 2px;
background: #AAA;
border-radius: 2px;
animation-duration: 1s;
animation-name: spinner-pulse;
animation-iteration-count: infinite;
}
.spinner .d2 {
animation-delay: 0.15s;
}
.spinner .d3 {
animation-delay: 0.3s;
}
@keyframes spinner-pulse {
from {
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}

+ 6
- 0
static/js/checks.js View File

@ -199,6 +199,7 @@ $(function () {
// Schedule refresh to run every 3s when tab is visible and user // Schedule refresh to run every 3s when tab is visible and user
// is active, every 60s otherwise // is active, every 60s otherwise
var lastStatus = {}; var lastStatus = {};
var lastStarted = {};
var lastPing = {}; var lastPing = {};
var statusUrl = $("#checks-table").data("status-url"); var statusUrl = $("#checks-table").data("status-url");
function refreshStatus() { function refreshStatus() {
@ -213,6 +214,11 @@ $(function () {
$("#" + el.code + " span.status").attr("class", "status icon-" + el.status); $("#" + el.code + " span.status").attr("class", "status icon-" + el.status);
} }
if (lastStarted[el.code] != el.started) {
lastStarted[el.code] = el.started;
$("#" + el.code + " .spinner").toggleClass("started", el.started);
}
if (lastPing[el.code] != el.last_ping) { if (lastPing[el.code] != el.last_ping) {
lastPing[el.code] = el.last_ping; lastPing[el.code] = el.last_ping;
$("#lpd-" + el.code).html(el.last_ping); $("#lpd-" + el.code).html(el.last_ping);


+ 1
- 1
templates/front/details.html View File

@ -111,7 +111,7 @@
<table> <table>
<tr> <tr>
<td> <td>
<span id="log-status-icon" class="status icon-{{ check.get_status_with_started }}"></span>
<span id="log-status-icon" class="status icon-{{ check.get_status }}"></span>
</td> </td>
<td > <td >
<p id="log-status-text">{% include "front/log_status_text.html" %}</p> <p id="log-status-text">{% include "front/log_status_text.html" %}</p>


+ 1
- 1
templates/front/log_status_text.html View File

@ -1,5 +1,5 @@
{% load humanize %} {% load humanize %}
{% with check.get_status_with_started as status %}
{% with check.get_status as status %}
{% if status == "down" %} {% if status == "down" %}
This check is down. Last ping was {{ check.last_ping|naturaltime }}. This check is down. Last ping was {{ check.last_ping|naturaltime }}.
{% elif status == "up" %} {% elif status == "up" %}


+ 7
- 2
templates/front/my_checks_desktop.html View File

@ -1,4 +1,4 @@
{% load hc_extras %}
{% load hc_extras static %}
<table <table
id="checks-table" id="checks-table"
class="table" class="table"
@ -60,7 +60,12 @@
{% if check in hidden_checks %}style="display: none"{% endif %}> {% if check in hidden_checks %}style="display: none"{% endif %}>
<td class="indicator-cell"> <td class="indicator-cell">
<span class="status icon-{{ check.get_status_with_started }}" data-toggle="tooltip"></span>
<span class="status icon-{{ check.get_status }}" data-toggle="tooltip"></span>
<div class="spinner {% if check.last_start %}started{% endif %}">
<div class="d1"></div>
<div class="d2"></div>
<div class="d3"></div>
</div>
</td> </td>
<td> <td>
<div data-name="{{ check.name }}" <div data-name="{{ check.name }}"


Loading…
Cancel
Save