feat: reformatted some templates and new filter for TicketListView
This commit is contained in:
@@ -1,56 +1,60 @@
|
|||||||
|
{% load static %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<style>
|
<!DOCTYPE html>
|
||||||
.login-container {
|
<head>
|
||||||
max-width: 400px;
|
<link href="{% static 'css/tailwind.css' %}" rel="stylesheet">
|
||||||
margin: 4rem auto;
|
</head>
|
||||||
padding: 2rem;
|
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4">
|
||||||
border: 1px solid #ccc;
|
<div class="max-w-md w-full space-y-8">
|
||||||
border-radius: 8px;
|
<div class="text-center">
|
||||||
background: #f9f9f9;
|
<div class="text-6xl mb-4">🔐</div>
|
||||||
font-family: sans-serif;
|
<h2 class="text-3xl font-bold text-gray-900 mb-2">Anmelden</h2>
|
||||||
}
|
<p class="text-gray-600 mb-8">Melde dich in deinem Ticketsystem an</p>
|
||||||
|
</div>
|
||||||
.login-container h2 {
|
<div class="bg-white rounded-lg shadow-md p-8">
|
||||||
text-align: center;
|
<form method="post" class="space-y-6">
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-container label {
|
|
||||||
display: block;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-container input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.5rem;
|
|
||||||
margin-top: 0.3rem;
|
|
||||||
border: 1px solid #bbb;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-container button {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.6rem;
|
|
||||||
background-color: #007bff;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-container .errorlist {
|
|
||||||
color: red;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="login-container">
|
|
||||||
<h2>🔐 Login</h2>
|
|
||||||
<form method="post">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.as_p }}
|
<!-- Form Errors -->
|
||||||
<button type="submit">Anmelden</button>
|
{% if form.non_field_errors %}
|
||||||
|
<div class="bg-red-100 border border-red-200 rounded p-3">
|
||||||
|
{% for error in form.non_field_errors %}<div class="text-red-700 text-sm">{{ error }}</div>{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
<label for="id_username"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1">Benutzername:</label>
|
||||||
|
<input type="text"
|
||||||
|
name="username"
|
||||||
|
id="id_username"
|
||||||
|
value="{{ form.username.value|default:'' }}"
|
||||||
|
required
|
||||||
|
class="w-full p-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
placeholder="Gib deinen Benutzernamen ein">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="id_password"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1">Passwort:</label>
|
||||||
|
<input type="password"
|
||||||
|
name="password"
|
||||||
|
id="id_password"
|
||||||
|
required
|
||||||
|
class="w-full p-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
placeholder="Gib dein Passwort ein">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type="submit"
|
||||||
|
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
||||||
|
🚀 Anmelden
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<div class="mt-6 text-center">
|
||||||
|
<p class="text-sm text-gray-600">
|
||||||
|
Noch keinen Account?
|
||||||
|
<a href="#" class="text-blue-600 hover:text-blue-800 font-medium">Kontaktiere uns</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,45 +1,53 @@
|
|||||||
{% extends "ticketsystem/base.html" %}
|
{% extends "ticketsystem/base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<style>
|
<div class="max-w-4xl mx-auto px-4 py-12">
|
||||||
.home-container {
|
<!-- Header -->
|
||||||
max-width: 800px;
|
<div class="text-center mb-12">
|
||||||
margin: 3rem auto;
|
<div class="text-6xl mb-4">🎫</div>
|
||||||
text-align: center;
|
<h1 class="text-4xl font-bold text-gray-900 mb-4">Willkommen im Ticketsystem</h1>
|
||||||
font-family: sans-serif;
|
<p class="text-lg text-gray-600 mb-2">Verwalte deine Aufgaben und Tickets effizient</p>
|
||||||
}
|
<p class="text-gray-500">Was möchten Sie tun?</p>
|
||||||
.home-container h1 {
|
</div>
|
||||||
font-size: 2rem;
|
<!-- Quick Actions -->
|
||||||
margin-bottom: 1rem;
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
|
||||||
}
|
<!-- Alle Tickets -->
|
||||||
.actions {
|
<a href="{% url 'ticket-list' %}"
|
||||||
display: flex;
|
class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition-shadow duration-200 border border-gray-200">
|
||||||
flex-wrap: wrap;
|
<div class="text-3xl mb-3">📄</div>
|
||||||
justify-content: center;
|
<h3 class="text-lg font-bold text-gray-900 mb-2">Alle Tickets</h3>
|
||||||
gap: 1rem;
|
<p class="text-sm text-gray-600">Übersicht aller Tickets anzeigen</p>
|
||||||
margin-top: 2rem;
|
</a>
|
||||||
}
|
<!-- Neues Ticket -->
|
||||||
.actions a {
|
<a href="{% url 'create' %}"
|
||||||
padding: 1rem 2rem;
|
class="bg-green-50 rounded-lg shadow-md p-6 text-center hover:shadow-lg transition-shadow duration-200 border border-green-200">
|
||||||
background: #007bff;
|
<div class="text-3xl mb-3">➕</div>
|
||||||
color: white;
|
<h3 class="text-lg font-bold text-green-800 mb-2">Neues Ticket</h3>
|
||||||
border-radius: 8px;
|
<p class="text-sm text-green-600">Ein neues Ticket erstellen</p>
|
||||||
text-decoration: none;
|
</a>
|
||||||
font-weight: bold;
|
<!-- Offene Tickets -->
|
||||||
transition: background 0.2s ease;
|
<a href="{% url 'ticket-list' %}?status=open"
|
||||||
}
|
class="bg-blue-50 rounded-lg shadow-md p-6 text-center hover:shadow-lg transition-shadow duration-200 border border-blue-200">
|
||||||
.actions a:hover {
|
<div class="text-3xl mb-3">📂</div>
|
||||||
background: #0056b3;
|
<h3 class="text-lg font-bold text-blue-800 mb-2">Offene Tickets</h3>
|
||||||
}
|
<p class="text-sm text-blue-600">Nur offene Tickets anzeigen</p>
|
||||||
</style>
|
</a>
|
||||||
|
</div>
|
||||||
<div class="home-container">
|
<div class="bg-gray-50 rounded-lg p-6 text-center">
|
||||||
<h1>Willkommen im Korrekturmanagementsystem 🎫</h1>
|
<h2 class="text-xl font-bold text-gray-900 mb-4">📊 Übersicht</h2>
|
||||||
<p>Was möchten Sie tun?</p>
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||||
|
<div class="bg-white rounded-lg p-4 shadow-sm">
|
||||||
<div class="actions">
|
<div class="text-2xl font-bold text-blue-600 mb-1">{{ total_tickets|default:"0" }}</div>
|
||||||
<a href="{% url 'ticket-list' %}">📄 Alle Tickets anzeigen</a>
|
<div class="text-sm text-gray-600">Tickets insgesamt</div>
|
||||||
<a href="{% url 'create' %}">➕ Neues Ticket erstellen</a>
|
</div>
|
||||||
<a href="{% url 'ticket-list' %}?status=open">📂 Offene Tickets</a>
|
<div class="bg-white rounded-lg p-4 shadow-sm">
|
||||||
|
<div class="text-2xl font-bold text-red-600 mb-1">{{ open_tickets|default:"0" }}</div>
|
||||||
|
<div class="text-sm text-gray-600">Offene Tickets</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white rounded-lg p-4 shadow-sm">
|
||||||
|
<div class="text-2xl font-bold text-green-600 mb-1">{{ closed_tickets|default:"0" }}</div>
|
||||||
|
<div class="text-sm text-gray-600">Erledigte Tickets</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
{% extends "ticketsystem/base.html" %}
|
{% extends "ticketsystem/base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<!-- Messages -->
|
||||||
<!-- Messages -->
|
{% if messages %}
|
||||||
{% if messages %}
|
<div class="max-w-6xl mx-auto px-4 pt-4">
|
||||||
<div class="max-w-6xl mx-auto px-4 pt-4">
|
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
<div class="mb-4 p-3 rounded {% if message.tags == 'error' %}bg-red-100 text-red-700{% elif message.tags == 'success' %}bg-green-100 text-green-700{% else %}bg-yellow-100 text-yellow-700{% endif %}">
|
<div class="mb-4 p-3 rounded {% if message.tags == 'error' %}bg-red-100 text-red-700{% elif message.tags == 'success' %}bg-green-100 text-green-700{% else %}bg-yellow-100 text-yellow-700{% endif %}">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="max-w-6xl mx-auto px-4 py-6">
|
||||||
<div class="max-w-6xl mx-auto px-4 py-6">
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-6">
|
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-6">
|
||||||
<div>
|
<div>
|
||||||
@@ -26,53 +24,105 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Filter und Suche -->
|
<!-- Filter und Suche -->
|
||||||
<div class="bg-white rounded-lg shadow p-4 mb-6">
|
<div class="bg-white rounded-lg shadow p-4 mb-6">
|
||||||
<div class="flex flex-col lg:flex-row gap-4">
|
<div class="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
||||||
<!-- Status Filter -->
|
<!-- Status Filter -->
|
||||||
<div class="flex-1">
|
<div>
|
||||||
<form method="get">
|
<form method="get">
|
||||||
<label class="block text-sm font-medium mb-1">Status:</label>
|
<label class="block text-sm font-medium mb-1">Status:</label>
|
||||||
<select name="status" onchange="this.form.submit()"
|
<select name="status"
|
||||||
class="w-full p-2 border border-gray-300 rounded shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
onchange="this.form.submit()"
|
||||||
|
class="w-full h-10 px-3 border border-gray-300 rounded shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||||
<option value="">Alle Status</option>
|
<option value="">Alle Status</option>
|
||||||
<option value="open" {% if selected_status == "open" %}selected{% endif %}>🔴 Offen</option>
|
<option value="open" {% if selected_status == "open" %}selected{% endif %}>🔴 Offen</option>
|
||||||
<option value="in_progress" {% if selected_status == "in_progress" %}selected{% endif %}>🟡 In Bearbeitung</option>
|
<option value="in_progress"
|
||||||
<option value="closed" {% if selected_status == "closed" %}selected{% endif %}>🟢 Erledigt</option>
|
{% if selected_status == "in_progress" %}selected{% endif %}>
|
||||||
|
🟡 In Bearbeitung
|
||||||
|
</option>
|
||||||
|
<option value="closed"
|
||||||
|
{% if selected_status == "closed" %}selected{% endif %}>🟢 Erledigt</option>
|
||||||
</select>
|
</select>
|
||||||
|
<!-- Andere Filter beibehalten -->
|
||||||
|
{% if request.GET.assigned_to %}
|
||||||
|
<input type="hidden"
|
||||||
|
name="assigned_to"
|
||||||
|
value="{{ request.GET.assigned_to }}">
|
||||||
|
{% endif %}
|
||||||
|
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Meine Tickets Filter -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium mb-1">Zuweisung:</label>
|
||||||
|
{% if request.GET.assigned_to == user.id|stringformat:'s' %}
|
||||||
|
<!-- Wenn aktiv: Button zum Deaktivieren -->
|
||||||
|
<a href="?{% if selected_status %}status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
|
||||||
|
class="block w-full h-10 px-3 border border-purple-300 rounded shadow-sm text-center bg-purple-200 hover:bg-purple-300 transition-colors flex items-center justify-center">
|
||||||
|
👤 Meine Tickets ✓
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<!-- Wenn nicht aktiv: Button zum Aktivieren -->
|
||||||
|
<a href="?assigned_to={{ user.id }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
|
||||||
|
class="block w-full h-10 px-3 border border-purple-300 rounded shadow-sm text-center bg-purple-50 hover:bg-purple-100 transition-colors flex items-center justify-center">
|
||||||
|
👤 Meine Tickets
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
<!-- Suche -->
|
<!-- Suche -->
|
||||||
<div class="flex-1 lg:flex-2">
|
<div class="lg:col-span-2">
|
||||||
<form method="get">
|
<form method="get">
|
||||||
<label class="block text-sm font-medium mb-1">Suche:</label>
|
<label class="block text-sm font-medium mb-1">Suche:</label>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<input type="text" name="q" value="{{ search_query }}"
|
<input type="text"
|
||||||
|
name="q"
|
||||||
|
value="{{ search_query }}"
|
||||||
placeholder="Titel oder Beschreibung durchsuchen..."
|
placeholder="Titel oder Beschreibung durchsuchen..."
|
||||||
class="flex-1 p-2 border border-gray-300 rounded-l shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
class="flex-1 h-10 px-3 border border-gray-300 rounded-l shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||||
{% if selected_status %}
|
{% if selected_status %}<input type="hidden" name="status" value="{{ selected_status }}">{% endif %}
|
||||||
<input type="hidden" name="status" value="{{ selected_status }}">
|
{% if request.GET.assigned_to %}
|
||||||
|
<input type="hidden"
|
||||||
|
name="assigned_to"
|
||||||
|
value="{{ request.GET.assigned_to }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-r">
|
class="bg-blue-500 hover:bg-blue-600 text-white h-10 px-4 rounded-r">🔍</button>
|
||||||
🔍
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<!-- Aktive Filter Anzeige -->
|
||||||
|
{% if selected_status or request.GET.assigned_to or search_query %}
|
||||||
<!-- Suchergebnisse Info -->
|
<div class="mt-4 p-3 bg-gray-50 rounded border-l-4 border-blue-400">
|
||||||
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
|
<span class="font-medium text-gray-700">Aktive Filter:</span>
|
||||||
|
{% if selected_status %}
|
||||||
|
<span class="px-2 py-1 bg-blue-100 text-blue-800 text-sm rounded">
|
||||||
|
Status: {{ selected_status|title }}
|
||||||
|
<a href="?{% if search_query %}q={{ search_query }}{% endif %}{% if request.GET.assigned_to %}&assigned_to={{ request.GET.assigned_to }}{% endif %}"
|
||||||
|
class="ml-1 text-blue-600 hover:text-blue-800">×</a>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if request.GET.assigned_to %}
|
||||||
|
<span class="px-2 py-1 bg-purple-100 text-purple-800 text-sm rounded">
|
||||||
|
Meine Tickets
|
||||||
|
<a href="?{% if selected_status %}status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
|
||||||
|
class="ml-1 text-purple-600 hover:text-purple-800">×</a>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
{% if search_query %}
|
{% if search_query %}
|
||||||
<div class="mb-4 p-3 bg-blue-100 border-l-4 border-blue-400 rounded">
|
<span class="px-2 py-1 bg-green-100 text-green-800 text-sm rounded">
|
||||||
<span class="font-medium">Suchergebnisse für:</span> „{{ search_query }}"
|
Suche: "{{ search_query }}"
|
||||||
<a href="?" class="ml-4 text-blue-600 hover:text-blue-800">Suche zurücksetzen</a>
|
<a href="?{% if selected_status %}status={{ selected_status }}{% endif %}{% if request.GET.assigned_to %}&assigned_to={{ request.GET.assigned_to }}{% endif %}"
|
||||||
|
class="ml-1 text-green-600 hover:text-green-800">×</a>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
<a href="{% url 'ticket-list' %}"
|
||||||
|
class="text-sm text-gray-600 hover:text-gray-800 font-medium">Alle Filter entfernen</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
<!-- Ticket Tabelle -->
|
<!-- Ticket Tabelle -->
|
||||||
{% if tickets %}
|
{% if tickets %}
|
||||||
<div class="bg-white rounded-lg shadow overflow-hidden">
|
<div class="bg-white rounded-lg shadow overflow-hidden">
|
||||||
@@ -90,9 +140,7 @@
|
|||||||
<tbody class="divide-y divide-gray-200">
|
<tbody class="divide-y divide-gray-200">
|
||||||
{% for ticket in tickets %}
|
{% for ticket in tickets %}
|
||||||
<tr class="hover:bg-gray-50">
|
<tr class="hover:bg-gray-50">
|
||||||
<td class="px-4 py-3 text-center text-sm font-bold text-gray-500">
|
<td class="px-4 py-3 text-center text-sm font-bold text-gray-500">#{{ ticket.id }}</td>
|
||||||
#{{ ticket.id }}
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-3">
|
<td class="px-4 py-3">
|
||||||
<a href="{% url 'detail' ticket.pk %}"
|
<a href="{% url 'detail' ticket.pk %}"
|
||||||
class="font-bold text-blue-600 hover:text-blue-800 hover:underline">
|
class="font-bold text-blue-600 hover:text-blue-800 hover:underline">
|
||||||
@@ -101,24 +149,18 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-center">
|
<td class="px-4 py-3 text-center">
|
||||||
{% if ticket.status == 'open' %}
|
{% if ticket.status == 'open' %}
|
||||||
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">
|
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">{{ ticket.get_status_display }}</span>
|
||||||
{{ ticket.get_status_display }}
|
|
||||||
</span>
|
|
||||||
{% elif ticket.status == 'in_progress' %}
|
{% elif ticket.status == 'in_progress' %}
|
||||||
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
|
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
|
||||||
{{ ticket.get_status_display }}
|
{{ ticket.get_status_display }}
|
||||||
</span>
|
</span>
|
||||||
{% elif ticket.status == 'closed' %}
|
{% elif ticket.status == 'closed' %}
|
||||||
<span class="px-2 py-1 rounded-full text-xs font-bold bg-green-500 text-white">
|
<span class="px-2 py-1 rounded-full text-xs font-bold bg-green-500 text-white">{{ ticket.get_status_display }}</span>
|
||||||
{{ ticket.get_status_display }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-center">
|
<td class="px-4 py-3 text-center">
|
||||||
{% if ticket.priority == 'low' %}
|
{% if ticket.priority == 'low' %}
|
||||||
<span class="px-2 py-1 rounded-full text-xs font-bold bg-blue-500 text-white">
|
<span class="px-2 py-1 rounded-full text-xs font-bold bg-blue-500 text-white">{{ ticket.get_priority_display }}</span>
|
||||||
{{ ticket.get_priority_display }}
|
|
||||||
</span>
|
|
||||||
{% elif ticket.priority == 'medium' %}
|
{% elif ticket.priority == 'medium' %}
|
||||||
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
|
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
|
||||||
{{ ticket.get_priority_display }}
|
{{ ticket.get_priority_display }}
|
||||||
@@ -128,9 +170,7 @@
|
|||||||
{{ ticket.get_priority_display }}
|
{{ ticket.get_priority_display }}
|
||||||
</span>
|
</span>
|
||||||
{% elif ticket.priority == 'urgent' %}
|
{% elif ticket.priority == 'urgent' %}
|
||||||
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">
|
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">{{ ticket.get_priority_display }}</span>
|
||||||
{{ ticket.get_priority_display }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-sm text-gray-600">
|
<td class="px-4 py-3 text-sm text-gray-600">
|
||||||
@@ -149,13 +189,10 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pagination -->
|
<!-- Pagination -->
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<div class="mt-6 flex justify-between items-center">
|
<div class="mt-6 flex justify-between items-center">
|
||||||
<div class="text-sm text-gray-600">
|
<div class="text-sm text-gray-600">Seite {{ page_obj.number }} von {{ page_obj.paginator.num_pages }}</div>
|
||||||
Seite {{ page_obj.number }} von {{ page_obj.paginator.num_pages }}
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
{% if page_obj.has_previous %}
|
{% if page_obj.has_previous %}
|
||||||
<a href="?page={{ page_obj.previous_page_number }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
|
<a href="?page={{ page_obj.previous_page_number }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
|
||||||
@@ -168,7 +205,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<!-- Keine Tickets -->
|
<!-- Keine Tickets -->
|
||||||
<div class="text-center py-12 bg-white rounded-lg shadow">
|
<div class="text-center py-12 bg-white rounded-lg shadow">
|
||||||
@@ -178,9 +214,7 @@
|
|||||||
<p class="text-gray-500 mb-4">
|
<p class="text-gray-500 mb-4">
|
||||||
Keine Tickets gefunden für die Suche „<strong>{{ search_query }}</strong>"
|
Keine Tickets gefunden für die Suche „<strong>{{ search_query }}</strong>"
|
||||||
</p>
|
</p>
|
||||||
<a href="?" class="text-blue-600 hover:text-blue-800 font-medium">
|
<a href="?" class="text-blue-600 hover:text-blue-800 font-medium">Alle Tickets anzeigen</a>
|
||||||
Alle Tickets anzeigen
|
|
||||||
</a>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<h3 class="text-lg font-medium text-gray-900 mb-2">Noch keine Tickets vorhanden</h3>
|
<h3 class="text-lg font-medium text-gray-900 mb-2">Noch keine Tickets vorhanden</h3>
|
||||||
<p class="text-gray-500 mb-4">Erstelle dein erstes Ticket um loszulegen.</p>
|
<p class="text-gray-500 mb-4">Erstelle dein erstes Ticket um loszulegen.</p>
|
||||||
@@ -191,6 +225,5 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from . import views
|
|
||||||
from .views import (
|
from .views import (
|
||||||
TicketListView,
|
TicketListView,
|
||||||
TicketCreateView,
|
TicketCreateView,
|
||||||
|
|||||||
@@ -16,6 +16,16 @@ from .models import Ticket, TicketHistory
|
|||||||
class HomeView(TemplateView):
|
class HomeView(TemplateView):
|
||||||
template_name = "ticketsystem/home.html"
|
template_name = "ticketsystem/home.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({
|
||||||
|
'total_tickets': Ticket.objects.count(),
|
||||||
|
'open_tickets': Ticket.objects.filter(status='open').count(),
|
||||||
|
'closed_tickets': Ticket.objects.filter(status='closed').count(),
|
||||||
|
'recent_tickets': Ticket.objects.order_by('-updated_at')[:5],
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class TicketListView(ListView):
|
class TicketListView(ListView):
|
||||||
model = Ticket
|
model = Ticket
|
||||||
@@ -27,11 +37,13 @@ class TicketListView(ListView):
|
|||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
status = self.request.GET.get("status")
|
status = self.request.GET.get("status")
|
||||||
|
assigned_to = self.request.GET.get("assigned_to")
|
||||||
query = self.request.GET.get("q")
|
query = self.request.GET.get("q")
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
queryset = queryset.filter(status=status)
|
queryset = queryset.filter(status=status)
|
||||||
|
if assigned_to:
|
||||||
|
queryset = queryset.filter(assigned_to_id=assigned_to)
|
||||||
if query:
|
if query:
|
||||||
queryset = queryset.filter(
|
queryset = queryset.filter(
|
||||||
Q(title__icontains=query) | Q(description__icontains=query)
|
Q(title__icontains=query) | Q(description__icontains=query)
|
||||||
|
|||||||
Reference in New Issue
Block a user