forked from GithubBackups/healthchecks
Toggle integrations on/off on "My Checks" page.
This commit is contained in:
parent
0b3030311c
commit
83a2ff17e6
@ -240,6 +240,23 @@ class Channel(models.Model):
|
||||
email_verified = models.BooleanField(default=False)
|
||||
checks = models.ManyToManyField(Check)
|
||||
|
||||
def __str__(self):
|
||||
if self.kind == "email":
|
||||
return "Email to %s" % self.value
|
||||
elif self.kind == "sms":
|
||||
if self.sms_label:
|
||||
return "SMS to %s" % self.sms_label
|
||||
return "SMS to %s" % self.sms_number
|
||||
elif self.kind == "slack":
|
||||
return "Slack %s" % self.slack.channel
|
||||
elif self.kind == "telegram":
|
||||
return "Telegram %s" % self.telegram_name
|
||||
|
||||
return self.get_kind_display()
|
||||
|
||||
def icon_url(self):
|
||||
return settings.STATIC_URL + "img/integrations/%s.png" % self.kind
|
||||
|
||||
def assign_all_checks(self):
|
||||
checks = Check.objects.filter(user=self.user)
|
||||
self.checks.add(*checks)
|
||||
|
@ -15,7 +15,7 @@ class ChannelChecksTestCase(BaseTestCase):
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, "Assign Checks to Channel", status_code=200)
|
||||
self.assertContains(r, "Assign Checks to Integration", status_code=200)
|
||||
|
||||
def test_team_access_works(self):
|
||||
url = "/integrations/%s/checks/" % self.channel.code
|
||||
@ -24,7 +24,7 @@ class ChannelChecksTestCase(BaseTestCase):
|
||||
# should work.
|
||||
self.client.login(username="bob@example.org", password="password")
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, "Assign Checks to Channel", status_code=200)
|
||||
self.assertContains(r, "Assign Checks to Integration", status_code=200)
|
||||
|
||||
def test_it_checks_owner(self):
|
||||
# channel does not belong to mallory so this should come back
|
||||
|
@ -9,6 +9,7 @@ check_urls = [
|
||||
path('remove/', views.remove_check, name="hc-remove-check"),
|
||||
path('log/', views.log, name="hc-log"),
|
||||
path('last_ping/', views.ping_details, name="hc-last-ping"),
|
||||
path('channels/<uuid:channel_code>/enabled', views.switch_channel, name="hc-switch-channel"),
|
||||
path('pings/<int:n>/', views.ping_details, name="hc-ping-details"),
|
||||
]
|
||||
|
||||
|
@ -59,16 +59,20 @@ def my_checks(request):
|
||||
request.profile.sort = request.GET["sort"]
|
||||
request.profile.save()
|
||||
|
||||
checks = list(Check.objects.filter(user=request.team.user))
|
||||
checks = list(Check.objects.filter(user=request.team.user).prefetch_related("channel_set"))
|
||||
sortchecks(checks, request.profile.sort)
|
||||
|
||||
tags_statuses, num_down = _tags_statuses(checks)
|
||||
pairs = list(tags_statuses.items())
|
||||
pairs.sort(key=lambda pair: pair[0].lower())
|
||||
|
||||
channels = Channel.objects.filter(user=request.team.user)
|
||||
channels = list(channels.order_by("created"))
|
||||
|
||||
ctx = {
|
||||
"page": "checks",
|
||||
"checks": checks,
|
||||
"channels": channels,
|
||||
"num_down": num_down,
|
||||
"now": timezone.now(),
|
||||
"tags": pairs,
|
||||
@ -104,6 +108,25 @@ def status(request):
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def switch_channel(request, code, channel_code):
|
||||
check = get_object_or_404(Check, code=code)
|
||||
if check.user_id != request.team.user.id:
|
||||
return HttpResponseForbidden()
|
||||
|
||||
channel = get_object_or_404(Channel, code=channel_code)
|
||||
if channel.user_id != request.team.user.id:
|
||||
return HttpResponseForbidden()
|
||||
|
||||
if request.POST.get("state") == "on":
|
||||
channel.checks.add(check)
|
||||
else:
|
||||
channel.checks.remove(check)
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
def _welcome_check(request):
|
||||
check = None
|
||||
if "welcome_code" in request.session:
|
||||
|
@ -48,11 +48,15 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.navbar-text {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.page-checks .container-fluid {
|
||||
/* Fluid below 1320px, but max width capped to 1320px ... */
|
||||
max-width: 1320px;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 24px;
|
||||
}
|
||||
@ -86,4 +90,4 @@ pre {
|
||||
|
||||
.jumbotron p {
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,6 @@
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
table.table tr > th.th-name {
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#checks-table .indicator-cell {
|
||||
text-align: center;
|
||||
}
|
||||
@ -24,10 +19,6 @@ table.table tr > th.th-name {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
#checks-table th {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
#checks-table a.default {
|
||||
color: #333;
|
||||
}
|
||||
@ -41,26 +32,33 @@ table.table tr > th.th-name {
|
||||
border-top: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
#checks-table .my-checks-name {
|
||||
#checks-table .my-checks-name,
|
||||
#checks-table .integrations,
|
||||
#checks-table .timeout-grace,
|
||||
#checks-table .last-ping,
|
||||
#checks-table .last-ping-never {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
padding: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#checks-table tr:hover .my-checks-name {
|
||||
#checks-table tr:hover .my-checks-name,
|
||||
#checks-table tr:hover .integrations,
|
||||
#checks-table tr:hover .timeout-grace,
|
||||
#checks-table tr:hover .last-ping {
|
||||
border: 1px dotted #AAA;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#checks-table > tbody > tr > th.th-name,
|
||||
#checks-table > tbody > tr > th.th-integrations,
|
||||
#checks-table > tbody > tr > th.th-period,
|
||||
#checks-table > tbody > tr > th.th-last-ping {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
#checks-table .timeout-grace {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
padding: 6px;
|
||||
display: block;
|
||||
#checks-table .integrations img {
|
||||
padding: 10px 2px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.timeout-grace .cron-expression {
|
||||
@ -71,26 +69,6 @@ table.table tr > th.th-name {
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
#checks-table tr:hover .timeout-grace {
|
||||
border: 1px dotted #AAA;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#checks-table .last-ping {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
#checks-table .last-ping-never {
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
|
||||
#checks-table tr:hover .last-ping {
|
||||
border: 1px dotted #AAA;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checks-subline {
|
||||
color: #888;
|
||||
white-space: nowrap;
|
||||
@ -139,7 +117,9 @@ tr:hover .copy-link {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
#checks-table .url-cell {
|
||||
#checks-table .url-cell,
|
||||
#checks-table .integrations-cell,
|
||||
#checks-table .timeout-cell {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@ -147,7 +127,6 @@ tr:hover .copy-link {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
|
||||
.my-checks-url {
|
||||
font-family: "Lucida Console", Monaco, monospace;
|
||||
font-size: 11.7px;
|
||||
@ -156,3 +135,7 @@ tr:hover .copy-link {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.integrations-cell .off {
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
@ -56,4 +56,8 @@
|
||||
|
||||
.label-down {
|
||||
background-color: #d9534f;
|
||||
}
|
||||
}
|
||||
|
||||
#checks-list .base {
|
||||
color: #888;
|
||||
}
|
||||
|
@ -175,6 +175,19 @@ $(function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".integrations img").click(function() {
|
||||
var isOff = $(this).toggleClass("off").hasClass("off");
|
||||
var token = $('input[name=csrfmiddlewaretoken]').val();
|
||||
$.ajax({
|
||||
url: this.dataset.url,
|
||||
type: "post",
|
||||
headers: {"X-CSRFToken": token},
|
||||
data: {"state": isOff ? "off" : "on"}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".last-ping-cell").on("click", ".last-ping", function() {
|
||||
$("#ping-details-body").text("Updating...");
|
||||
$('#ping-details-modal').modal("show");
|
||||
@ -192,6 +205,7 @@ $(function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Filtering by tags
|
||||
$("#my-checks-tags button").click(function() {
|
||||
// .active has not been updated yet by bootstrap code,
|
||||
|
@ -49,7 +49,7 @@
|
||||
</head>
|
||||
<body class="page-{{ page }}">
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<div class="container{% if page == "checks" %}-fluid{% endif %}">
|
||||
<div class="navbar-header">
|
||||
<button
|
||||
type="button"
|
||||
@ -158,13 +158,13 @@
|
||||
</nav>
|
||||
|
||||
{% block containers %}
|
||||
<div class="container">
|
||||
<div class="container{% if page == "checks" %}-fluid{% endif %}">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="container{% if page == "checks" %}-fluid{% endif %}">
|
||||
<ul>
|
||||
<li>
|
||||
Powered by Healthchecks open-source project
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="update-timeout-title">Assign Checks to Channel</h4>
|
||||
<h4 class="update-timeout-title">Assign Checks to Integration</h4>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="channel" value="{{ channel.code }}" />
|
||||
|
@ -5,15 +5,6 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h1>
|
||||
{% if request.team == request.user.profile %}
|
||||
My Checks
|
||||
{% else %}
|
||||
{{ request.team.team_name }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
</div>
|
||||
{% if tags %}
|
||||
<div id="my-checks-tags" class="col-sm-12">
|
||||
{% for tag, status in tags %}
|
||||
@ -99,7 +90,7 @@
|
||||
class="form-control" />
|
||||
|
||||
<span class="help-block">
|
||||
Optionally, assign tags for easy filtering.
|
||||
Use tags for easy filtering and for status badges.
|
||||
Separate multiple tags with spaces.
|
||||
</span>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% load hc_extras %}
|
||||
<table id="checks-table" class="table hidden-xs">
|
||||
{% load hc_extras staticfiles %}
|
||||
<table id="checks-table" class="table hidden-xs hidden-sm">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="th-name">
|
||||
@ -18,6 +18,7 @@
|
||||
{% endif %}
|
||||
</th>
|
||||
<th>Ping URL</th>
|
||||
<th class="th-integrations">Integrations</th>
|
||||
<th class="th-period">
|
||||
Period <br />
|
||||
<span class="checks-subline">Grace</span>
|
||||
@ -69,8 +70,26 @@
|
||||
copy
|
||||
</button>
|
||||
</td>
|
||||
<td class="integrations-cell">
|
||||
{% if channels|length < 8 %}
|
||||
<div class="integrations">
|
||||
{% spaceless %}
|
||||
{% for channel in channels %}
|
||||
<img
|
||||
data-toggle="tooltip"
|
||||
data-url="{% url 'hc-switch-channel' check.code channel.code %}"
|
||||
title="{{ channel }}"
|
||||
src="{{ channel.icon_url }}"
|
||||
{% if channel in check.channel_set.all %}{% else %}class="off"{% endif %} />
|
||||
{% endfor %}
|
||||
{% endspaceless %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ check.channel_set.all|length }} of {{ channels|length }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="timeout-cell">
|
||||
<span
|
||||
<div
|
||||
data-url="{% url 'hc-update-timeout' check.code %}"
|
||||
data-kind="{{ check.kind }}"
|
||||
data-timeout="{{ check.timeout.total_seconds }}"
|
||||
@ -87,7 +106,7 @@
|
||||
<span class="checks-subline">
|
||||
{{ check.grace|hc_duration }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td id="lpd-{{ check.code}}" class="last-ping-cell">
|
||||
{% include "front/last_ping_cell.html" with check=check %}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% load hc_extras humanize %}
|
||||
|
||||
<ul id="checks-list" class="visible-xs">
|
||||
<ul id="checks-list" class="visible-xs visible-sm">
|
||||
{% for check in checks %}
|
||||
<li>
|
||||
<h2>
|
||||
@ -8,7 +8,9 @@
|
||||
{{ check.name|default:"unnamed" }}
|
||||
</span>
|
||||
|
||||
<code>{{ check.code }}</code>
|
||||
<code>
|
||||
<span class="base hidden-xs">{{ ping_endpoint }}</span>{{ check.code }}
|
||||
</code>
|
||||
</h2>
|
||||
|
||||
<a
|
||||
@ -42,7 +44,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if check.kind == "simple " %}
|
||||
{% if check.kind == "simple" %}
|
||||
<tr>
|
||||
<th>Period</th>
|
||||
<td>{{ check.timeout|hc_duration }}</td>
|
||||
|
Loading…
x
Reference in New Issue
Block a user