Browse Source

Checks can be sorted by name or last ping. Fixes #136

pull/140/head
Pēteris Caune 7 years ago
parent
commit
fc8d9ffe48
13 changed files with 114 additions and 40 deletions
  1. +1
    -1
      hc/accounts/admin.py
  2. +20
    -0
      hc/accounts/migrations/0011_profile_sort.py
  3. +1
    -0
      hc/accounts/models.py
  4. +14
    -0
      hc/front/tests/test_my_checks.py
  5. +14
    -7
      hc/front/views.py
  6. +25
    -22
      static/css/icomoon.css
  7. +12
    -0
      static/css/my_checks_desktop.css
  8. BIN
      static/fonts/icomoon.eot
  9. +8
    -7
      static/fonts/icomoon.svg
  10. BIN
      static/fonts/icomoon.ttf
  11. BIN
      static/fonts/icomoon.woff
  12. +1
    -1
      templates/front/my_checks.html
  13. +18
    -2
      templates/front/my_checks_desktop.html

+ 1
- 1
hc/accounts/admin.py View File

@ -21,7 +21,7 @@ class Fieldset:
class ProfileFieldset(Fieldset): class ProfileFieldset(Fieldset):
name = "User Profile" name = "User Profile"
fields = ("email", "api_key", "current_team", "reports_allowed", fields = ("email", "api_key", "current_team", "reports_allowed",
"next_report_date", "token")
"next_report_date", "token", "sort")
class TeamFieldset(Fieldset): class TeamFieldset(Fieldset):


+ 20
- 0
hc/accounts/migrations/0011_profile_sort.py View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-09-12 14:24
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0010_profile_team_limit'),
]
operations = [
migrations.AddField(
model_name='profile',
name='sort',
field=models.CharField(default='created', max_length=20),
),
]

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

@ -51,6 +51,7 @@ class Profile(models.Model):
sms_limit = models.IntegerField(default=0) sms_limit = models.IntegerField(default=0)
sms_sent = models.IntegerField(default=0) sms_sent = models.IntegerField(default=0)
team_limit = models.IntegerField(default=2) team_limit = models.IntegerField(default=2)
sort = models.CharField(max_length=20, default="created")
objects = ProfileManager() objects = ProfileManager()


+ 14
- 0
hc/front/tests/test_my_checks.py View File

@ -66,3 +66,17 @@ class MyChecksTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", password="password")
r = self.client.get("/checks/") r = self.client.get("/checks/")
self.assertContains(r, "Check limit reached", status_code=200) self.assertContains(r, "Check limit reached", status_code=200)
def test_it_saves_sort_field(self):
self.client.login(username="[email protected]", password="password")
self.client.get("/checks/?sort=name")
self.profile.refresh_from_db()
self.assertEqual(self.profile.sort, "name")
def test_it_ignores_bad_sort_value(self):
self.client.login(username="[email protected]", password="password")
self.client.get("/checks/?sort=invalid")
self.profile.refresh_from_db()
self.assertEqual(self.profile.sort, "created")

+ 14
- 7
hc/front/views.py View File

@ -1,4 +1,3 @@
from collections import Counter
from datetime import datetime, timedelta as td from datetime import datetime, timedelta as td
import json import json
@ -32,17 +31,24 @@ from pytz.exceptions import UnknownTimeZoneError
import requests import requests
VALID_SORT_VALUES = ("name", "-name", "last_ping", "-last_ping", "created")
@login_required @login_required
def my_checks(request): def my_checks(request):
q = Check.objects.filter(user=request.team.user).order_by("created")
if request.GET.get("sort") in VALID_SORT_VALUES:
request.profile.sort = request.GET["sort"]
request.profile.save()
q = Check.objects.filter(user=request.team.user)
q = q.order_by(request.profile.sort)
checks = list(q) checks = list(q)
counter = Counter()
down_tags, grace_tags = set(), set()
tags, down_tags, grace_tags = set(), set(), set()
for check in checks: for check in checks:
status = check.get_status() status = check.get_status()
for tag in check.tags_list(): for tag in check.tags_list():
counter[tag] += 1
tags.add(tag)
if status == "down": if status == "down":
down_tags.add(tag) down_tags.add(tag)
@ -55,12 +61,13 @@ def my_checks(request):
"page": "checks", "page": "checks",
"checks": checks, "checks": checks,
"now": timezone.now(), "now": timezone.now(),
"tags": counter.most_common(),
"tags": sorted(tags, key=lambda s: s.lower()),
"down_tags": down_tags, "down_tags": down_tags,
"grace_tags": grace_tags, "grace_tags": grace_tags,
"ping_endpoint": settings.PING_ENDPOINT, "ping_endpoint": settings.PING_ENDPOINT,
"timezones": all_timezones, "timezones": all_timezones,
"can_add_more": can_add_more
"can_add_more": can_add_more,
"sort": request.profile.sort
} }
return render(request, "front/my_checks.html", ctx) return render(request, "front/my_checks.html", ctx)


+ 25
- 22
static/css/icomoon.css View File

@ -1,10 +1,10 @@
@font-face { @font-face {
font-family: 'icomoon'; font-family: 'icomoon';
src: url('../fonts/icomoon.eot?cxijqz');
src: url('../fonts/icomoon.eot?cxijqz#iefix') format('embedded-opentype'),
url('../fonts/icomoon.ttf?cxijqz') format('truetype'),
url('../fonts/icomoon.woff?cxijqz') format('woff'),
url('../fonts/icomoon.svg?cxijqz#icomoon') format('svg');
src: url('../fonts/icomoon.eot?rq3u8q');
src: url('../fonts/icomoon.eot?rq3u8q#iefix') format('embedded-opentype'),
url('../fonts/icomoon.ttf?rq3u8q') format('truetype'),
url('../fonts/icomoon.woff?rq3u8q') format('woff'),
url('../fonts/icomoon.svg?rq3u8q#icomoon') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -24,42 +24,45 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-clippy:before {
content: "\e900";
}
.icon-cancel:before { .icon-cancel:before {
content: "\e5c9"; content: "\e5c9";
} }
.icon-ok:before {
content: "\e86d";
}
.icon-up:before {
content: "\e86c";
}
.icon-close:before { .icon-close:before {
content: "\e5cd"; content: "\e5cd";
} }
.icon-delete:before {
content: "\e872";
}
.icon-mail:before {
content: "\e159";
}
.icon-grace:before { .icon-grace:before {
content: "\e000"; content: "\e000";
} }
.icon-missing:before { .icon-missing:before {
content: "\e001"; content: "\e001";
} }
.icon-asc:before {
content: "\e5ce";
}
.icon-desc:before {
content: "\e5cf";
}
.icon-dots:before { .icon-dots:before {
content: "\e5d3"; content: "\e5d3";
} }
.icon-down:before { .icon-down:before {
content: "\e7f8";
content: "\e7f7";
} }
.icon-paused:before { .icon-paused:before {
content: "\e7f7";
content: "\e7f6";
} }
.icon-settings:before { .icon-settings:before {
content: "\e8b8"; content: "\e8b8";
}
.icon-mail:before {
content: "\e900";
}
.icon-delete:before {
content: "\e901";
}
.icon-up:before, .icon-ok:before {
content: "\e902";
}
.icon-clippy:before {
content: "\e903";
} }

+ 12
- 0
static/css/my_checks_desktop.css View File

@ -24,6 +24,18 @@ table.table tr > th.th-name {
border-top: 0; border-top: 0;
} }
#checks-table th {
border-top: 0;
}
#checks-table a.default {
color: #333;
}
#checks-table tr:hover a.default {
color: #0091EA;
}
#checks-table td { #checks-table td {
vertical-align: middle; vertical-align: middle;
border-top: 1px solid #f1f1f1; border-top: 1px solid #f1f1f1;


BIN
static/fonts/icomoon.eot View File


+ 8
- 7
static/fonts/icomoon.svg View File

@ -9,15 +9,16 @@
<glyph unicode="&#x20;" horiz-adv-x="512" d="" /> <glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe000;" glyph-name="grace" d="M554 384.667v256h-84v-256h84zM554 212.667v86h-84v-86h84zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" /> <glyph unicode="&#xe000;" glyph-name="grace" d="M554 384.667v256h-84v-256h84zM554 212.667v86h-84v-86h84zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe001;" glyph-name="missing" d="M512 84.667c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM470 640.667h84v-256h-84v256zM470 298.667h84v-86h-84v86z" /> <glyph unicode="&#xe001;" glyph-name="missing" d="M512 84.667c188 0 342 154 342 342s-154 342-342 342-342-154-342-342 154-342 342-342zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426zM470 640.667h84v-256h-84v256zM470 298.667h84v-86h-84v86z" />
<glyph unicode="&#xe159;" glyph-name="mail" d="M854 596.667v86l-342-214-342 214v-86l342-212zM854 768.667c46 0 84-40 84-86v-512c0-46-38-86-84-86h-684c-46 0-84 40-84 86v512c0 46 38 86 84 86h684z" />
<glyph unicode="&#xe5c9;" glyph-name="cancel" d="M726 272.667l-154 154 154 154-60 60-154-154-154 154-60-60 154-154-154-154 60-60 154 154 154-154zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" /> <glyph unicode="&#xe5c9;" glyph-name="cancel" d="M726 272.667l-154 154 154 154-60 60-154-154-154 154-60-60 154-154-154-154 60-60 154 154 154-154zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe5cd;" glyph-name="close" d="M810 664.667l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" /> <glyph unicode="&#xe5cd;" glyph-name="close" d="M810 664.667l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" />
<glyph unicode="&#xe5ce;" glyph-name="asc" d="M512 596.667l256-256-60-60-196 196-196-196-60 60z" />
<glyph unicode="&#xe5cf;" glyph-name="desc" d="M708 572.667l60-60-256-256-256 256 60 60 196-196z" />
<glyph unicode="&#xe5d3;" glyph-name="dots" d="M512 512.667c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 512.667c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM256 512.667c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86z" /> <glyph unicode="&#xe5d3;" glyph-name="dots" d="M512 512.667c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM768 512.667c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86zM256 512.667c46 0 86-40 86-86s-40-86-86-86-86 40-86 86 40 86 86 86z" />
<glyph unicode="&#xe7f7;" glyph-name="paused" d="M768 312.667l-382 402c10 4 20 10 30 14h2l12 6c6 2 12 2 18 4v30c0 36 28 64 64 64s64-28 64-64v-30c122-30 192-138 192-270v-156zM512 0.667c-48 0-86 36-86 84h172c0-48-38-84-86-84zM334 676.667c187.235-193.432 375.34-385.994 562-580l-54-54-86 86h-586v42l86 86v214c0 54 12 104 34 146l-120 118 54 56z" />
<glyph unicode="&#xe7f8;" glyph-name="down" d="M512 0.667c-48 0-86 38-86 84h170c0-49.675-37.225-84-84-84zM768 468.667v-212l86-86v-42h-684v42l86 86v212c0 132 70 240 192 270v30c0 36 28 64 64 64s64-28 64-64v-30c122-30 192-140 192-270zM852 490.667c-6 114-64 212-150 274l60 60c102-78 170-198 176-334h-86zM324 764.667c-88-62-146-160-152-274h-86c6 136 74 256 176 334z" />
<glyph unicode="&#xe86c;" glyph-name="up" d="M426 212.667l384 384-60 62-324-324-152 152-60-60zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe86d;" glyph-name="ok" d="M426 212.667l384 384-60 62-324-324-152 152-60-60zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe872;" glyph-name="delete" d="M810 768.667v-86h-596v86h148l44 42h212l44-42h148zM256 128.667v512h512v-512c0-46-40-86-86-86h-340c-46 0-86 40-86 86z" />
<glyph unicode="&#xe7f6;" glyph-name="paused" d="M768 312.667l-382 402c10 4 20 10 30 14h2l12 6c6 2 12 2 18 4v30c0 36 28 64 64 64s64-28 64-64v-30c122-30 192-138 192-270v-156zM512 0.667c-48 0-86 36-86 84h172c0-48-38-84-86-84zM334 676.667c187.235-193.432 375.34-385.994 562-580l-54-54-86 86h-586v42l86 86v214c0 54 12 104 34 146l-120 118 54 56z" />
<glyph unicode="&#xe7f7;" glyph-name="down" d="M512 0.667c-48 0-86 38-86 84h170c0-49.675-37.225-84-84-84zM768 468.667v-212l86-86v-42h-684v42l86 86v212c0 132 70 240 192 270v30c0 36 28 64 64 64s64-28 64-64v-30c122-30 192-140 192-270zM852 490.667c-6 114-64 212-150 274l60 60c102-78 170-198 176-334h-86zM324 764.667c-88-62-146-160-152-274h-86c6 136 74 256 176 334z" />
<glyph unicode="&#xe8b8;" glyph-name="settings" d="M512 276.667c82 0 150 68 150 150s-68 150-150 150-150-68-150-150 68-150 150-150zM830 384.667l90-70c8-6 10-18 4-28l-86-148c-6-10-16-12-26-8l-106 42c-22-16-46-32-72-42l-16-112c-2-10-10-18-20-18h-172c-10 0-18 8-20 18l-16 112c-26 10-50 24-72 42l-106-42c-10-4-20-2-26 8l-86 148c-6 10-4 22 4 28l90 70c-2 14-2 28-2 42s0 28 2 42l-90 70c-8 6-10 18-4 28l86 148c6 10 16 12 26 8l106-42c22 16 46 32 72 42l16 112c2 10 10 18 20 18h172c10 0 18-8 20-18l16-112c26-10 50-24 72-42l106 42c10 4 20 2 26-8l86-148c6-10 4-22-4-28l-90-70c2-14 2-28 2-42s0-28-2-42z" /> <glyph unicode="&#xe8b8;" glyph-name="settings" d="M512 276.667c82 0 150 68 150 150s-68 150-150 150-150-68-150-150 68-150 150-150zM830 384.667l90-70c8-6 10-18 4-28l-86-148c-6-10-16-12-26-8l-106 42c-22-16-46-32-72-42l-16-112c-2-10-10-18-20-18h-172c-10 0-18 8-20 18l-16 112c-26 10-50 24-72 42l-106-42c-10-4-20-2-26 8l-86 148c-6 10-4 22 4 28l90 70c-2 14-2 28-2 42s0 28 2 42l-90 70c-8 6-10 18-4 28l86 148c6 10 16 12 26 8l106-42c22 16 46 32 72 42l16 112c2 10 10 18 20 18h172c10 0 18-8 20-18l16-112c26-10 50-24 72-42l106 42c10 4 20 2 26-8l86-148c6-10 4-22-4-28l-90-70c2-14 2-28 2-42s0-28-2-42z" />
<glyph unicode="&#xe900;" glyph-name="clippy" horiz-adv-x="896" d="M704 64h-640v576h640v-192h64v320c0 35-29 64-64 64h-192c0 71-57 128-128 128s-128-57-128-128h-192c-35 0-64-29-64-64v-704c0-35 29-64 64-64h640c35 0 64 29 64 64v128h-64v-128zM192 768c29 0 29 0 64 0s64 29 64 64 29 64 64 64 64-29 64-64 32-64 64-64 33 0 64 0 64-29 64-64h-512c0 39 28 64 64 64zM128 256h128v64h-128v-64zM576 384v128l-256-192 256-192v128h320v128h-320zM128 128h192v64h-192v-64zM448 576h-320v-64h320v64zM256 448h-128v-64h128v64z" />
<glyph unicode="&#xe900;" glyph-name="mail" d="M512 468.667l342 214h-684zM854 170.667v426l-342-212-342 212v-426h684zM854 768.667c46 0 84-40 84-86v-512c0-46-38-86-84-86h-684c-46 0-84 40-84 86v512c0 46 38 86 84 86h684z" />
<glyph unicode="&#xe901;" glyph-name="delete" d="M810 768.667v-86h-596v86h148l44 42h212l44-42h148zM256 128.667v512h512v-512c0-46-40-86-86-86h-340c-46 0-86 40-86 86z" />
<glyph unicode="&#xe902;" glyph-name="up" d="M426 212.667l384 384-60 62-324-324-152 152-60-60zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe903;" glyph-name="clippy" horiz-adv-x="896" d="M704 64h-640v576h640v-192h64v320c0 35-29 64-64 64h-192c0 71-57 128-128 128s-128-57-128-128h-192c-35 0-64-29-64-64v-704c0-35 29-64 64-64h640c35 0 64 29 64 64v128h-64v-128zM192 768c29 0 29 0 64 0s64 29 64 64 29 64 64 64 64-29 64-64 32-64 64-64 33 0 64 0 64-29 64-64h-512c0 39 28 64 64 64zM128 256h128v64h-128v-64zM576 384v128l-256-192 256-192v128h320v128h-320zM128 128h192v64h-192v-64zM448 576h-320v-64h320v64zM256 448h-128v-64h128v64z" />
</font></defs></svg> </font></defs></svg>

BIN
static/fonts/icomoon.ttf View File


BIN
static/fonts/icomoon.woff View File


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

@ -17,7 +17,7 @@
</div> </div>
{% if tags %} {% if tags %}
<div id="my-checks-tags" class="col-sm-12"> <div id="my-checks-tags" class="col-sm-12">
{% for tag, count in tags %}
{% for tag in tags %}
{% if tag in down_tags %} {% if tag in down_tags %}
<button class="btn btn-danger btn-xs" data-toggle="button">{{ tag }}</button> <button class="btn btn-danger btn-xs" data-toggle="button">{{ tag }}</button>
{% elif tag in grace_tags %} {% elif tag in grace_tags %}


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

@ -2,13 +2,29 @@
<table id="checks-table" class="table hidden-xs"> <table id="checks-table" class="table hidden-xs">
<tr> <tr>
<th></th> <th></th>
<th class="th-name">Name</th>
<th class="th-name">
{% if sort == "name" %}
<a href="?sort=-name">Name<span class="icon-asc"></span></a>
{% elif sort == "-name" %}
<a href="?sort=created">Name<span class="icon-desc"></span></a>
{% else %}
<a href="?sort=name" class="default">Name</span></a>
{% endif %}
</th>
<th>Ping URL</th> <th>Ping URL</th>
<th class="th-period"> <th class="th-period">
Period <br /> Period <br />
<span class="checks-subline">Grace</span> <span class="checks-subline">Grace</span>
</th> </th>
<th class="th-last-ping">Last Ping</th>
<th class="th-last-ping">
{% if sort == "last_ping" %}
<a href="?sort=created">Last Ping<span class="icon-desc"></span></a>
{% elif sort == "-last_ping" %}
<a href="?sort=last_ping">Last Ping<span class="icon-asc"></span></a>
{% else %}
<a href="?sort=-last_ping" class="default">Last Ping</span></a>
{% endif %}
</th>
<th></th> <th></th>
</tr> </tr>
{% for check in checks %} {% for check in checks %}


Loading…
Cancel
Save