From 51bf409e3c9abe7fe4d8b780b4ee2c55e172bdd9 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 30 May 2025 00:04:35 +0200 Subject: [PATCH] feat: added faqs --- ticketsystem/admin.py | 3 +- ticketsystem/models.py | 16 ++++ ticketsystem/templates/ticketsystem/base.html | 4 +- ticketsystem/templates/ticketsystem/faq.html | 24 ++++++ ticketsystem/urls.py | 4 + ticketsystem/views.py | 77 ++++++++++++++++++- 6 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 ticketsystem/templates/ticketsystem/faq.html diff --git a/ticketsystem/admin.py b/ticketsystem/admin.py index f474898..d7940ea 100644 --- a/ticketsystem/admin.py +++ b/ticketsystem/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin -from .models import Ticket, Course +from .models import Ticket, Course, FAQ admin.site.register(Ticket) admin.site.register(Course) +admin.site.register(FAQ) diff --git a/ticketsystem/models.py b/ticketsystem/models.py index 5dc3b52..b982d60 100644 --- a/ticketsystem/models.py +++ b/ticketsystem/models.py @@ -95,3 +95,19 @@ class TicketHistory(models.Model): class Meta: ordering = ["-changed_at"] + + +class FAQ(models.Model): + """Einfaches FAQ Model""" + question = models.CharField(max_length=300, verbose_name="Frage") + answer = models.TextField(verbose_name="Antwort") + order = models.IntegerField(default=0, verbose_name="Reihenfolge") + is_active = models.BooleanField(default=True, verbose_name="Aktiv") + + class Meta: + ordering = ['order', 'question'] + verbose_name = "FAQ" + verbose_name_plural = "FAQs" + + def __str__(self): + return self.question \ No newline at end of file diff --git a/ticketsystem/templates/ticketsystem/base.html b/ticketsystem/templates/ticketsystem/base.html index d352666..ee1eb7e 100644 --- a/ticketsystem/templates/ticketsystem/base.html +++ b/ticketsystem/templates/ticketsystem/base.html @@ -16,6 +16,7 @@ đź“‹ Tickets đź§ľ Meine Tickets + âť“ FAQ
{% if user.is_authenticated %} @@ -30,8 +31,7 @@
- {% block content %} - {% endblock %} + {% block content %}{% endblock %}
diff --git a/ticketsystem/templates/ticketsystem/faq.html b/ticketsystem/templates/ticketsystem/faq.html new file mode 100644 index 0000000..086784b --- /dev/null +++ b/ticketsystem/templates/ticketsystem/faq.html @@ -0,0 +1,24 @@ +{% extends "ticketsystem/base.html" %} +{% block content %} +
+ +
+
+

❓ Häufig gestellte Fragen

+ đź“„ PDF Download +
+
+ + {% for faq in faqs %} +
+

{{ forloop.counter }}. {{ faq.question }}

+
{{ faq.answer|linebreaks }}
+
+ {% empty %} +
+

Noch keine FAQs vorhanden.

+
+ {% endfor %} +
+{% endblock %} diff --git a/ticketsystem/urls.py b/ticketsystem/urls.py index 50625df..273f2d2 100644 --- a/ticketsystem/urls.py +++ b/ticketsystem/urls.py @@ -7,6 +7,8 @@ from .views import ( HomeView, AssignedTicketListView, TicketDetailUpdateView, + faq_list, + faq_pdf_download ) urlpatterns = [ @@ -20,4 +22,6 @@ urlpatterns = [ path("new/", TicketCreateView.as_view(), name="create"), path("/modify/", TicketUpdateView.as_view(), name="modify"), path("meine-tickets/", AssignedTicketListView.as_view(), name="assigned-tickets"), + path('faq/', faq_list, name='faq-list'), + path('faq/download/', faq_pdf_download, name='faq-pdf-download'), ] diff --git a/ticketsystem/views.py b/ticketsystem/views.py index 9a70f56..58227eb 100644 --- a/ticketsystem/views.py +++ b/ticketsystem/views.py @@ -7,10 +7,16 @@ from .forms import CommentForm, TicketForm from django.urls import reverse from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib import messages -from django.shortcuts import redirect +from django.shortcuts import redirect, render from django.db.models import Q +from django.http import HttpResponse +from reportlab.lib.pagesizes import A4 +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.lib.units import cm +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer +from reportlab.lib.enums import TA_LEFT, TA_CENTER -from .models import Ticket, TicketHistory +from .models import Ticket, TicketHistory, FAQ class HomeView(TemplateView): @@ -239,3 +245,70 @@ class TicketUpdateView(LoginRequiredMixin, UpdateView): def get_success_url(self): return reverse_lazy("detail", kwargs={"pk": self.object.pk}) + + +def faq_list(request): + """Zeigt alle aktiven FAQs an""" + faqs = FAQ.objects.filter(is_active=True) + return render(request, 'ticketsystem/faq.html', {'faqs': faqs}) + + +def faq_pdf_download(request): + """Generiert PDF mit allen FAQs""" + # Response Setup + response = HttpResponse(content_type='application/pdf') + response['Content-Disposition'] = 'attachment; filename="FAQ_Ticketsystem.pdf"' + + # PDF erstellen + doc = SimpleDocTemplate(response, pagesize=A4, topMargin=2 * cm, bottomMargin=2 * cm) + + # Styles + styles = getSampleStyleSheet() + title_style = ParagraphStyle( + 'CustomTitle', + parent=styles['Heading1'], + fontSize=24, + textColor='#1a1a1a', + spaceAfter=30, + alignment=TA_CENTER + ) + question_style = ParagraphStyle( + 'Question', + parent=styles['Heading2'], + fontSize=14, + textColor='#2563eb', + spaceAfter=10 + ) + answer_style = ParagraphStyle( + 'Answer', + parent=styles['Normal'], + fontSize=11, + spaceAfter=20, + alignment=TA_LEFT + ) + + # Content + elements = [] + + # Titel + elements.append(Paragraph("Häufig gestellte Fragen (FAQ)", title_style)) + elements.append(Spacer(1, 20)) + + # FAQs holen + faqs = FAQ.objects.filter(is_active=True) + + # FAQs hinzufügen + for i, faq in enumerate(faqs, 1): + # Frage + elements.append(Paragraph(f"{i}. {faq.question}", question_style)) + + # Antwort + elements.append(Paragraph(faq.answer.replace('\n', '
'), answer_style)) + + # Abstand zwischen FAQs + elements.append(Spacer(1, 10)) + + # PDF generieren + doc.build(elements) + + return response \ No newline at end of file