forked from GithubBackups/healthchecks
Add ability to set grace period
This commit is contained in:
parent
29e36fc14d
commit
0af1fb782a
@ -13,7 +13,7 @@ CREATE OR REPLACE FUNCTION update_alert_after()
|
||||
RETURNS trigger AS $update_alert_after$
|
||||
BEGIN
|
||||
IF NEW.last_ping IS NOT NULL THEN
|
||||
NEW.alert_after := NEW.last_ping + NEW.timeout + '1 hour';
|
||||
NEW.alert_after := NEW.last_ping + NEW.timeout + NEW.grace;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
|
20
hc/api/migrations/0006_check_grace.py
Normal file
20
hc/api/migrations/0006_check_grace.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import datetime
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('api', '0005_auto_20150630_2021'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='check',
|
||||
name='grace',
|
||||
field=models.DurationField(default=datetime.timedelta(0, 3600)),
|
||||
),
|
||||
]
|
@ -10,7 +10,13 @@ from hc.lib.emails import send
|
||||
|
||||
STATUSES = (("up", "Up"), ("down", "Down"), ("new", "New"))
|
||||
DEFAULT_TIMEOUT = td(days=1)
|
||||
TIMEOUT_CHOICES = (
|
||||
DEFAULT_GRACE = td(hours=1)
|
||||
|
||||
DURATION_CHOICES = (
|
||||
("1 minute", td(minutes=1)),
|
||||
("2 minutes", td(minutes=2)),
|
||||
("5 minutes", td(minutes=5)),
|
||||
("10 minutes", td(minutes=10)),
|
||||
("15 minutes", td(minutes=15)),
|
||||
("30 minutes", td(minutes=30)),
|
||||
("1 hour", td(hours=1)),
|
||||
@ -30,6 +36,7 @@ class Check(models.Model):
|
||||
user = models.ForeignKey(User, blank=True, null=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
timeout = models.DurationField(default=DEFAULT_TIMEOUT)
|
||||
grace = models.DurationField(default=DEFAULT_GRACE)
|
||||
last_ping = models.DateTimeField(null=True, blank=True)
|
||||
alert_after = models.DateTimeField(null=True, blank=True, editable=False)
|
||||
status = models.CharField(max_length=6, choices=STATUSES, default="new")
|
||||
@ -39,7 +46,7 @@ class Check(models.Model):
|
||||
|
||||
def send_alert(self):
|
||||
ctx = {
|
||||
"timeout_choices": TIMEOUT_CHOICES,
|
||||
"timeout_choices": DURATION_CHOICES,
|
||||
"check": self,
|
||||
"checks": self.user.check_set.order_by("created"),
|
||||
"now": timezone.now()
|
||||
|
@ -1,7 +1,6 @@
|
||||
from django import forms
|
||||
|
||||
from hc.api.models import TIMEOUT_CHOICES
|
||||
|
||||
|
||||
class TimeoutForm(forms.Form):
|
||||
timeout = forms.ChoiceField(choices=TIMEOUT_CHOICES)
|
||||
timeout = forms.IntegerField(min_value=60, max_value=604800)
|
||||
grace = forms.IntegerField(min_value=60, max_value=604800)
|
||||
|
@ -1,10 +1,12 @@
|
||||
from datetime import timedelta as td
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponseForbidden
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils import timezone
|
||||
|
||||
from hc.api.models import Check
|
||||
from hc.front.forms import TimeoutForm, TIMEOUT_CHOICES
|
||||
from hc.api.models import Check, DURATION_CHOICES
|
||||
from hc.front.forms import TimeoutForm
|
||||
|
||||
|
||||
def _welcome(request):
|
||||
@ -42,7 +44,7 @@ def _my_checks(request):
|
||||
ctx = {
|
||||
"checks": checks,
|
||||
"now": timezone.now(),
|
||||
"timeout_choices": TIMEOUT_CHOICES
|
||||
"duration_choices": DURATION_CHOICES
|
||||
}
|
||||
|
||||
return render(request, "front/my_checks.html", ctx)
|
||||
@ -100,7 +102,8 @@ def update_timeout(request, code):
|
||||
|
||||
form = TimeoutForm(request.POST)
|
||||
if form.is_valid():
|
||||
check.timeout = form.cleaned_data["timeout"]
|
||||
check.timeout = td(seconds=form.cleaned_data["timeout"])
|
||||
check.grace = td(seconds=form.cleaned_data["grace"])
|
||||
check.save()
|
||||
|
||||
return redirect("hc-index")
|
||||
|
4
static/css/nouislider.min.css
vendored
Normal file
4
static/css/nouislider.min.css
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/*! nouislider - 8.0.2 - 2015-07-06 13:22:09 */
|
||||
|
||||
|
||||
.noUi-target,.noUi-target *{-webkit-touch-callout:none;-webkit-user-select:none;-ms-touch-action:none;-ms-user-select:none;-moz-user-select:none;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-target{position:relative;direction:ltr}.noUi-base{width:100%;height:100%;position:relative;z-index:1}.noUi-origin{position:absolute;right:0;top:0;left:0;bottom:0}.noUi-handle{position:relative;z-index:1}.noUi-stacking .noUi-handle{z-index:10}.noUi-state-tap .noUi-origin{-webkit-transition:left .3s,top .3s;transition:left .3s,top .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-base{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.noUi-horizontal{height:18px}.noUi-horizontal .noUi-handle{width:34px;height:28px;left:-17px;top:-6px}.noUi-vertical{width:18px}.noUi-vertical .noUi-handle{width:28px;height:34px;left:-6px;top:-17px}.noUi-background{background:#FAFAFA;box-shadow:inset 0 1px 1px #f0f0f0}.noUi-connect{background:#3FB8AF;box-shadow:inset 0 0 3px rgba(51,51,51,.45);-webkit-transition:background 450ms;transition:background 450ms}.noUi-origin{border-radius:2px}.noUi-target{border-radius:4px;border:1px solid #D3D3D3;box-shadow:inset 0 1px 1px #F0F0F0,0 3px 6px -5px #BBB}.noUi-target.noUi-connect{box-shadow:inset 0 0 3px rgba(51,51,51,.45),0 3px 6px -5px #BBB}.noUi-dragable{cursor:w-resize}.noUi-vertical .noUi-dragable{cursor:n-resize}.noUi-handle{border:1px solid #D9D9D9;border-radius:3px;background:#FFF;cursor:default;box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #EBEBEB,0 3px 6px -3px #BBB}.noUi-active{box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #DDD,0 3px 6px -3px #BBB}.noUi-handle:after,.noUi-handle:before{content:"";display:block;position:absolute;height:14px;width:1px;background:#E8E7E6;left:14px;top:6px}.noUi-handle:after{left:17px}.noUi-vertical .noUi-handle:after,.noUi-vertical .noUi-handle:before{width:14px;height:1px;left:6px;top:14px}.noUi-vertical .noUi-handle:after{top:17px}[disabled] .noUi-connect,[disabled].noUi-connect{background:#B8B8B8}[disabled] .noUi-handle,[disabled].noUi-origin{cursor:not-allowed}.noUi-pips,.noUi-pips *{-moz-box-sizing:border-box;box-sizing:border-box}.noUi-pips{position:absolute;font:400 12px Arial;color:#999}.noUi-value{width:40px;position:absolute;text-align:center}.noUi-value-sub{color:#ccc;font-size:10px}.noUi-marker{position:absolute;background:#CCC}.noUi-marker-large,.noUi-marker-sub{background:#AAA}.noUi-pips-horizontal{padding:10px 0;height:50px;top:100%;left:0;width:100%}.noUi-value-horizontal{margin-left:-20px;padding-top:20px}.noUi-value-horizontal.noUi-value-sub{padding-top:15px}.noUi-marker-horizontal.noUi-marker{margin-left:-1px;width:2px;height:5px}.noUi-marker-horizontal.noUi-marker-sub{height:10px}.noUi-marker-horizontal.noUi-marker-large{height:15px}.noUi-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.noUi-value-vertical{width:15px;margin-left:20px;margin-top:-5px}.noUi-marker-vertical.noUi-marker{width:5px;height:2px;margin-top:-1px}.noUi-marker-vertical.noUi-marker-sub{width:10px}.noUi-marker-vertical.noUi-marker-large{width:15px}
|
98
static/css/nouislider.pips.css
Normal file
98
static/css/nouislider.pips.css
Normal file
@ -0,0 +1,98 @@
|
||||
|
||||
/* Base;
|
||||
*
|
||||
*/
|
||||
.noUi-pips,
|
||||
.noUi-pips * {
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.noUi-pips {
|
||||
position: absolute;
|
||||
font: 400 12px Arial;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* Values;
|
||||
*
|
||||
*/
|
||||
.noUi-value {
|
||||
width: 40px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.noUi-value-sub {
|
||||
color: #ccc;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* Markings;
|
||||
*
|
||||
*/
|
||||
.noUi-marker {
|
||||
position: absolute;
|
||||
background: #CCC;
|
||||
}
|
||||
.noUi-marker-sub {
|
||||
background: #AAA;
|
||||
}
|
||||
.noUi-marker-large {
|
||||
background: #AAA;
|
||||
}
|
||||
|
||||
/* Horizontal layout;
|
||||
*
|
||||
*/
|
||||
.noUi-pips-horizontal {
|
||||
padding: 10px 0;
|
||||
height: 50px;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.noUi-value-horizontal {
|
||||
margin-left: -20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.noUi-value-horizontal.noUi-value-sub {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.noUi-marker-horizontal.noUi-marker {
|
||||
margin-left: -1px;
|
||||
width: 2px;
|
||||
height: 5px;
|
||||
}
|
||||
.noUi-marker-horizontal.noUi-marker-sub {
|
||||
height: 10px;
|
||||
}
|
||||
.noUi-marker-horizontal.noUi-marker-large {
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
/* Vertical layout;
|
||||
*
|
||||
*/
|
||||
.noUi-pips-vertical {
|
||||
padding: 0 10px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
}
|
||||
.noUi-value-vertical {
|
||||
width: 15px;
|
||||
margin-left: 20px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.noUi-marker-vertical.noUi-marker {
|
||||
width: 5px;
|
||||
height: 2px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
.noUi-marker-vertical.noUi-marker-sub {
|
||||
width: 10px;
|
||||
}
|
||||
.noUi-marker-vertical.noUi-marker-large {
|
||||
width: 15px;
|
||||
}
|
@ -121,25 +121,16 @@ table.table tr > th.th-name {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.name-edit.inactive .input-name {
|
||||
.my-checks-name {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
transition: none;
|
||||
padding: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.name-edit.inactive .input-name:hover {
|
||||
.my-checks-name:hover {
|
||||
border: 1px dotted #AAA;
|
||||
}
|
||||
|
||||
.name-edit.inactive button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.name-edit button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.url-cell {
|
||||
font-size: small;
|
||||
}
|
||||
@ -153,21 +144,28 @@ td.inactive .popover {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
left: auto;
|
||||
margin-top: 32px;
|
||||
margin-top: 57px;
|
||||
margin-left: -77px;
|
||||
}
|
||||
|
||||
.timeout {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
padding: 6px;
|
||||
#checks-table > tbody > tr > th.th-frequency {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.timeout_grace {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
padding: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.timeout:hover {
|
||||
color: #337ab7;
|
||||
.timeout_grace:hover {
|
||||
border: 1px dotted #AAA;
|
||||
}
|
||||
|
||||
.checks-subline {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.check-menu {
|
||||
visibility: hidden;
|
||||
}
|
||||
@ -175,3 +173,41 @@ td.inactive .popover {
|
||||
tr:hover .check-menu {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
||||
.update-timeout-info {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.update-timeout-label {
|
||||
position: relative;
|
||||
right: 3px;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.update-timeout-value {
|
||||
font-size: 22px;
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
#frequency-slider {
|
||||
margin: 20px 50px 80px 50px;
|
||||
}
|
||||
|
||||
#frequency-slider.noUi-connect {
|
||||
background: #5cb85c;
|
||||
}
|
||||
|
||||
#grace-slider {
|
||||
margin: 20px 50px 60px 50px;
|
||||
}
|
||||
|
||||
#grace-slider.noUi-connect {
|
||||
background: #f0ad4e;
|
||||
}
|
||||
|
@ -1,40 +1,97 @@
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$(".name-edit input").click(function() {
|
||||
$form = $(this.parentNode);
|
||||
if (!$form.hasClass("inactive"))
|
||||
return;
|
||||
var secsToText = function(total) {
|
||||
total = Math.floor(total / 60);
|
||||
var m = total % 60; total = Math.floor(total / 60);
|
||||
var h = total % 24; total = Math.floor(total / 24);
|
||||
var d = total % 7; total = Math.floor(total / 7);
|
||||
var w = total;
|
||||
|
||||
// Click on all X buttons
|
||||
$(".name-edit:not(.inactive) .name-edit-cancel").click();
|
||||
var result = "";
|
||||
if (w) result += w + (w == 1 ? " week " : " weeks ");
|
||||
if (d) result += d + (d == 1 ? " day " : " days ");
|
||||
if (h) result += h + (h == 1 ? " hour " : " hours ");
|
||||
if (m) result += m + (m == 1 ? " minute " : " minutes ");
|
||||
|
||||
// Make this form editable and store its initial value
|
||||
$form
|
||||
.removeClass("inactive")
|
||||
.data("originalValue", this.value);
|
||||
return result;
|
||||
}
|
||||
|
||||
var frequencySlider = document.getElementById("frequency-slider");
|
||||
noUiSlider.create(frequencySlider, {
|
||||
start: [20],
|
||||
connect: "lower",
|
||||
range: {
|
||||
'min': [60, 60],
|
||||
'30%': [3600, 3600],
|
||||
'82.80%': [86400, 86400],
|
||||
'max': 604800
|
||||
},
|
||||
pips: {
|
||||
mode: 'values',
|
||||
values: [60, 1800, 3600, 43200, 86400, 604800],
|
||||
density: 5,
|
||||
format: {
|
||||
to: secsToText,
|
||||
from: function() {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(".name-edit-cancel").click(function(){
|
||||
var $form = $(this.parentNode);
|
||||
var v = $form.data("originalValue");
|
||||
frequencySlider.noUiSlider.on("update", function(a, b, value) {
|
||||
var rounded = Math.round(value);
|
||||
$("#frequency-slider-value").text(secsToText(rounded));
|
||||
$("#update-timeout-timeout").val(rounded);
|
||||
});
|
||||
|
||||
$form
|
||||
.addClass("inactive")
|
||||
.find(".input-name").val(v);
|
||||
|
||||
var graceSlider = document.getElementById("grace-slider");
|
||||
noUiSlider.create(graceSlider, {
|
||||
start: [20],
|
||||
connect: "lower",
|
||||
range: {
|
||||
'min': [60, 60],
|
||||
'30%': [3600, 3600],
|
||||
'82.80%': [86400, 86400],
|
||||
'max': 604800
|
||||
},
|
||||
pips: {
|
||||
mode: 'values',
|
||||
values: [60, 1800, 3600, 43200, 86400, 604800],
|
||||
density: 5,
|
||||
format: {
|
||||
to: secsToText,
|
||||
from: function() {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
graceSlider.noUiSlider.on("update", function(a, b, value) {
|
||||
var rounded = Math.round(value);
|
||||
$("#grace-slider-value").text(secsToText(rounded));
|
||||
$("#update-timeout-grace").val(rounded);
|
||||
});
|
||||
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$(".my-checks-name").click(function() {
|
||||
var $this = $(this);
|
||||
|
||||
$("#update-name-form").attr("action", $this.data("url"));
|
||||
$("#update-name-input").val($this.text());
|
||||
$('#update-name-modal').modal("show");
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".timeout").click(function() {
|
||||
$(".timeout-cell").addClass("inactive");
|
||||
$(".timeout_grace").click(function() {
|
||||
var $this = $(this);
|
||||
|
||||
$cell = $(this.parentNode);
|
||||
$cell.removeClass("inactive");
|
||||
});
|
||||
$("#update-timeout-form").attr("action", $this.data("url"));
|
||||
frequencySlider.noUiSlider.set($this.data("timeout"))
|
||||
graceSlider.noUiSlider.set($this.data("grace"))
|
||||
$('#update-timeout-modal').modal("show");
|
||||
|
||||
$(".timeout-edit-cancel").click(function() {
|
||||
$(this).parents("td").addClass("inactive");
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -48,4 +105,5 @@ $(function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
});
|
3
static/js/nouislider.min.js
vendored
Normal file
3
static/js/nouislider.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -9,6 +9,8 @@
|
||||
{% load staticfiles %}
|
||||
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,300,600' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}" type="text/css">
|
||||
<link rel="stylesheet" href="{% static 'css/nouislider.min.css' %}" type="text/css">
|
||||
<link rel="stylesheet" href="{% static 'css/nouislider.pips.css' %}" type="text/css">
|
||||
<link rel="stylesheet" href="{% static 'css/style.css' %}" type="text/css">
|
||||
<link rel="stylesheet" href="{% static 'css/pricing.css' %}" type="text/css">
|
||||
<link rel="stylesheet" href="{% static 'css/syntax.css' %}" type="text/css">
|
||||
|
@ -14,7 +14,10 @@
|
||||
<th></th>
|
||||
<th class="th-name">Name</th>
|
||||
<th>URL</th>
|
||||
<th>Frequency</th>
|
||||
<th class="th-frequency">
|
||||
Frequency <br />
|
||||
<span class="checks-subline">Grace</span>
|
||||
</th>
|
||||
<th>Last Ping</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@ -30,62 +33,31 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="name-cell">
|
||||
<form
|
||||
method="post"
|
||||
action="{% url 'hc-update-name' check.code %}"
|
||||
class="name-edit form-inline inactive">
|
||||
{% csrf_token %}
|
||||
<input
|
||||
name="name"
|
||||
type="text"
|
||||
value="{{ check.name }}"
|
||||
placeholder="unnamed"
|
||||
class="input-name form-control" />
|
||||
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</button>
|
||||
<button class="btn btn-default name-edit-cancel">
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
</button>
|
||||
</form>
|
||||
<span data-url="{% url 'hc-update-name' check.code %}"
|
||||
class="my-checks-name">{{ check.name }}</span>
|
||||
</td>
|
||||
<td class="url-cell">
|
||||
<code>{{ check.url }}</code>
|
||||
</td>
|
||||
<td class="timeout-cell inactive">
|
||||
<div class="timeout-dialog popover bottom">
|
||||
<div class="arrow"></div>
|
||||
<div class="popover-content">
|
||||
<form
|
||||
method="post"
|
||||
action="{% url 'hc-update-timeout' check.code %}"
|
||||
class="form-inline">
|
||||
{% csrf_token %}
|
||||
<select class="form-control" name="timeout">
|
||||
{% for label, value in timeout_choices %}
|
||||
{% if check.timeout == value %}
|
||||
<option selected>{{ label }}</option>
|
||||
{% else %}
|
||||
<option>{{ label }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</button>
|
||||
<button class="btn btn-default timeout-edit-cancel">
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<span class="timeout">
|
||||
{% for label, value in timeout_choices %}
|
||||
<span
|
||||
data-url="{% url 'hc-update-timeout' check.code %}"
|
||||
data-timeout="{{ check.timeout.total_seconds }}"
|
||||
data-grace="{{ check.grace.total_seconds }}"
|
||||
class="timeout_grace">
|
||||
{% for label, value in duration_choices %}
|
||||
{% if check.timeout == value %}
|
||||
{{ label }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<br />
|
||||
<span class="checks-subline">
|
||||
{% for label, value in duration_choices %}
|
||||
{% if check.grace == value %}
|
||||
{{ label }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
@ -135,11 +107,89 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div id="update-name-modal" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<form id="update-name-form" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</span></button>
|
||||
<h4 class="update-timeout-title">Update Name</h4>
|
||||
</div> <div class="modal-body">
|
||||
<p>Name:</p>
|
||||
<input
|
||||
id="update-name-input"
|
||||
name="name"
|
||||
type="text"
|
||||
value="---"
|
||||
placeholder="unnamed"
|
||||
class="input-name form-control" />
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-timeout-modal" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<form id="update-timeout-form" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="timeout" id="update-timeout-timeout" />
|
||||
<input type="hidden" name="grace" id="update-timeout-grace" />
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</span></button>
|
||||
<h4 class="update-timeout-title">Update Frequency and Grace Period</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="update-timeout-info text-center">
|
||||
<span
|
||||
class="update-timeout-label"
|
||||
data-toggle="tooltip"
|
||||
title="Expected time between pings.">
|
||||
Frequency
|
||||
</span>
|
||||
<span
|
||||
id="frequency-slider-value"
|
||||
class="update-timeout-value">
|
||||
1 day
|
||||
</span>
|
||||
</div>
|
||||
<div id="frequency-slider"></div>
|
||||
|
||||
<div class="update-timeout-info text-center">
|
||||
<span
|
||||
class="update-timeout-label"
|
||||
data-toggle="tooltip"
|
||||
title="When check is late, how much time to wait until alert is sent">
|
||||
Grace Period
|
||||
</span>
|
||||
<span
|
||||
id="grace-slider-value"
|
||||
class="update-timeout-value">
|
||||
1 day
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="grace-slider"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="remove-check-modal" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<form id="remove-check-form" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="code" class="remove-check-code" />
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</span></button>
|
||||
@ -166,5 +216,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{% static 'js/moment.min.js' %}"></script>
|
||||
<script src="{% static 'js/nouislider.min.js' %}"></script>
|
||||
<script src="{% static 'js/checks.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user