Browse Source

Show "Badges" and "Settings" in top navigation. Fixes #234

pull/241/head
Pēteris Caune 6 years ago
parent
commit
178b0ff95c
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
20 changed files with 382 additions and 186 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +2
    -2
      hc/accounts/tests/test_badges.py
  3. +22
    -3
      hc/accounts/tests/test_project.py
  4. +0
    -1
      hc/accounts/urls.py
  5. +18
    -37
      hc/accounts/views.py
  6. +1
    -0
      hc/front/urls.py
  7. +37
    -0
      hc/front/views.py
  8. +22
    -0
      static/css/base.css
  9. +0
    -93
      templates/accounts/badges.html
  10. +0
    -1
      templates/accounts/billing.html
  11. +0
    -1
      templates/accounts/notifications.html
  12. +0
    -1
      templates/accounts/profile.html
  13. +8
    -3
      templates/accounts/project.html
  14. +8
    -37
      templates/base.html
  15. +169
    -0
      templates/base_project.html
  16. +86
    -0
      templates/front/badges.html
  17. +1
    -1
      templates/front/channels.html
  18. +1
    -1
      templates/front/details.html
  19. +1
    -1
      templates/front/log.html
  20. +5
    -4
      templates/front/my_checks.html

+ 1
- 0
CHANGELOG.md View File

@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
### Improvements
- Add the EMAIL_USE_VERIFICATION configuration setting (#232)
- Show "Badges" and "Settings" in top navigation (#234)
## 1.6.0 - 2019-04-01


+ 2
- 2
hc/accounts/tests/test_badges.py View File

@ -9,7 +9,7 @@ class BadgesTestCase(BaseTestCase):
Check.objects.create(project=self.bobs_project, tags="bobs-tag")
self.client.login(username="[email protected]", password="password")
r = self.client.get("/accounts/profile/badges/")
r = self.client.get("/projects/%s/badges/" % self.project.code)
self.assertContains(r, "foo.svg")
self.assertContains(r, "a-B_1.svg")
@ -27,6 +27,6 @@ class BadgesTestCase(BaseTestCase):
self.project.save()
self.client.login(username="[email protected]", password="password")
r = self.client.get("/accounts/profile/badges/")
r = self.client.get("/projects/%s/badges/" % self.project.code)
self.assertContains(r, "badge/alices-badge-key/")
self.assertContains(r, "badge/alices-badge-key/")

+ 22
- 3
hc/accounts/tests/test_project.py View File

@ -5,17 +5,22 @@ from hc.test import BaseTestCase
from hc.accounts.models import Member
class ProfileTestCase(BaseTestCase):
class ProjectTestCase(BaseTestCase):
def setUp(self):
super(ProfileTestCase, self).setUp()
super(ProjectTestCase, self).setUp()
self.url = "/projects/%s/settings/" % self.project.code
def test_it_checks_access(self):
self.client.login(username="bob@example.org", password="password")
self.client.login(username="charlie@example.org", password="password")
r = self.client.get(self.url)
self.assertEqual(r.status_code, 404)
def test_it_allows_team_access(self):
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertContains(r, "Change Project Name")
def test_it_shows_api_keys(self):
self.project.api_key_readonly = "R" * 32
self.project.save()
@ -78,6 +83,13 @@ class ProfileTestCase(BaseTestCase):
" Alice's Project on %s" % settings.SITE_NAME)
self.assertEqual(mail.outbox[0].subject, subj)
def test_it_requires_owner_to_add_team_member(self):
self.client.login(username="[email protected]", password="password")
form = {"invite_team_member": "1", "email": "[email protected]"}
r = self.client.post(self.url, form)
self.assertEqual(r.status_code, 403)
def test_it_checks_team_size(self):
self.profile.team_limit = 0
self.profile.save()
@ -100,6 +112,13 @@ class ProfileTestCase(BaseTestCase):
self.bobs_profile.refresh_from_db()
self.assertEqual(self.bobs_profile.current_project, None)
def test_it_requires_owner_to_remove_team_member(self):
self.client.login(username="[email protected]", password="password")
form = {"remove_team_member": "1", "email": "[email protected]"}
r = self.client.post(self.url, form)
self.assertEqual(r.status_code, 403)
def test_it_checks_membership_when_removing_team_member(self):
self.client.login(username="[email protected]", password="password")


+ 0
- 1
hc/accounts/urls.py View File

@ -16,7 +16,6 @@ urlpatterns = [
path('profile/', views.profile, name="hc-profile"),
path('profile/notifications/', views.notifications, name="hc-notifications"),
path('profile/badges/', views.badges, name="hc-badges"),
path('close/', views.close, name="hc-close"),
path('unsubscribe_reports/<str:username>/',


+ 18
- 37
hc/accounts/views.py View File

@ -1,6 +1,5 @@
from datetime import timedelta as td
import uuid
import re
from django.conf import settings
from django.contrib import messages
@ -10,7 +9,8 @@ from django.contrib.auth import authenticate
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core import signing
from django.http import HttpResponseForbidden, HttpResponseBadRequest
from django.http import (HttpResponseForbidden, HttpResponseBadRequest,
HttpResponseNotFound)
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.timezone import now
from django.urls import resolve, Resolver404
@ -23,7 +23,6 @@ from hc.accounts.forms import (ChangeEmailForm, EmailPasswordForm,
ExistingEmailForm)
from hc.accounts.models import Profile, Project, Member
from hc.api.models import Channel, Check
from hc.lib.badges import get_badge_url
from hc.payments.models import Subscription
NEXT_WHITELIST = ("hc-checks",
@ -238,12 +237,22 @@ def add_project(request):
@login_required
def project(request, code):
project = get_object_or_404(Project, code=code, owner=request.user)
if request.user.is_superuser:
q = Project.objects
else:
q = request.profile.projects()
try:
project = q.get(code=code)
except Project.DoesNotExist:
return HttpResponseNotFound()
is_owner = project.owner_id == request.user.id
ctx = {
"page": "project",
"project": project,
"show_api_keys": False,
"is_owner": is_owner,
"show_api_keys": "show_api_keys" in request.GET,
"project_name_status": "default",
"api_status": "default",
"team_status": "default"
@ -267,7 +276,7 @@ def project(request, code):
elif "show_api_keys" in request.POST:
ctx["show_api_keys"] = True
elif "invite_team_member" in request.POST:
if not project.can_invite():
if not is_owner or not project.can_invite():
return HttpResponseForbidden()
form = InviteTeamMemberForm(request.POST)
@ -284,6 +293,9 @@ def project(request, code):
ctx["team_status"] = "success"
elif "remove_team_member" in request.POST:
if not is_owner:
return HttpResponseForbidden()
form = RemoveTeamMemberForm(request.POST)
if form.is_valid():
q = User.objects
@ -354,37 +366,6 @@ def notifications(request):
return render(request, "accounts/notifications.html", ctx)
@login_required
def badges(request):
badge_sets = []
for project in request.profile.projects():
tags = set()
for check in Check.objects.filter(project=project):
tags.update(check.tags_list())
sorted_tags = sorted(tags, key=lambda s: s.lower())
sorted_tags.append("*") # For the "overall status" badge
urls = []
for tag in sorted_tags:
if not re.match("^[\w-]+$", tag) and tag != "*":
continue
urls.append({
"svg": get_badge_url(project.badge_key, tag),
"json": get_badge_url(project.badge_key, tag, format="json"),
})
badge_sets.append({"project": project, "urls": urls})
ctx = {
"page": "profile",
"badges": badge_sets
}
return render(request, "accounts/badges.html", ctx)
@login_required
def set_password(request, token):
if not request.profile.check_token(token, "set-password"):


+ 1
- 0
hc/front/urls.py View File

@ -50,6 +50,7 @@ channel_urls = [
urlpatterns = [
path('', views.index, name="hc-index"),
path('projects/<uuid:code>/checks/', views.my_checks, name="hc-checks"),
path('projects/<uuid:code>/badges/', views.badges, name="hc-badges"),
path('projects/<uuid:code>/checks/add/', views.add_check, name="hc-add-check"),
path('checks/cron_preview/', views.cron_preview),
path('projects/<uuid:code>/checks/status/', views.status, name="hc-status"),


+ 37
- 0
hc/front/views.py View File

@ -1,5 +1,6 @@
from datetime import datetime, timedelta as td
import json
import re
from urllib.parse import urlencode
from croniter import croniter
@ -29,6 +30,7 @@ from hc.front.schemas import telegram_callback
from hc.front.templatetags.hc_extras import (num_down_title, down_title,
sortchecks)
from hc.lib import jsonschema
from hc.lib.badges import get_badge_url
import pytz
from pytz.exceptions import UnknownTimeZoneError
import requests
@ -441,6 +443,7 @@ def log(request, code):
limit = check.project.owner_profile.ping_log_limit
ctx = {
"project": check.project,
"check": check,
"events": _get_events(check, limit),
"limit": limit,
@ -459,6 +462,7 @@ def details(request, code):
ctx = {
"page": "details",
"project": check.project,
"check": check,
"channels": channels,
"timezones": pytz.all_timezones
@ -515,6 +519,38 @@ def status_single(request, code):
return JsonResponse(doc)
@login_required
def badges(request, code):
project = _get_project_for_user(request, code)
tags = set()
for check in Check.objects.filter(project=project):
tags.update(check.tags_list())
sorted_tags = sorted(tags, key=lambda s: s.lower())
sorted_tags.append("*") # For the "overall status" badge
urls = []
for tag in sorted_tags:
if not re.match("^[\w-]+$", tag) and tag != "*":
continue
urls.append({
"tag": tag,
"svg": get_badge_url(project.badge_key, tag),
"json": get_badge_url(project.badge_key, tag, format="json"),
})
ctx = {
"have_tags": len(urls) > 1,
"page": "badges",
"project": project,
"badges": urls
}
return render(request, "front/badges.html", ctx)
@login_required
def channels(request):
if request.method == "POST":
@ -547,6 +583,7 @@ def channels(request):
ctx = {
"page": "channels",
"project": request.project,
"profile": request.project.owner_profile,
"channels": channels,
"enable_pushbullet": settings.PUSHBULLET_CLIENT_ID is not None,


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

@ -41,6 +41,10 @@ body {
font-size: small;
}
#global-links > li > a {
font-size: small;
}
@media (min-width: 768px) {
.navbar-default .navbar-nav > li.active > a, .navbar-default .navbar-nav > li > a:hover {
border-bottom: 5px solid #eee;
@ -48,6 +52,11 @@ body {
}
}
.navbar-default .navbar-brand, .navbar-default .navbar-brand:hover {
color: #333;
font-weight: bold;
}
.navbar-text {
font-size: small;
}
@ -115,3 +124,16 @@ pre {
.badge-down {
background-color: #d9534f;
}
.dropdown-menu > li.project-item a {
min-width: 200px;
padding: 6px 20px 3px 20px;
}
.project-item .name {
display: inline-block;
max-width: 130px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

+ 0
- 93
templates/accounts/badges.html View File

@ -1,93 +0,0 @@
{% extends "base.html" %}
{% load compress static hc_extras %}
{% block title %}Account Settings - {% site_name %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-12">
<h1 class="settings-title">Settings <small>{{ request.user.email }}</small></h1>
</div>
</div>
<div class="row">
<div class="col-sm-2">
<ul class="nav nav-pills nav-stacked">
<li><a href="{% url 'hc-profile' %}">Account</a></li>
{% if show_pricing %}
<li><a href="{% url 'hc-billing' %}">Billing</a></li>
{% endif %}
<li><a href="{% url 'hc-notifications' %}">Email Reports</a></li>
<li class="active"><a href="{% url 'hc-badges' %}">Badges</a></li>
</ul>
</div>
<div class="col-sm-10">
<div class="panel panel-default">
<div class="panel-body settings-block">
<h2 class="settings-title">Status Badges</h2>
<p id="badges-description">
{% site_name %} provides status badges for each of the tags
you have used. Additionally, the "{% site_name %}"
badge shows the overall status of all checks in a
project. The badges have public, but hard-to-guess
URLs. You can use them in your READMEs,
dashboards or status pages.
</p>
<div id="b-format" class="btn-group" data-toggle="buttons">
<label id="show-svg" class="btn btn-default active">
<input type="radio" autocomplete="off" checked> SVG
</label>
<label id="show-json" class="btn btn-default">
<input type="radio" autocomplete="off"> JSON
</label>
</div>
<table id="badges-svg" class="badges table">
{% for badge_set in badges %}
<tr>
<th colspan="2">{{ badge_set.project }}</th>
</tr>
{% for urldict in badge_set.urls %}
<tr>
<td>
<img src="{{ urldict.svg }}" alt="" />
</td>
<td class="svg-url">
<code>{{ urldict.svg }}</code>
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
<table id="badges-json" class="badges table">
{% for badge_set in badges %}
<tr>
<th colspan="2">{{ badge_set.project }}</th>
</tr>
{% for urldict in badge_set.urls %}
<tr>
<td class="json-response" data-url="{{ urldict.json }}">
</td>
<td class="json-url">
<code>{{ urldict.json }}</code>
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
{% compress js %}
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/badges.js' %}"></script>
{% endcompress %}
{% endblock %}

+ 0
- 1
templates/accounts/billing.html View File

@ -19,7 +19,6 @@
<li><a href="{% url 'hc-profile' %}">Account</a></li>
<li class="active"><a href="{% url 'hc-billing' %}">Billing</a></li>
<li><a href="{% url 'hc-notifications' %}">Email Reports</a></li>
<li><a href="{% url 'hc-badges' %}">Badges</a></li>
</ul>
</div>


+ 0
- 1
templates/accounts/notifications.html View File

@ -21,7 +21,6 @@
<li><a href="{% url 'hc-billing' %}">Billing</a></li>
{% endif %}
<li class="active"><a href="{% url 'hc-notifications' %}">Email Reports</a></li>
<li><a href="{% url 'hc-badges' %}">Badges</a></li>
</ul>
</div>


+ 0
- 1
templates/accounts/profile.html View File

@ -29,7 +29,6 @@
<li><a href="{% url 'hc-billing' %}">Billing</a></li>
{% endif %}
<li><a href="{% url 'hc-notifications' %}">Email Reports</a></li>
<li><a href="{% url 'hc-badges' %}">Badges</a></li>
</ul>
</div>


+ 8
- 3
templates/accounts/project.html View File

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base_project.html" %}
{% load compress static hc_extras %}
{% block title %}Project Settings - {{ project }}{% endblock %}
@ -7,7 +7,6 @@
{% block content %}
<div class="row">
<div class="col-sm-9 col-md-6">
<h1 class="settings-title">Project Settings</h1>
{% for message in messages %}
<p class="alert alert-{{ message.tags }}">{{ message }}</p>
{% endfor %}
@ -103,10 +102,12 @@
<td>{{ member.user.email }} </td>
<td>Member</td>
<td>
{% if is_owner %}
<a
href="#"
data-email="{{ member.user.email }}"
class="pull-right member-remove">Remove</a>
{% endif %}
</td>
</tr>
{% endfor %}
@ -121,7 +122,8 @@
<br />
{% if project.can_invite %}
{% if is_owner %}
{% if project.can_invite%}
<a
href="#"
class="btn btn-primary pull-right"
@ -134,6 +136,7 @@
<a href="{% url 'hc-pricing' %}">upgrade your account!</a>
</div>
{% endif %}
{% endif %}
</div>
{% if team_member_invited %}
@ -149,6 +152,7 @@
{% endif %}
</div>
{% if is_owner %}
<div class="panel panel-default">
<div class="panel-body settings-block">
{% csrf_token %}
@ -163,6 +167,7 @@
</form>
</div>
</div>
{% endif %}
</div>
</div>


+ 8
- 37
templates/base.html View File

@ -88,18 +88,7 @@
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul id="nav-main-sections" class="nav navbar-nav">
{% if request.user.is_authenticated and request.profile.current_project %}
<li {% if page == 'checks' %} class="active" {% endif %}>
<a href="{% url 'hc-checks' request.profile.current_project.code %}">Checks</a>
</li>
<li {% if page == 'channels' %} class="active" {% endif %}>
<a href="{% url 'hc-channels' %}">Integrations</a>
</li>
{% endif %}
<ul id="global-links" class="nav navbar-nav navbar-right">
{% if show_pricing %}
<li {% if page == 'pricing' %} class="active" {% endif %}>
<a href="{% url 'hc-pricing' %}">Pricing</a>
@ -110,29 +99,18 @@
<a href="{% url 'hc-docs' %}">Docs</a>
</li>
</ul>
{% if request.user.is_authenticated %}
<ul class="nav navbar-nav navbar-right">
{% if request.user.is_authenticated %}
<li class="dropdown">
<a id="nav-email" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button">
{% if check %}
{{ check.project }}
{% elif request.profile.current_project %}
{{ request.profile.current_project }}
{% else %}
{{ request.user.email }}
{% endif %}
Account
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li class="dropdown-header">Projects</li>
{% for project in request.profile.annotated_projects %}
<li class="dropdown-header">{{ project }}</li>
<li>
<a href="{% url 'hc-checks' project.code %}">
Checks
{{ project }}
{% if project.n_down %}
<span class="badge badge-down pull-right">
{{ project.n_down }}
@ -140,24 +118,17 @@
{% endif %}
</a>
</li>
{% if project.owner_id == request.user.id %}
<li>
<a href="{% url 'hc-project-settings' project.code %}">Project Settings</a>
</li>
{% endif %}
<li role="separator" class="divider"></li>
{% endfor %}
<li role="separator" class="divider"></li>
<li><a href="{% url 'hc-profile' %}">Account Settings</a></li>
<li><a href="{% url 'hc-logout' %}">Log Out</a></li>
</ul>
</li>
</ul>
{% elif page != "login" %}
<ul class="nav navbar-nav navbar-right">
{% elif page != "login" %}
<li><a href="{% url 'hc-login' %}">Sign In</a></li>
{% endif %}
</ul>
{% endif %}
{% if show_search %}
<form class="navbar-form navbar-right hidden-xs hidden-sm">


+ 169
- 0
templates/base_project.html View File

@ -0,0 +1,169 @@
<!DOCTYPE html>{% load compress staticfiles hc_extras %}
<html lang="en">
<head>
<meta charset="utf-8">
<title>{% block title %}{% site_name %} - Monitor Cron Jobs. Get Notified When Your Cron Jobs Fail{% endblock %}</title>
{% block description %}
<meta name="description" content="Monitor and Get Notified When Your Cron Jobs Fail. Free alternative to Cronitor and Dead Man's Snitch.">
{% endblock %}
{% block keywords %}
<meta name="keywords" content="healthchecks, monitor cron jobs, cron monitoring, cron job syntax, health checks, crontab cheat sheet, crontab monitoring, cronjob monitoring, cron dashboard">
{% endblock %}
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-title" content="{% site_name %}">
<meta name="application-name" content="{% site_name %}">
<link rel="icon" type="image/x-icon" href="{% static 'img/favicon.ico' %}">
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'img/apple-touch-180.png' %}">
{% compress css %}
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/icomoon.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/bootstrap-select.min.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/snippet-copy.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/base.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/docs.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/docs_cron.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/welcome.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/my_checks.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/my_checks_desktop.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">
<link rel="stylesheet" href="{% static 'css/channels.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/channel_checks.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/details.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/log.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/add_pushover.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/add_webhook.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/settings.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/ping_details.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/profile.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/checkbox.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/radio.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/billing.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/login.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/projects.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/add_project_modal.css' %}" type="text/css">
{% endcompress %}
</head>
<body class="page-{{ page }}">
{% debug_warning %}
<nav class="navbar navbar-default">
<div class="container{% if page == "checks" or page == "details" %}-fluid{% endif %}">
<div class="navbar-header">
<button
type="button"
class="navbar-toggle collapsed"
data-toggle="collapse"
data-target="#navbar"
aria-expanded="false"
aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
{{ project }}
<span class="caret"></span>
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul id="nav-main-sections" class="nav navbar-nav">
{% if project %}
<li {% if page == 'checks' %} class="active" {% endif %}>
<a href="{% url 'hc-checks' project.code %}">Checks</a>
</li>
<li {% if page == 'channels' %} class="active" {% endif %}>
<a href="{% url 'hc-channels' %}">Integrations</a>
</li>
<li {% if page == 'badges' %} class="active" {% endif %}>
<a href="{% url 'hc-badges' project.code %}">Badges</a>
</li>
<li {% if page == 'project' %} class="active" {% endif %}>
<a href="{% url 'hc-project-settings' project.code %}">Settings</a>
</li>
{% endif %}
</ul>
{% if request.user.is_authenticated %}
<ul id="global-links" class="nav navbar-nav navbar-right">
{% if show_pricing %}
<li {% if page == 'pricing' %} class="active" {% endif %}>
<a href="{% url 'hc-pricing' %}">Pricing</a>
</li>
{% endif %}
<li {% if page == 'docs' %} class="active" {% endif %}>
<a href="{% url 'hc-docs' %}">Docs</a>
</li>
<li class="dropdown">
<a id="nav-email" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button">
Account
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li class="dropdown-header">Projects</li>
{% for project in request.profile.annotated_projects %}
<li class="project-item">
<a href="{% url 'hc-checks' project.code %}">
<span class="name">{{ project }}</span>
{% if project.n_down %}
<span class="badge badge-down pull-right">
{{ project.n_down }}
</span>
{% endif %}
</a>
</li>
{% endfor %}
<li role="separator" class="divider"></li>
<li><a href="{% url 'hc-profile' %}">Account Settings</a></li>
<li><a href="{% url 'hc-logout' %}">Log Out</a></li>
</ul>
</li>
</ul>
{% elif page != "login" %}
<ul class="nav navbar-nav navbar-right">
<li><a href="{% url 'hc-login' %}">Sign In</a></li>
</ul>
{% endif %}
</div>
</div>
</nav>
{% block containers %}
<div class="container{% if page == "checks" or page == "details" %}-fluid{% endif %}">
{% block content %}{% endblock %}
</div>
{% endblock %}
<footer class="footer">
<div class="container{% if page == "checks" or page == "details" %}-fluid{% endif %}">
<ul>
<li>
Powered by Healthchecks open-source project
(<a href="https://github.com/healthchecks/healthchecks">github</a>,
<a href="https://healthchecks.io">healthchecks.io</a>)
</li>
</ul>
</div>
</footer>
{% block scripts %}
{% compress js %}
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
{% endcompress %}
{% endblock %}
</body>
</html>

+ 86
- 0
templates/front/badges.html View File

@ -0,0 +1,86 @@
{% extends "base_project.html" %}
{% load compress static hc_extras %}
{% block title %}Account Settings - {% site_name %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-10">
<h1>Status Badges</h1>
<p id="badges-description">
{% site_name %} provides status badges for each of the tags
you have used. Additionally, the "{% site_name %}"
badge shows the overall status of all checks in a
project. The badges have public, but hard-to-guess
URLs. You can use them in your READMEs,
dashboards or status pages.
</p>
<div id="b-format" class="btn-group" data-toggle="buttons">
<label id="show-svg" class="btn btn-default active">
<input type="radio" autocomplete="off" checked> SVG
</label>
<label id="show-json" class="btn btn-default">
<input type="radio" autocomplete="off"> JSON
</label>
</div>
<table id="badges-svg" class="badges table">
{% if have_tags %}
<tr>
<th colspan="2">Tags</th>
</tr>
{% endif %}
{% for urldict in badges %}
{% if urldict.tag == "*" %}
<tr>
<th colspan="2">Overall Status</th>
</tr>
{% endif %}
<tr>
<td>
<img src="{{ urldict.svg }}" alt="" />
</td>
<td class="svg-url">
<code>{{ urldict.svg }}</code>
</td>
</tr>
{% endfor %}
</table>
<table id="badges-json" class="badges table">
{% if have_tags %}
<tr>
<th colspan="2">Tags</th>
</tr>
{% endif %}
{% for urldict in badges %}
{% if urldict.tag == "*" %}
<tr>
<th colspan="2">Overall Status</th>
</tr>
{% endif %}
<tr>
<td class="json-response" data-url="{{ urldict.json }}">
</td>
<td class="json-url">
<code>{{ urldict.json }}</code>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}
{% block scripts %}
{% compress js %}
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/badges.js' %}"></script>
{% endcompress %}
{% endblock %}

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

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base_project.html" %}
{% load compress humanize static hc_extras %}
{% block title %}Integrations - {% site_name %}{% endblock %}


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

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base_project.html" %}
{% load compress humanize static hc_extras %}
{% block title %}{{ check|down_title }}{% endblock %}


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

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base_project.html" %}
{% load compress humanize staticfiles hc_extras %}
{% block title %}My Checks - {% site_name %}{% endblock %}


+ 5
- 4
templates/front/my_checks.html View File

@ -1,17 +1,18 @@
{% extends "base.html" %}
{% extends "base_project.html" %}
{% load compress static hc_extras %}
{% block title %}{{ num_down|num_down_title }}{% endblock %}
{% block content %}
<div class="row">
{% if tags %}
<div id="my-checks-tags" class="col-sm-12">
<div id="my-checks-tags" class="col-sm-9">
{% for tag, status in tags %}
<div class="btn btn-xs {{ status }} {% if tag in selected_tags %}checked{% endif%}">{{ tag }}</div>
{% endfor %}
</div>
{% endif %}
<div class="col-sm-3">
<input id="search" type="text" placeholder="Filter by check name&hellip;" class="form-control" value="{{ search }}">
</div>
</div>
<div class="row">


Loading…
Cancel
Save