forked from GithubBackups/healthchecks
Better welcome page.
This commit is contained in:
parent
7b2e9ead5f
commit
7db4185267
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
__pycache__/
|
||||
local_settings.py
|
@ -10,6 +10,7 @@ from django.http import HttpResponseBadRequest
|
||||
from django.shortcuts import redirect, render
|
||||
|
||||
from hc.accounts.forms import EmailForm
|
||||
from hc.api.models import Check
|
||||
|
||||
|
||||
def _make_user(email):
|
||||
@ -20,6 +21,13 @@ def _make_user(email):
|
||||
return user
|
||||
|
||||
|
||||
def _associate_demo_check(request, user):
|
||||
if "welcome_code" in request.session:
|
||||
check = Check.objects.get(code=request.session["welcome_code"])
|
||||
check.user = user
|
||||
check.save()
|
||||
|
||||
|
||||
def login(request):
|
||||
if request.method == 'POST':
|
||||
form = EmailForm(request.POST)
|
||||
@ -29,6 +37,7 @@ def login(request):
|
||||
user = User.objects.get(email=email)
|
||||
except User.DoesNotExist:
|
||||
user = _make_user(email)
|
||||
_associate_demo_check(request, user)
|
||||
|
||||
# We don't want to reset passwords of staff users :-)
|
||||
if user.is_staff:
|
||||
|
20
hc/api/migrations/0005_auto_20150630_2021.py
Normal file
20
hc/api/migrations/0005_auto_20150630_2021.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('api', '0004_auto_20150616_1319'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='check',
|
||||
name='user',
|
||||
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
]
|
@ -11,7 +11,7 @@ DEFAULT_TIMEOUT = td(days=1)
|
||||
class Check(models.Model):
|
||||
name = models.CharField(max_length=100, blank=True)
|
||||
code = models.UUIDField(default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User)
|
||||
user = models.ForeignKey(User, blank=True, null=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
timeout = models.DurationField(default=DEFAULT_TIMEOUT)
|
||||
last_ping = models.DateTimeField(null=True, blank=True)
|
||||
|
@ -11,4 +11,5 @@ urlpatterns = [
|
||||
url(r'^pricing/$', views.pricing, name="hc-pricing"),
|
||||
url(r'^docs/$', views.docs, name="hc-docs"),
|
||||
url(r'^about/$', views.about, name="hc-about"),
|
||||
url(r'^welcome/timer/$', views.welcome_timer, name="hc-welcome-timer"),
|
||||
]
|
||||
|
@ -1,5 +1,8 @@
|
||||
import json
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponseForbidden
|
||||
from django.contrib.humanize.templatetags.humanize import naturaltime
|
||||
from django.http import HttpResponse, HttpResponseForbidden
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils import timezone
|
||||
|
||||
@ -8,7 +11,32 @@ from hc.front.forms import TimeoutForm, TIMEOUT_CHOICES
|
||||
|
||||
|
||||
def index(request):
|
||||
return render(request, "index.html", {"page": "welcome"})
|
||||
if "welcome_code" not in request.session:
|
||||
check = Check()
|
||||
check.save()
|
||||
code = str(check.code)
|
||||
request.session["welcome_code"] = code
|
||||
else:
|
||||
code = request.session["welcome_code"]
|
||||
check = Check.objects.get(code=code)
|
||||
|
||||
if check.alert_after:
|
||||
duration = check.alert_after - timezone.now()
|
||||
timer = int(duration.total_seconds())
|
||||
timer_formatted = "%dh %dm %ds" % (timer / 3600, (timer / 60) % 60, timer % 60)
|
||||
else:
|
||||
timer = 0
|
||||
timer_formatted = "Never"
|
||||
|
||||
ctx = {
|
||||
"page": "welcome",
|
||||
"check": check,
|
||||
"timer": timer,
|
||||
"timer_formatted": timer_formatted,
|
||||
"ping_url": "http://healthchecks.io/ping/%s/" % check.code
|
||||
}
|
||||
|
||||
return render(request, "index.html", ctx)
|
||||
|
||||
|
||||
def pricing(request):
|
||||
@ -23,6 +51,24 @@ def about(request):
|
||||
return render(request, "about.html", {"page": "about"})
|
||||
|
||||
|
||||
def welcome_timer(request):
|
||||
code = request.session["welcome_code"]
|
||||
|
||||
check = Check.objects.get(code=code)
|
||||
if check.last_ping and check.alert_after:
|
||||
duration = check.alert_after - timezone.now()
|
||||
response = {
|
||||
"last_ping": check.last_ping.isoformat(),
|
||||
"last_ping_human": naturaltime(check.last_ping),
|
||||
"timer": int(duration.total_seconds())
|
||||
}
|
||||
else:
|
||||
response = {"last_ping": None, "timer": None}
|
||||
|
||||
return HttpResponse(json.dumps(response),
|
||||
content_type="application/javascript")
|
||||
|
||||
|
||||
@login_required
|
||||
def checks(request):
|
||||
|
||||
|
@ -4,18 +4,20 @@ html, body {
|
||||
|
||||
#pitch {
|
||||
text-align: center;
|
||||
padding: 2em 0 3em 0;
|
||||
padding: 2em 0 2em 0;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
#pitch-subtitle {
|
||||
text-align: center;
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
color: #777;
|
||||
|
||||
}
|
||||
|
||||
#get-started {
|
||||
#pitch-url {
|
||||
text-align: center;
|
||||
font-family: monospace;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
#welcome-status, #get-started {
|
||||
margin-top: 4em;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,6 @@ $(function () {
|
||||
});
|
||||
|
||||
$(".timeout-edit-cancel").click(function() {
|
||||
console.log("aaa");
|
||||
$(this).parents("td").addClass("inactive");
|
||||
return false;
|
||||
});
|
||||
|
45
static/js/index.js
Normal file
45
static/js/index.js
Normal file
@ -0,0 +1,45 @@
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
var url = $("#pitch-url").text();
|
||||
var lastPing = null;
|
||||
var lastPingHuman = null;
|
||||
|
||||
$("#run-it").click(function() {
|
||||
$.get(url);
|
||||
});
|
||||
|
||||
function checkLastPing() {
|
||||
$.getJSON("/welcome/timer/", function(data) {
|
||||
if (data.last_ping != lastPing) {
|
||||
lastPing = data.last_ping;
|
||||
$("#timer").data("timer", data.timer);
|
||||
}
|
||||
|
||||
if (data.last_ping_human.indexOf("seconds ago") > 0)
|
||||
data.last_ping_human = "seconds ago";
|
||||
|
||||
if (data.last_ping_human != lastPingHuman) {
|
||||
lastPingHuman = data.last_ping_human;
|
||||
$("#last-ping").text(lastPingHuman);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateTimer() {
|
||||
var timer = parseInt($("#timer").data("timer"));
|
||||
if (timer == 0)
|
||||
return;
|
||||
|
||||
var s = timer % 60;
|
||||
var m = parseInt(timer / 60) % 60;
|
||||
var h = parseInt(timer / 3600);
|
||||
$("#timer").text(h + "h " + m + "m " + s + "s");
|
||||
|
||||
$("#timer").data("timer", timer - 1);
|
||||
}
|
||||
|
||||
setInterval(checkLastPing, 3000);
|
||||
setInterval(updateTimer, 1000);
|
||||
|
||||
});
|
@ -9,15 +9,22 @@
|
||||
Hello, my name is Pēteris Caune, I live in Riga, Latvia and do programming for living.
|
||||
You can contact me <a href="mailto:cuu508@gmail.com">via email</a>.
|
||||
</p>
|
||||
<p>
|
||||
Code is on
|
||||
<a href="https://github.com/healthchecks/healthchecks">GitHub</a>.
|
||||
</p>
|
||||
|
||||
<h3>Reliability Guarantees</h3>
|
||||
<p>
|
||||
Health Checks is currently at a very early stage as you can probably tell.
|
||||
</p>
|
||||
<p>
|
||||
The service is currently run on single $5 Digital Ocean box. The service
|
||||
can and will have ocassional outages. User data should be safe however,
|
||||
as we are doing regular database backups to Amazon S3.
|
||||
The service is currently run on single $5 Digital Ocean box.
|
||||
It can and will have ocassional outages. <!-- User data should be safe however,
|
||||
as we are doing regular database backups to Amazon S3. -->
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If all this does not sound very inspiring,
|
||||
there are also alternative services:
|
||||
|
@ -57,6 +57,6 @@
|
||||
|
||||
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
|
||||
<script src="{% static 'js/bootstrap.min.js' %}"></script>
|
||||
<script src="{% static 'js/checks.js' %}"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load humanize %}
|
||||
{% load humanize staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
@ -47,7 +47,7 @@
|
||||
</form>
|
||||
</td>
|
||||
<td class="url-cell">
|
||||
<code>https://healthchecks.io{% url 'hc-ping' check.code %}</code>
|
||||
<code>http://healthchecks.io{% url 'hc-ping' check.code %}</code>
|
||||
</td>
|
||||
<td class="timeout-cell inactive">
|
||||
<div class="timeout-dialog popover bottom">
|
||||
@ -116,4 +116,8 @@
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{% static 'js/checks.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
5
templates/front/snippets/bash.txt
Normal file
5
templates/front/snippets/bash.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# using curl:
|
||||
curl {{ ping_url }}
|
||||
|
||||
# using wget:
|
||||
wget {{ ping_url }} -O /dev/null
|
3
templates/front/snippets/browser.txt
Normal file
3
templates/front/snippets/browser.txt
Normal file
@ -0,0 +1,3 @@
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '{{ ping_url }}', true);
|
||||
xhr.send(null);
|
2
templates/front/snippets/crontab.txt
Normal file
2
templates/front/snippets/crontab.txt
Normal file
@ -0,0 +1,2 @@
|
||||
# m h dom mon dow command
|
||||
8 6 * * * /home/user/tasks/backup_all.sh && curl {{ ping_url }}
|
7
templates/front/snippets/python.txt
Normal file
7
templates/front/snippets/python.txt
Normal file
@ -0,0 +1,7 @@
|
||||
>>> # using urllib2:
|
||||
>>> import urllib2
|
||||
>>> urllib2.urlopen("{{ ping_url }}")
|
||||
|
||||
>>> # using requests:
|
||||
>>> import requests
|
||||
>>> requests.get("{{ ping_url }}")
|
@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load humanize staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
@ -9,47 +9,89 @@
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<p class="step-number">1</p>
|
||||
<p>
|
||||
Create a ping URL on healtchecks.io
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<p class="step-number">2</p>
|
||||
Add a single line at the bottom of your batch processing task:
|
||||
<div class="col-sm-12">
|
||||
<h2 id="pitch-subtitle">Here's an unique ping address for you:</h2>
|
||||
<div id="pitch-url">{{ ping_url }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active">
|
||||
<a href="#bash" aria-controls="home" role="tab" data-toggle="tab">Bash</a>
|
||||
<li class="active">
|
||||
<a href="#crontab" data-toggle="tab">Crontab</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#python" aria-controls="profile" role="tab" data-toggle="tab">Python</a>
|
||||
<li>
|
||||
<a href="#bash" data-toggle="tab">Bash</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#python" data-toggle="tab">Python</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#node" data-toggle="tab">Node.js</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#php" data-toggle="tab">PHP</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#browser" data-toggle="tab">Browser</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="bash">
|
||||
<pre>wget https://healthchecks.io/ping/b2012751-c542-4deb-b054-ff51322102b9/ -O /dev/null
|
||||
</pre>
|
||||
<div role="tabpanel" class="tab-pane active" id="crontab">
|
||||
<pre>{% include "front/snippets/crontab.txt" %}</pre>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="bash">
|
||||
<pre>{% include "front/snippets/bash.txt" %}</pre>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="python">
|
||||
<pre>
|
||||
>>> import urllib2
|
||||
>>> urllib2.urlopen("https://healthchecks.io/ping/b2012751-c542-4deb-b054-ff51322102b9/")
|
||||
|
||||
</pre>
|
||||
<pre>{% include "front/snippets/python.txt" %}</pre>
|
||||
</div>
|
||||
<div class="tab-pane" id="browser">
|
||||
<pre>{% include "front/snippets/browser.txt" %}</pre>
|
||||
<div class="welcome-browser-controls">
|
||||
<button id="run-it" class="btn btn-default">Run It!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<p class="step-number">3</p>
|
||||
Receive an email from healthchecks.io when the task has an issue
|
||||
|
||||
|
||||
<div id="welcome-status" class="col-sm-6">
|
||||
<h2>Status
|
||||
<small>{{ check.code }}</small>
|
||||
</h2>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Last ping</th>
|
||||
<th>Frequency</th>
|
||||
<th>Alert in</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="last-ping">
|
||||
{% if check.last_ping %}
|
||||
{{ check.last_ping|naturaltime }}
|
||||
{% else %}
|
||||
Never
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>1 day
|
||||
<span
|
||||
class="glyphicon glyphicon-question-sign"
|
||||
data-toggle="tooltip"
|
||||
title="Sign in to change frequency"></span>
|
||||
</td>
|
||||
<td id="timer" data-timer="{{ timer}}">
|
||||
{{ timer_formatted }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="get-started" class="col-sm-6 col-sm-offset-3">
|
||||
<h3>E-mail Address to Receive Notifications:</h3>
|
||||
<div id="get-started" class="col-sm-6">
|
||||
<h3>E-mail Address to Receive Alerts:</h3>
|
||||
<form action="{% url 'hc-login' %}" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
@ -75,4 +117,8 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{% static 'js/index.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user