From fc8d9ffe4813ac465f79b09e4d85f3636a305342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Tue, 12 Sep 2017 17:32:53 +0300 Subject: [PATCH] Checks can be sorted by name or last ping. Fixes #136 --- hc/accounts/admin.py | 2 +- hc/accounts/migrations/0011_profile_sort.py | 20 +++++++++ hc/accounts/models.py | 1 + hc/front/tests/test_my_checks.py | 14 ++++++ hc/front/views.py | 21 ++++++--- static/css/icomoon.css | 47 +++++++++++--------- static/css/my_checks_desktop.css | 12 +++++ static/fonts/icomoon.eot | Bin 2968 -> 2948 bytes static/fonts/icomoon.svg | 15 ++++--- static/fonts/icomoon.ttf | Bin 2804 -> 2784 bytes static/fonts/icomoon.woff | Bin 2880 -> 2860 bytes templates/front/my_checks.html | 2 +- templates/front/my_checks_desktop.html | 20 ++++++++- 13 files changed, 114 insertions(+), 40 deletions(-) create mode 100644 hc/accounts/migrations/0011_profile_sort.py diff --git a/hc/accounts/admin.py b/hc/accounts/admin.py index 17f5a58d..deabc73f 100644 --- a/hc/accounts/admin.py +++ b/hc/accounts/admin.py @@ -21,7 +21,7 @@ class Fieldset: class ProfileFieldset(Fieldset): name = "User Profile" fields = ("email", "api_key", "current_team", "reports_allowed", - "next_report_date", "token") + "next_report_date", "token", "sort") class TeamFieldset(Fieldset): diff --git a/hc/accounts/migrations/0011_profile_sort.py b/hc/accounts/migrations/0011_profile_sort.py new file mode 100644 index 00000000..31c6133f --- /dev/null +++ b/hc/accounts/migrations/0011_profile_sort.py @@ -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), + ), + ] diff --git a/hc/accounts/models.py b/hc/accounts/models.py index b74fbe76..8d8e2001 100644 --- a/hc/accounts/models.py +++ b/hc/accounts/models.py @@ -51,6 +51,7 @@ class Profile(models.Model): sms_limit = models.IntegerField(default=0) sms_sent = models.IntegerField(default=0) team_limit = models.IntegerField(default=2) + sort = models.CharField(max_length=20, default="created") objects = ProfileManager() diff --git a/hc/front/tests/test_my_checks.py b/hc/front/tests/test_my_checks.py index 2228adbf..a5c1a780 100644 --- a/hc/front/tests/test_my_checks.py +++ b/hc/front/tests/test_my_checks.py @@ -66,3 +66,17 @@ class MyChecksTestCase(BaseTestCase): self.client.login(username="alice@example.org", password="password") r = self.client.get("/checks/") self.assertContains(r, "Check limit reached", status_code=200) + + def test_it_saves_sort_field(self): + self.client.login(username="alice@example.org", 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="alice@example.org", password="password") + self.client.get("/checks/?sort=invalid") + + self.profile.refresh_from_db() + self.assertEqual(self.profile.sort, "created") diff --git a/hc/front/views.py b/hc/front/views.py index 3e3a231b..7ad2bcce 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -1,4 +1,3 @@ -from collections import Counter from datetime import datetime, timedelta as td import json @@ -32,17 +31,24 @@ from pytz.exceptions import UnknownTimeZoneError import requests +VALID_SORT_VALUES = ("name", "-name", "last_ping", "-last_ping", "created") + + @login_required 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) - counter = Counter() - down_tags, grace_tags = set(), set() + tags, down_tags, grace_tags = set(), set(), set() for check in checks: status = check.get_status() for tag in check.tags_list(): - counter[tag] += 1 + tags.add(tag) if status == "down": down_tags.add(tag) @@ -55,12 +61,13 @@ def my_checks(request): "page": "checks", "checks": checks, "now": timezone.now(), - "tags": counter.most_common(), + "tags": sorted(tags, key=lambda s: s.lower()), "down_tags": down_tags, "grace_tags": grace_tags, "ping_endpoint": settings.PING_ENDPOINT, "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) diff --git a/static/css/icomoon.css b/static/css/icomoon.css index 287b9c92..6c42598c 100644 --- a/static/css/icomoon.css +++ b/static/css/icomoon.css @@ -1,10 +1,10 @@ @font-face { 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-style: normal; } @@ -24,42 +24,45 @@ -moz-osx-font-smoothing: grayscale; } -.icon-clippy:before { - content: "\e900"; -} .icon-cancel:before { content: "\e5c9"; } -.icon-ok:before { - content: "\e86d"; -} -.icon-up:before { - content: "\e86c"; -} .icon-close:before { content: "\e5cd"; } -.icon-delete:before { - content: "\e872"; -} -.icon-mail:before { - content: "\e159"; -} .icon-grace:before { content: "\e000"; } .icon-missing:before { content: "\e001"; } +.icon-asc:before { + content: "\e5ce"; +} +.icon-desc:before { + content: "\e5cf"; +} .icon-dots:before { content: "\e5d3"; } .icon-down:before { - content: "\e7f8"; + content: "\e7f7"; } .icon-paused:before { - content: "\e7f7"; + content: "\e7f6"; } .icon-settings:before { 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"; } \ No newline at end of file diff --git a/static/css/my_checks_desktop.css b/static/css/my_checks_desktop.css index e63ab941..fe4a509b 100644 --- a/static/css/my_checks_desktop.css +++ b/static/css/my_checks_desktop.css @@ -24,6 +24,18 @@ table.table tr > th.th-name { 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 { vertical-align: middle; border-top: 1px solid #f1f1f1; diff --git a/static/fonts/icomoon.eot b/static/fonts/icomoon.eot index 870829768b694e8d3b23cbff6b4d08e02b2d621c..1b4b9a3225836aad1da2d5edab1ea85f80006336 100644 GIT binary patch delta 642 zcmXX@J!n%=6#mY=$xB}<(bS}`Mloq(Tb!&-Z2U=(Y()!#BpHIDuSso�Hw73Sz;~ z$-(-Tx`;ys8#|fB!NDO24kDPQgHTA3VBK0p9VB_47rk)ax!=#Z=e&DYwTfo1^aHIG zd(@WLU-ue2s%IrRb6*hv-f-N^7WLAn;$0s=#~4@U^o0`VLyVts?wc#zxpgkPM~q(p z%36L_&$%8H?y)q@`edF7M?p3iR~Vnj7t4$BB}bky`!Q9R&*}#rI-fG$V?0{a7fU$h z!!r2b)imYXb><`>G4tibu!(jjHj$k9cT#u{C?!UtoJ$CFS%2(+mE zzWuS?`1*VI^*3pDOp|r4YJvF=%>QB@J)X=j0h=%GJMW7Qd9{@0;xoud2(5NqjFYh~ zS1%KRj!1|U>^u%R#vEgUyTt1Cm`Itu49i38iCZ4hRElb%9y4LdBF-Dj57f%GmsC6I za8X7gjg+iPf`9`WSB(sl+dkr^i9xU1qlAWoqi5Wa$uRdycambGTkTfGMsVVEsFSq5 z)ZFTVs+*hLv`9ySU4+8nkU%hEG?XdBuVjpqeY<{sBJcWs;>N+)PxRY**U;QHTGqzO z#<&`#0VA*a^(`9@`7cmqrxj_A-2cov(sIeF+7gST9_5c6? delta 568 zcmYk3PiPZC6vp41+0AAXwT32cjipT!^`vN$aVa`98P=69<=#aZ5tGoo95(rei95~+;c|40C9^t4_A+ML(w;hOF>cjFVZciU~6MQgX=U;5oG{+D9=Lrm&>8Xb#{M$ - + + - - - - - + + - + + + + \ No newline at end of file diff --git a/static/fonts/icomoon.ttf b/static/fonts/icomoon.ttf index cea03cff95d47ce7aa6facb6ef67d3b1a43e3436..af330583df8b0b6e4be667eb4f8f40cfca0bfb25 100644 GIT binary patch delta 664 zcmYjPO=uHA6#m{!vT0IDO>DX~h^C2ckF7~;tR_frMGFCK_7DVJ+u9rw8)(6*NCVcM zdeH7gFQTBJu_tp;@X$jLJcweO9t2@Qg7sF#pMxap+r)zdZ{K|1_x@&Pe+10H5(q#i zN{|>%pB;*J`4z#;E4B+$1-T@iA_)Qk(p(ljJe-8WhYFcge^Y-~ z-~94>=fziPH7tvD&N0FKTjqZ;j}}kX=a3_q3LXz8dIM@k^>Pg|9+FylNyB7}%DbnD zK>H;`22LJ^T!XGb!CjKoYEopZmWLff9FwwRNOe;}71g8#TNWwa*zrK+y?jQMD~gx0 z5*jkHEC~WGsGQZ`M?Po2kD@&RU$+wJ3lALi#YbY?OKVJu^=7$Q7VF{Ykw|0G{!(qb z2`X=GH8r8d!%akDv4}u8ZVV~o#&u`bxaHb8#19mB`fcodSMn!19j$AqeKJgYV|!z@ zBeCRf^DU950T^rl*|vknZyU6IjD*nD|Z#C255|ii_g5 bcrHwNhU4rX&yOr0oR@&$3*T2syC2hEednA` delta 547 zcmaDL`bD&!fsuiMft#U$ftkU;KUm+0Ux@V&P-G7fCnV=47BuqLeq&%@lmYVRq$d^^ z0BHdre+Q7}NYANEOH*``2J#OuFtDx2NKH)P`Xr$Xl*$0gn`Hn6*mIaK0r?Ane3gvc zk_yWP)_p+!5g^|sCqLOSk@F6B5(5J#2S`C~VnqRiBts04uLI;OkXUd7DFz{(&Bbe1WrswgX?k(j8U2%EB^lA5WYiJ38T*uPc(RxyS# zhA9~tD*p`ukxZds*RF+KVQer_`p2MbY^==0pky-nG}FAzTbWlePUdHin#{`{Gx;Q& z+va#yKE}zJ>@VbjHWuf{1?++=qM4xJX8_TY3pmUf1t+iIkoOM*%3cHF zRZtA#!!SrZg}DK&9T<2FA`Eg2J`9r>b}_tT|ngZ#KmO66vgz2IRxxe!Oe1< GhZq6a>yLE+ diff --git a/static/fonts/icomoon.woff b/static/fonts/icomoon.woff index 8c57375ea73c29a3ece30862357969c224135cf3..da5cc1760732a37c54a7b76f336cd2f9874d05c7 100644 GIT binary patch delta 669 zcmX|luq z)~;NrcT+d6+!(Vm8<(O%a3MbWK!id-f)!j?@v)HPdL|YJzBx1h`Df0|FwY{@NaRv( zWCR3m-h=R}=xKoLZ3^8z5W1m>LfM)HsK|*W#ryJ=*t9jLw68qx-XSnux_p7PAAt5y zais8#ic{7kTUOXJtnl9~T`RK4+FPFQSGY@ZwOF2CV2#&eRFPeD7fUk*3pwZp3j+$@ zZO?$Z=MleEX^SWaCi zf&e5mzJ9zx%~#Dg&DGDpx1N5HPRnsP&s7>={Wa^qSVu=E=TqDj%f^nzGP}dkeALf- zbRMiGM2hTNa^(~eXpe-*ql=G5?m_pU;3`JFZiu|oiBKM5PgZ#-s#7K^>V^ZA7FixB zKTzB2dQ7z!nx7^lOyp%n5(M0c@~Zwm3U>7eX($p7hO}f~V&HHvJ)GiNW@}tj+m&`j zR1-solC5#o)A~jmR9RbVo5D;d+DN8SNr6P#zN(GdNo~S@=ich&&k%mJed63M<0rhX z&NHlU+6^^O(f-h#p&mP+_nz5s@ge_#3Of}hGr1Ev4^u9xmE1fCVIRhD4=>Tcchbn9 ZW%?-2i#y_pXvov-Q6I6Vc3po?e*v%0pN9Yd delta 631 zcmZ1@c0f#|+~3WOfsp|SxE&a{K{VHw$%5Px6Lo~@S^p&GCKfO-FlGRS=YVh{f9<#Q z#A2Wr6AO^f0mTC8IhAQZF&+j6wiO_prsyP{k(!tSRI&xA#tekHK1t|i00n_!Z-9Ii z5N6L|zLb$$Qo+E$DFEcVfUso)>%N@)BafGAiuZ-=pBd}kXmM-YG&q3lX)2J85t(~Fj^-z07YaN1b{L; zK+h{YV0;+)^yJgCPcJ|J@gny{(Tg1~8UFwM{~xFdsQ&>2T=x5m93)xB|Bn?|mI?t38G$JoJm jhlz{Hf+>pW5pxJIR2diq8KM~2!RkR)0m0@f&P|K}2rQE6 diff --git a/templates/front/my_checks.html b/templates/front/my_checks.html index fe698e3a..fb388ec5 100644 --- a/templates/front/my_checks.html +++ b/templates/front/my_checks.html @@ -17,7 +17,7 @@ {% if tags %}
- {% for tag, count in tags %} + {% for tag in tags %} {% if tag in down_tags %} {% elif tag in grace_tags %} diff --git a/templates/front/my_checks_desktop.html b/templates/front/my_checks_desktop.html index d81e410d..877e3efd 100644 --- a/templates/front/my_checks_desktop.html +++ b/templates/front/my_checks_desktop.html @@ -2,13 +2,29 @@ - + - + {% for check in checks %}