From 4906a5247cadddae6b0774b1b962b6fd75d1726e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Thu, 16 Mar 2017 16:06:22 +0200 Subject: [PATCH] Split "Account Settings" page into subpages. --- hc/accounts/tests/test_badges.py | 20 ++++ hc/accounts/tests/test_notifications.py | 24 +++++ hc/accounts/tests/test_profile.py | 15 --- hc/accounts/urls.py | 2 + hc/accounts/views.py | 56 ++++++++-- static/css/base.css | 6 +- static/css/bootstrap.css | 4 +- stuff/bootstrap/variables.less | 4 +- templates/accounts/badges.html | 63 +++++++++++ templates/accounts/notifications.html | 58 ++++++++++ templates/accounts/profile.html | 136 ++++++++---------------- templates/base.html | 4 +- 12 files changed, 267 insertions(+), 125 deletions(-) create mode 100644 hc/accounts/tests/test_badges.py create mode 100644 hc/accounts/tests/test_notifications.py create mode 100644 templates/accounts/badges.html create mode 100644 templates/accounts/notifications.html diff --git a/hc/accounts/tests/test_badges.py b/hc/accounts/tests/test_badges.py new file mode 100644 index 00000000..d047ea11 --- /dev/null +++ b/hc/accounts/tests/test_badges.py @@ -0,0 +1,20 @@ +from hc.test import BaseTestCase +from hc.api.models import Check + + +class BadgesTestCase(BaseTestCase): + + def test_it_shows_badges(self): + self.client.login(username="alice@example.org", password="password") + Check.objects.create(user=self.alice, tags="foo a-B_1 baz@") + Check.objects.create(user=self.bob, tags="bobs-tag") + + r = self.client.get("/accounts/profile/badges/") + self.assertContains(r, "foo.svg") + self.assertContains(r, "a-B_1.svg") + + # Expect badge URLs only for tags that match \w+ + self.assertNotContains(r, "baz@.svg") + + # Expect only Alice's tags + self.assertNotContains(r, "bobs-tag.svg") diff --git a/hc/accounts/tests/test_notifications.py b/hc/accounts/tests/test_notifications.py new file mode 100644 index 00000000..5ed0c8e1 --- /dev/null +++ b/hc/accounts/tests/test_notifications.py @@ -0,0 +1,24 @@ +from hc.test import BaseTestCase + + +class NotificationsTestCase(BaseTestCase): + + def test_it_saves_reports_allowed_true(self): + self.client.login(username="alice@example.org", password="password") + + form = {"reports_allowed": "on"} + r = self.client.post("/accounts/profile/notifications/", form) + assert r.status_code == 200 + + self.alice.profile.refresh_from_db() + self.assertTrue(self.alice.profile.reports_allowed) + + def test_it_saves_reports_allowed_false(self): + self.client.login(username="alice@example.org", password="password") + + form = {} + r = self.client.post("/accounts/profile/notifications/", form) + assert r.status_code == 200 + + self.alice.profile.refresh_from_db() + self.assertFalse(self.alice.profile.reports_allowed) diff --git a/hc/accounts/tests/test_profile.py b/hc/accounts/tests/test_profile.py index 3d026c43..7630ee57 100644 --- a/hc/accounts/tests/test_profile.py +++ b/hc/accounts/tests/test_profile.py @@ -123,18 +123,3 @@ class ProfileTestCase(BaseTestCase): # to user's default team. self.bobs_profile.refresh_from_db() self.assertEqual(self.bobs_profile.current_team, self.bobs_profile) - - def test_it_shows_badges(self): - self.client.login(username="alice@example.org", password="password") - Check.objects.create(user=self.alice, tags="foo a-B_1 baz@") - Check.objects.create(user=self.bob, tags="bobs-tag") - - r = self.client.get("/accounts/profile/") - self.assertContains(r, "foo.svg") - self.assertContains(r, "a-B_1.svg") - - # Expect badge URLs only for tags that match \w+ - self.assertNotContains(r, "baz@.svg") - - # Expect only Alice's tags - self.assertNotContains(r, "bobs-tag.svg") diff --git a/hc/accounts/urls.py b/hc/accounts/urls.py index 452c4c09..06fc8445 100644 --- a/hc/accounts/urls.py +++ b/hc/accounts/urls.py @@ -14,6 +14,8 @@ urlpatterns = [ views.check_token, name="hc-check-token"), url(r'^profile/$', views.profile, name="hc-profile"), + url(r'^profile/notifications/$', views.notifications, name="hc-notifications"), + url(r'^profile/badges/$', views.badges, name="hc-badges"), url(r'^unsubscribe_reports/([\w-]+)/$', views.unsubscribe_reports, name="hc-unsubscribe-reports"), diff --git a/hc/accounts/views.py b/hc/accounts/views.py index d86a9e91..519c1f11 100644 --- a/hc/accounts/views.py +++ b/hc/accounts/views.py @@ -169,12 +169,6 @@ def profile(request): messages.info(request, "The API key has been revoked!") elif "show_api_key" in request.POST: show_api_key = True - elif "update_reports_allowed" in request.POST: - form = ReportSettingsForm(request.POST) - if form.is_valid(): - profile.reports_allowed = form.cleaned_data["reports_allowed"] - profile.save() - messages.success(request, "Your settings have been updated!") elif "invite_team_member" in request.POST: if not profile.team_access_allowed: return HttpResponseForbidden() @@ -213,6 +207,48 @@ def profile(request): profile.save() messages.success(request, "Team Name updated!") + ctx = { + "page": "profile", + "profile": profile, + "show_api_key": show_api_key + } + + return render(request, "accounts/profile.html", ctx) + + +@login_required +def notifications(request): + profile = request.user.profile + # Switch user back to its default team + if profile.current_team_id != profile.id: + request.team = profile + profile.current_team_id = profile.id + profile.save() + + if request.method == "POST": + form = ReportSettingsForm(request.POST) + if form.is_valid(): + profile.reports_allowed = form.cleaned_data["reports_allowed"] + profile.save() + messages.success(request, "Your settings have been updated!") + + ctx = { + "page": "profile", + "profile": profile, + } + + return render(request, "accounts/notifications.html", ctx) + + +@login_required +def badges(request): + profile = request.user.profile + # Switch user back to its default team + if profile.current_team_id != profile.id: + request.team = profile + profile.current_team_id = profile.id + profile.save() + tags = set() for check in Check.objects.filter(user=request.team.user): tags.update(check.tags_list()) @@ -228,11 +264,9 @@ def profile(request): ctx = { "page": "profile", "badge_urls": badge_urls, - "profile": profile, - "show_api_key": show_api_key } - return render(request, "accounts/profile.html", ctx) + return render(request, "accounts/badges.html", ctx) @login_required @@ -286,11 +320,11 @@ def switch_team(request, target_username): # Superuser can switch to any team. access_ok = request.user.is_superuser - # Users can switch to teams they are members of. + # Users can switch to their own teams. if not access_ok and other_user.id == request.user.id: access_ok = True - # Users can switch to their own teams. + # Users can switch to teams they are members of. if not access_ok: for membership in request.user.member_set.all(): if membership.team.user.id == other_user.id: diff --git a/static/css/base.css b/static/css/base.css index 2fa9f07e..379fc1b9 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -78,4 +78,8 @@ body { pre { border: 0; -} \ No newline at end of file +} + +.nav-pills > li > a { + color: #888; +} diff --git a/static/css/bootstrap.css b/static/css/bootstrap.css index 840d63be..9d8ff47e 100644 --- a/static/css/bootstrap.css +++ b/static/css/bootstrap.css @@ -3274,8 +3274,8 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { - color: #ffffff; - background-color: #22bc66; + color: #888888; + background-color: #eeeeee; } .nav-stacked > li { float: none; diff --git a/stuff/bootstrap/variables.less b/stuff/bootstrap/variables.less index d96bb1d7..b4e6a721 100755 --- a/stuff/bootstrap/variables.less +++ b/stuff/bootstrap/variables.less @@ -440,8 +440,8 @@ //== Pills @nav-pills-border-radius: @border-radius-base; -@nav-pills-active-link-hover-bg: @component-active-bg; -@nav-pills-active-link-hover-color: @component-active-color; +@nav-pills-active-link-hover-bg: #EEE; +@nav-pills-active-link-hover-color: #888; //== Pagination diff --git a/templates/accounts/badges.html b/templates/accounts/badges.html new file mode 100644 index 00000000..0c73ab19 --- /dev/null +++ b/templates/accounts/badges.html @@ -0,0 +1,63 @@ +{% extends "base.html" %} +{% load compress staticfiles hc_extras %} + +{% block title %}Account Settings - {% site_name %}{% endblock %} + +{% block content %} +
+
+

Settings

+
+
+ +
+ + +
+
+
+

Status Badges

+

+ healthchecks.io provides status badges for each of the tags + you have used. The badges have public, but hard-to-guess + URLs. If you wish, you can add them to your READMEs, + dashboards or status pages. +

+ {% if badge_urls %} + + {% for badge_url in badge_urls %} + + + + + {% endfor %} +
+ + + {{ badge_url }} +
+ {% else %} +

+ To get started with status badges, add some tags to + your checks! +

+ {% endif %} + +
+
+
+
+{% endblock %} + +{% block scripts %} +{% compress js %} + + +{% endcompress %} +{% endblock %} diff --git a/templates/accounts/notifications.html b/templates/accounts/notifications.html new file mode 100644 index 00000000..99a75a9a --- /dev/null +++ b/templates/accounts/notifications.html @@ -0,0 +1,58 @@ +{% extends "base.html" %} +{% load compress staticfiles hc_extras %} + +{% block title %}Account Settings - {% site_name %}{% endblock %} + +{% block content %} +
+
+

Settings

+
+ {% if messages %} +
+ {% for message in messages %} +

{{ message }}

+ {% endfor %} +
+ {% endif %} +
+ +
+ + +
+
+
+

Monthly Reports

+
+ {% csrf_token %} + + +
+
+
+
+
+{% endblock %} + +{% block scripts %} +{% compress js %} + + +{% endcompress %} +{% endblock %} diff --git a/templates/accounts/profile.html b/templates/accounts/profile.html index 31f2694d..eccd32d7 100644 --- a/templates/accounts/profile.html +++ b/templates/accounts/profile.html @@ -19,26 +19,13 @@
-
-
-
-
- {% csrf_token %} -

Monthly Reports

- - -
-
-
+ +
@@ -55,9 +42,44 @@
-
-
+
+
+

API Access

+ {% if profile.api_key %} + {% if show_api_key %} + API key: {{ profile.api_key }} + + + {% else %} +
+ + API access is enabled. + {% csrf_token %} + + +
+ {% endif %} + {% else %} + + API access is disabled. +
+ {% csrf_token %} + +
+ {% endif %} +
+
+

Team Access

@@ -115,77 +137,7 @@
- -
-
-
-

API Access

- {% if profile.api_key %} - {% if show_api_key %} - API key: {{ profile.api_key }} - - - {% else %} - - API access is enabled. -
- {% csrf_token %} - - -
- {% endif %} - {% else %} - - API access is disabled. -
- {% csrf_token %} - -
- {% endif %} -
-
-
- - -{% if badge_urls %} -
-
-
-
-

Status Badges

-

- Here are status badges for each of the tags you have used. The - badges have public, but hard-to-guess URLs. If you wish, you can - add them to your READMEs, dashboards or status pages. -

- - {% for badge_url in badge_urls %} - - - - - {% endfor %} -
- - - {{ badge_url }} -
-
-
-
-{% endif %} - -