register device flow views

This commit is contained in:
Tom Irgang 2023-04-19 21:28:59 +02:00
parent 92354201af
commit 8fd9e9b38c
12 changed files with 244 additions and 52 deletions

View file

@ -48,8 +48,13 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'crispy_forms',
'crispy_bootstrap4',
] ]
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap4'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',

42
rc_hip/repapp/forms.py Normal file
View file

@ -0,0 +1,42 @@
from django import forms
class RegisterDevice(forms.Form):
mail = forms.EmailField(
label="eMail Adresse",
help_text="Diese eMail-Adresse wird für Aktualisierungen"
" zur Anfrage verwendet.",
max_length=200)
device = forms.CharField(
label="Gerätebezeichnung",
help_text="Bitte geben Sie den Hersteller und die"
" Gerätebezeichnung an.",
max_length=200
)
error = forms.CharField(
label="Fehlerbeschreibung",
help_text="Beschreiben Sie hier das Problem ihres Gerätes.",
widget=forms.Textarea
)
follow_up = forms.BooleanField(
label="Folgetermin",
help_text="Klicken Sie dieses Kästchen an wenn sie mit diesem"
" Gerät bereits bei einem Repair-Café waren.",
required=False
)
class RegisterGuest(forms.Form):
name = forms.CharField(
label="Name",
max_length=200
)
phone = forms.CharField(
label="Telefonnummer",
max_length=200,
help_text="Diese Telefonnummer wird für Rückfragen verwendet."
)
residence = forms.CharField(
label="Wohnort",
max_length=200
)

View file

@ -85,7 +85,7 @@ class Device(models.Model):
verbose_name_plural = _('Geräte') verbose_name_plural = _('Geräte')
def __str__(self): def __str__(self):
return f'Gerät {self.device} von {self.guest_id.name}' return f'Gerät {self.device}'
class Appointment(models.Model): class Appointment(models.Model):

View file

@ -1,13 +1,29 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="de">
<head> <head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous"
/>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
crossorigin="anonymous"
></script>
<title>RepApp{% block title %}{% endblock title %}</title> <title>RepApp{% block title %}{% endblock title %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
</head> </head>
<body> <body>
{% block content %}{% endblock content %} <div class="container">
<div class="row justify-content-center">
<div class="col-8">{% block content %} {% endblock %}</div>
</div>
</div>
</body> </body>
</html> </html>

View file

@ -3,7 +3,8 @@
{% block title %}- Repair-Cafés{% endblock title %} {% block title %}- Repair-Cafés{% endblock title %}
{% block content %} {% block content %}
<h1>Repair-Cafés</h1> <h1 class="mt-2">Repair-Cafés</h1>
<hr class="mt-0 mb-4">
<ul class="list-group"> <ul class="list-group">
{% for cafe in object_list %} {% for cafe in object_list %}
<li class="list-group-item"> <li class="list-group-item">

View file

@ -1,30 +1,15 @@
{% extends "repapp/base.html" %} {% extends "repapp/base.html" %}
{% load crispy_forms_tags %}
{% block title %}- Gerät anmelden{% endblock title %} {% block title %}- Gerät anmelden{% endblock title %}
{% block content %} {% block content %}
<h1 class="mt-2">Gerät anmelden</h1>
<hr class="mt-0 mb-4">
<form action="{% url 'register_device' cafe.id %}" method="post"> <form action="{% url 'register_device' cafe.id %}" method="post">
{% csrf_token %} {% csrf_token %}
<div class="mb-3"> {{ form|crispy }}
<label for="email_address" class="form-label">eMail Adresse</label>
<input type="text" class="form-control" id="email_address" name="email_address" aria-describedby="email_help">
<div id="email_help" class="form-text">Diese eMail-Adresse wird für Aktualisierungen zur Anfrage verwendet.</div>
</div>
<div class="mb-3">
<label for="device" class="form-label">Gerätebezeichnung</label>
<input type="text" class="form-control" id="device" name="device" aria-describedby="device_help">
<div id="device_help" class="form-text">Bitte geben Sie den Hersteller und die Gerätebezeichnung an.</div>
</div>
<div class="mb-3">
<label for="issue" class="form-label">Fehlerbeschreibung</label>
<textarea rows="6" cols="60" class="form-control" id="issue" name="issue" aria-describedby="issue_help"></textarea>
<div id="issue_help" class="form-text">Beschreiben Sie hier das Problem ihres Gerätes.</div>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="follow_up" name="follow_up" aria-describedby="follow_up_help">
<label class="form-check-label" for="follow_up">Folgetermin</label>
<div id="follow_up_help" class="form-text">Klicken Sie dieses Kästchen an wenn sie mit diesem Gerät bereits bei einem Repair-Café waren.</div>
</div>
<button type="submit" class="btn btn-primary">Absenden</button> <button type="submit" class="btn btn-primary">Absenden</button>
</form> </form>
{% endblock content %} {% endblock content %}

View file

@ -0,0 +1,12 @@
{% extends "repapp/base.html" %}
{% block title %}{% endblock title %}
{% block content %}
<h1 class="mt-2">Bestätigung ihrer Daten</h1>
<hr class="mt-0 mb-4">
<p>
Wir haben ihnen eine eMail mit ihren Daten gesendet. Bitte bestätigen
Sie ihre Anmeldung durch Klick auf den Link in der eMail.
</p>
{% endblock content %}

View file

@ -0,0 +1,15 @@
{% extends "repapp/base.html" %}
{% load crispy_forms_tags %}
{% block title %}- Gast anmelden{% endblock title %}
{% block content %}
<h1 class="mt-2">Ihre Daten</h1>
<hr class="mt-0 mb-4">
<form action="{% url 'register_guest' cafe.id device.identifier mail %}" method="post">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Absenden</button>
</form>
{% endblock content %}

View file

@ -7,5 +7,16 @@ from . import views
urlpatterns = [ urlpatterns = [
path("", views.IndexView.as_view(), name="index"), path("", views.IndexView.as_view(), name="index"),
path("<int:cafe_id>/", views.register_device, name="register_device"), path(
"cafe/<int:cafe_id>/",
views.RegisterDeviceFormView.as_view(),
name="register_device"
),
path(
"cafe/<int:cafe_id>/device/<str:device_identifier>/<str:mail>",
views.RegisterGuestFormView.as_view(),
name="register_guest"
),
path("cafe/<int:cafe_id>/device/<str:device_identifier>/guest/<str:guest_identifier>",
views.register_device_final, name="register_device_final"),
] ]

View file

@ -2,10 +2,13 @@
Views of RepApp. Views of RepApp.
""" """
import datetime import datetime
from django.shortcuts import get_object_or_404, render from hashlib import sha256
from django.http import HttpResponse, HttpResponseRedirect
from django.views import generic from django.views import generic
from .models import Cafe, Guest, Device from django.urls import reverse_lazy
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from .models import Cafe, Device, Guest
from .forms import RegisterDevice, RegisterGuest
class IndexView(generic.ListView): class IndexView(generic.ListView):
@ -18,20 +21,118 @@ class IndexView(generic.ListView):
return Cafe.objects.filter(event_date__gte=datetime.date.today()) return Cafe.objects.filter(event_date__gte=datetime.date.today())
def register_device(request, cafe_id): class RegisterDeviceFormView(generic.edit.FormView):
if request.method == "POST": template_name = "repapp/register_device.html"
mail = request.POST.get('email_address', '') form_class = RegisterDevice
device = request.POST.get('device', '')
issue = request.POST.get('issue', ''), def form_valid(self, form):
follow_up = request.POST.get('follow_up', 'false') == 'on' cafe_id = self.kwargs['cafe_id']
return HttpResponse(f"{mail} {device} {issue} {follow_up}")
# return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))
else:
cafe = get_object_or_404(Cafe, pk=cafe_id) cafe = get_object_or_404(Cafe, pk=cafe_id)
mail = form.cleaned_data['mail']
device = form.cleaned_data['device']
identifier = sha256(
f'{device}{mail}{datetime.datetime.now()}'.encode('utf-8')
).hexdigest()
device = Device(
identifier=identifier,
device=device,
error=form.cleaned_data['error'],
follow_up=form.cleaned_data['follow_up'],
)
device.save()
guest = Guest.objects.filter(mail=mail).first()
if guest:
device.guest_id = guest
device.save()
return HttpResponseRedirect(
reverse_lazy('register_device_final', kwargs={
'cafe_id': cafe.pk,
'device_identifier': device.identifier,
'guest_identifier': guest.identifier})
)
else:
return HttpResponseRedirect(
reverse_lazy('register_guest', kwargs={
'cafe_id': cafe.pk,
'device_identifier': device.identifier,
'mail': mail})
)
def get_context_data(self, **kwargs):
cafe_id = self.kwargs['cafe_id']
cafe = get_object_or_404(Cafe, pk=cafe_id)
context = super(RegisterDeviceFormView, self).get_context_data(
**kwargs
)
context["cafe"] = cafe
return context
class RegisterGuestFormView(generic.edit.FormView):
template_name = "repapp/register_guest.html"
form_class = RegisterGuest
def form_valid(self, form):
cafe_id = self.kwargs['cafe_id']
cafe = get_object_or_404(Cafe, pk=cafe_id)
device_identifier = self.kwargs['device_identifier']
device = get_object_or_404(Device, identifier=device_identifier)
name = form.cleaned_data['name']
residence = form.cleaned_data['residence']
identifier = sha256(
f'{name}{residence}{datetime.datetime.now()}'.encode('utf-8')
).hexdigest()
guest = Guest(
identifier=identifier,
name=name,
phone=form.cleaned_data['phone'],
residence=residence,
mail=self.kwargs['mail'],
)
guest.save()
device.guest_id = guest
device.save()
return HttpResponseRedirect(
reverse_lazy('register_device_final', kwargs={
'cafe_id': cafe.pk,
'device_identifier': device.identifier,
'guest_identifier': guest.identifier})
)
def get_context_data(self, **kwargs):
cafe_id = self.kwargs['cafe_id']
cafe = get_object_or_404(Cafe, pk=cafe_id)
device_identifier = self.kwargs['device_identifier']
device = get_object_or_404(Device, identifier=device_identifier)
context = super(RegisterGuestFormView, self).get_context_data(
**kwargs
)
context["cafe"] = cafe
context["device"] = device
context["mail"] = self.kwargs['mail']
return context
def register_device_final(request, cafe_id, device_identifier, guest_identifier):
cafe = get_object_or_404(Cafe, pk=cafe_id)
device = get_object_or_404(Device, identifier=device_identifier)
guest = get_object_or_404(Guest, identifier=guest_identifier)
print(cafe)
print(device)
print(guest)
return render( return render(
request, request,
"repapp/register_device.html", "repapp/register_device_final.html",
{ {},
"cafe": cafe,
},
) )

View file

@ -4,3 +4,5 @@ pep8==1.7.1
pylint==2.17.2 pylint==2.17.2
pylint-django==2.5.3 pylint-django==2.5.3
pylint-plugin-utils==0.7 pylint-plugin-utils==0.7
django-crispy-forms==2.0
crispy-bootstrap4==2022.1

View file

@ -1,2 +1,4 @@
Django==4.2 Django==4.2
gunicorn==20.1.0 gunicorn==20.1.0
django-crispy-forms==2.0
crispy-bootstrap4==2022.1