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 %} +
+ 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 %} ++ + | +
+ {{ badge_url }}
+ |
+
+ To get started with status badges, add some tags to + your checks! +
+ {% endif %} + +{{ profile.api_key }}
+
+
+ {% else %}
+
+ {% endif %}
+ {% else %}
+
+ API access is disabled.
+
+ {% endif %}
+ {{ profile.api_key }}
-
-
- {% else %}
-
- API access is enabled.
-
- {% endif %}
- {% else %}
-
- API access is disabled.
-
- {% endif %}
- - 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. -
-- - | -
- {{ badge_url }}
- |
-