Preferences form

This commit is contained in:
Klaas van Schelven
2024-09-12 12:41:40 +02:00
parent 9e4b326ab6
commit 7b5aaca3ac
5 changed files with 83 additions and 3 deletions

View File

@@ -8,7 +8,7 @@ from alerts.views import debug_email as debug_alerts_email
from users.views import debug_email as debug_users_email
from teams.views import debug_email as debug_teams_email
from bugsink.app_settings import get_settings
from users.views import signup, confirm_email, resend_confirmation, request_reset_password, reset_password
from users.views import signup, confirm_email, resend_confirmation, request_reset_password, reset_password, preferences
from .views import home, trigger_error, favicon, settings_view
@@ -31,6 +31,8 @@ urlpatterns = [
path("accounts/login/", auth_views.LoginView.as_view(template_name="bugsink/login.html"), name="login"),
path("accounts/logout/", auth_views.LogoutView.as_view(template_name="users/logged_out.html"), name="logout"),
path("accounts/preferences/", preferences, name="preferences"),
path('api/', include('ingest.urls')),
path('projects/', include('projects.urls')),

View File

@@ -34,7 +34,7 @@
{% if logged_in_user.is_anonymous %}
<a href="/accounts/login/"><div class="px-4 py-2 my-2 hover:bg-slate-300 rounded-xl">Login</div></a> {# I don't think this is actually ever shown in practice, because you must always be logged in #}
{% else %}
<a href="/accounts/TODO/"><div class="px-4 py-2 my-2 hover:bg-slate-300 rounded-xl">Profile</div></a>
<a href="/accounts/preferences/"><div class="px-4 py-2 my-2 hover:bg-slate-300 rounded-xl">Preferences</div></a>
<div class="px-4 py-2 my-2 mr-2 hover:bg-slate-300 rounded-xl"><form id="logout-form" method="post" action="{% url 'logout' %}">{% csrf_token %}<button type="submit">Log out</button></form></div>
{% endif %}
</div>

View File

@@ -11,6 +11,12 @@ from django.forms import ModelForm
from django.utils.html import escape, mark_safe
TRUE_FALSE_CHOICES = (
(True, 'Yes'),
(False, 'No')
)
def _(x):
# dummy gettext
return x
@@ -101,3 +107,13 @@ class SetPasswordForm(BaseSetPasswordForm):
self.fields['new_password1'].help_text = "At least 8 characters"
self.fields['new_password2'].help_text = None # "Confirm password" is descriptive enough
class PreferencesForm(ModelForm):
# I haven't gotten a decent display for checkboxes in forms yet; the quickest hack around this is a ChoiceField
send_email_alerts = forms.ChoiceField(
label=_("Send email alerts"), choices=TRUE_FALSE_CHOICES, required=False, widget=forms.Select())
class Meta:
model = UserModel
fields = ("send_email_alerts",)

View File

@@ -0,0 +1,37 @@
{% extends "base.html" %}
{% load static %}
{% load tailwind_forms %}
{% block title %}User Preferences · {{ site_title }}{% endblock %}
{% block content %}
<div class="flex items-center justify-center">
<div class="m-4 max-w-4xl flex-auto">
<form action="" method="post">
{% csrf_token %}
{% if messages %}
<ul>
{% for message in messages %}
{# if we introduce different levels we can use{% message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %} #}
<li class="bg-cyan-50 border-2 border-cyan-800 p-4 rounded-lg">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<div>
<h1 class="text-4xl my-4 font-bold">User Preferences</h1>
</div>
{% tailwind_formfield form.send_email_alerts %}
<button name="action" value="invite" class="font-bold text-slate-800 border-slate-500 pl-4 pr-4 pb-2 pt-2 border-2 bg-cyan-200 hover:bg-cyan-400 active:ring rounded-md">Save</button>
</form>
</div>
</div>
{% endblock %}

View File

@@ -5,10 +5,13 @@ from django.shortcuts import render, redirect, reverse
from django.contrib.auth import get_user_model
from django.http import Http404
from django.utils import timezone
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from bugsink.app_settings import get_settings, CB_ANYBODY
from bugsink.decorators import atomic_for_request_method
from .forms import UserCreationForm, ResendConfirmationForm, RequestPasswordResetForm, SetPasswordForm
from .forms import UserCreationForm, ResendConfirmationForm, RequestPasswordResetForm, SetPasswordForm, PreferencesForm
from .models import EmailVerification
from .tasks import send_confirm_email, send_reset_email
@@ -150,6 +153,28 @@ def reset_password(request, token=None):
return render(request, "users/reset_password.html", {"form": form, "next": next})
@atomic_for_request_method
# in the general case this is done by Middleware but we're under /accounts/. not security-critical because we simply
# get a failure on request.user if this wasn't there, but still the "right thing"
@login_required
def preferences(request):
user = request.user
if request.method == 'POST':
form = PreferencesForm(request.POST, instance=user)
if form.is_valid():
form.save()
messages.success(request, "Updated preferences")
return redirect('preferences')
else:
form = PreferencesForm(instance=user)
return render(request, 'users/preferences.html', {
'form': form,
})
DEBUG_CONTEXTS = {
"confirm_email": {
"site_title": get_settings().SITE_TITLE,