Merge branch '143-zeitangabe-fur-quizze' into 'master'
Resolve "Zeitangabe für Quizze" Closes #143 See merge request enrichment-2024/qivip!98
This commit is contained in:
@@ -56,6 +56,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'channels',
|
'channels',
|
||||||
'django_cleanup',
|
'django_cleanup',
|
||||||
|
'django.contrib.humanize',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import QivipQuiz, QivipQuestion, QivipQuizFavorite, QuestionImage, QuizCategory, QuizImage
|
from .models import QivipQuiz, QivipQuestion, QivipQuizFavorite, QuestionImage, QuizCategory, QuizImage, QuizRating
|
||||||
|
|
||||||
# Für das QivipQuiz Modell
|
# Für das QivipQuiz Modell
|
||||||
class QivipQuizAdmin(admin.ModelAdmin):
|
class QivipQuizAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name', 'user_id', 'status', 'category', 'creation_date', 'update_date') # Welche Felder sollen in der Übersicht angezeigt werden
|
list_display = ('name','published_at', 'user_id', 'status', 'category', 'creation_date', 'update_date') # Welche Felder sollen in der Übersicht angezeigt werden
|
||||||
search_fields = ('name', 'user_id__username', 'category__name') # Suchfelder
|
search_fields = ('name', 'user_id__username', 'category__name') # Suchfelder
|
||||||
list_filter = ('status', 'category') # Filteroptionen
|
list_filter = ('status', 'category') # Filteroptionen
|
||||||
# Für das QivipQuestion Modell
|
# Für das QivipQuestion Modell
|
||||||
|
|||||||
18
django/library/migrations/0055_qivipquiz_published_at.py
Normal file
18
django/library/migrations/0055_qivipquiz_published_at.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-06-26 16:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0054_qivipquestion_credits'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='qivipquiz',
|
||||||
|
name='published_at',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-06-27 12:35
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0055_qivipquiz_published_at'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='quizrating',
|
||||||
|
unique_together=set(),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -3,7 +3,7 @@ from django.contrib.auth.models import User
|
|||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
import uuid
|
import uuid
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
class QuizImage(models.Model):
|
class QuizImage(models.Model):
|
||||||
image = models.ImageField(max_length=256,verbose_name="Bild", upload_to='quiz_images/', blank=True, null=True) # Bild speichern in media/quiz_images/
|
image = models.ImageField(max_length=256,verbose_name="Bild", upload_to='quiz_images/', blank=True, null=True) # Bild speichern in media/quiz_images/
|
||||||
@@ -59,6 +59,10 @@ class QivipQuiz(models.Model):
|
|||||||
credits=models.TextField(blank=True, editable=True)
|
credits=models.TextField(blank=True, editable=True)
|
||||||
average_rating = models.FloatField(default=3.0)
|
average_rating = models.FloatField(default=3.0)
|
||||||
rating_count = models.IntegerField(default=0)
|
rating_count = models.IntegerField(default=0)
|
||||||
|
published_at = models.DateTimeField(null=True, blank=True) # manuell gesetzt, wenn veröffentlicht
|
||||||
|
|
||||||
|
def is_published(self):
|
||||||
|
return self.published_at is not None and self.published_at <= timezone.now()
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return self.name
|
return self.name
|
||||||
@@ -111,9 +115,22 @@ class QuizRating(models.Model):
|
|||||||
rating = models.IntegerField(choices=[(i, str(i)) for i in range(1, 6)])
|
rating = models.IntegerField(choices=[(i, str(i)) for i in range(1, 6)])
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
class Meta:
|
#class Meta:
|
||||||
unique_together = ('quiz', 'participant_id')
|
#unique_together = ('quiz', 'participant_id')
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
# Update quiz average rating (immer, auch bei Updates)
|
||||||
|
quiz = self.quiz
|
||||||
|
total_ratings = quiz.ratings.count()
|
||||||
|
avg_rating = quiz.ratings.aggregate(models.Avg('rating'))['rating__avg']
|
||||||
|
quiz.average_rating = round(avg_rating, 1) if avg_rating else 3.0
|
||||||
|
quiz.rating_count = total_ratings
|
||||||
|
quiz.save()
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
is_new = self.pk is None
|
is_new = self.pk is None
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
@@ -125,7 +142,7 @@ class QuizRating(models.Model):
|
|||||||
avg_rating = quiz.ratings.aggregate(models.Avg('rating'))['rating__avg']
|
avg_rating = quiz.ratings.aggregate(models.Avg('rating'))['rating__avg']
|
||||||
quiz.average_rating = round(avg_rating, 1) if avg_rating else 3.0
|
quiz.average_rating = round(avg_rating, 1) if avg_rating else 3.0
|
||||||
quiz.rating_count = total_ratings
|
quiz.rating_count = total_ratings
|
||||||
quiz.save()
|
quiz.save()"""
|
||||||
|
|
||||||
class QuizCategory(models.Model):
|
class QuizCategory(models.Model):
|
||||||
name = models.CharField(max_length=100, unique=True)
|
name = models.CharField(max_length=100, unique=True)
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ def favorite_quiz(request, pk):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if favorite.favorite==True:
|
if favorite.favorite==True:
|
||||||
favorite.favorite_date = timezone.now()
|
favorite.favorite_date = timezone.now()
|
||||||
favorite.save()
|
favorite.save()
|
||||||
@@ -347,10 +348,19 @@ def new_quiz(request):
|
|||||||
|
|
||||||
|
|
||||||
form = QuizForm(request.POST, request.FILES)
|
form = QuizForm(request.POST, request.FILES)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
quiz = form.save(commit=False)
|
quiz = form.save(commit=False)
|
||||||
|
status = form.cleaned_data.get('status')
|
||||||
|
|
||||||
|
if status == 'öffentlich' and not quiz.published_at:
|
||||||
|
quiz.published_at = timezone.now()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
quiz_image=request.FILES['quiz_image']
|
quiz_image=request.FILES['quiz_image']
|
||||||
|
|
||||||
imagequiz=QuizImage.objects.create(image=quiz_image)
|
imagequiz=QuizImage.objects.create(image=quiz_image)
|
||||||
quiz.image=imagequiz
|
quiz.image=imagequiz
|
||||||
|
|
||||||
@@ -359,6 +369,8 @@ def new_quiz(request):
|
|||||||
|
|
||||||
|
|
||||||
quiz.user_id = request.user
|
quiz.user_id = request.user
|
||||||
|
|
||||||
|
|
||||||
#quiz.creator = request.user
|
#quiz.creator = request.user
|
||||||
quiz.save()
|
quiz.save()
|
||||||
#form.save_m2m() # Speichert die Many-to-Many Beziehungen (Tags)
|
#form.save_m2m() # Speichert die Many-to-Many Beziehungen (Tags)
|
||||||
@@ -374,8 +386,13 @@ def edit_quiz(request, pk):
|
|||||||
quiz = get_object_or_404(QivipQuiz, pk=pk, user_id=request.user)
|
quiz = get_object_or_404(QivipQuiz, pk=pk, user_id=request.user)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = QuizForm(request.POST, instance=quiz, files=request.FILES)
|
form = QuizForm(request.POST, instance=quiz, files=request.FILES)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 'reset_image' in request.POST:
|
if 'reset_image' in request.POST:
|
||||||
quiz.image = None
|
quiz.image = None
|
||||||
|
|
||||||
@@ -388,7 +405,12 @@ def edit_quiz(request, pk):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
quiz = form.save(commit=False)
|
||||||
|
|
||||||
|
# Beispiel: Status aus dem Formular holen
|
||||||
|
status = form.cleaned_data.get('status')
|
||||||
|
if status == 'öffentlich' and not quiz.published_at:
|
||||||
|
quiz.published_at = timezone.now()
|
||||||
|
|
||||||
form.save()
|
form.save()
|
||||||
for img in QuizImage.objects.all():
|
for img in QuizImage.objects.all():
|
||||||
@@ -466,6 +488,7 @@ def copy_quiz(request, pk):
|
|||||||
new_quiz.base_quiz_id = pk
|
new_quiz.base_quiz_id = pk
|
||||||
new_quiz.rating_count = 0
|
new_quiz.rating_count = 0
|
||||||
new_quiz.average_rating = 3.0
|
new_quiz.average_rating = 3.0
|
||||||
|
new_quiz.published_at = timezone.now()
|
||||||
new_quiz.save() # Speichern als neues Objekt
|
new_quiz.save() # Speichern als neues Objekt
|
||||||
# Optional: Beschreibung anpassen
|
# Optional: Beschreibung anpassen
|
||||||
# Alle zugehörigen Fragen kopieren
|
# Alle zugehörigen Fragen kopieren
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ class GameConsumer(AsyncWebsocketConsumer):
|
|||||||
|
|
||||||
@database_sync_to_async
|
@database_sync_to_async
|
||||||
def save_rating(self, participant_id, rating):
|
def save_rating(self, participant_id, rating):
|
||||||
|
from django.db import models
|
||||||
if not settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM']:
|
if not settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM']:
|
||||||
return False
|
return False
|
||||||
from library.models import QuizRating
|
from library.models import QuizRating
|
||||||
@@ -275,16 +276,23 @@ class GameConsumer(AsyncWebsocketConsumer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Update or create rating
|
# Update or create rating
|
||||||
|
"""
|
||||||
rating_obj, created = QuizRating.objects.get_or_create(
|
rating_obj, created = QuizRating.objects.get_or_create(
|
||||||
quiz=game.quiz_id,
|
quiz=game.quiz_id,
|
||||||
participant_id=participant_id,
|
participant_id=participant_id,
|
||||||
defaults={'rating': rating}
|
defaults={'rating': rating}
|
||||||
)
|
)
|
||||||
|
"""
|
||||||
|
rating_obj=QuizRating.objects.create(
|
||||||
|
quiz=game.quiz_id,
|
||||||
|
participant_id=participant_id,
|
||||||
|
rating=rating)
|
||||||
|
|
||||||
if not created:
|
|
||||||
rating_obj.rating = rating
|
rating_obj.rating = rating
|
||||||
rating_obj.save()
|
rating_obj.save()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except (QuizGame.DoesNotExist, QuizGameParticipant.DoesNotExist):
|
except (QuizGame.DoesNotExist, QuizGameParticipant.DoesNotExist):
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -147,26 +147,7 @@ def join_game(request):
|
|||||||
messages.error(request, "Dieses Spiel existiert nicht.")
|
messages.error(request, "Dieses Spiel existiert nicht.")
|
||||||
return render(request, 'play/join_game.html')
|
return render(request, 'play/join_game.html')
|
||||||
|
|
||||||
def finished(request, join_code):
|
|
||||||
try:
|
|
||||||
game = QuizGame.objects.get(join_code=join_code)
|
|
||||||
participant = None
|
|
||||||
participant_id = request.session.get('participant_id')
|
|
||||||
if participant_id:
|
|
||||||
participant = QuizGameParticipant.objects.filter(
|
|
||||||
quiz_game=game,
|
|
||||||
participant_id=participant_id
|
|
||||||
).first()
|
|
||||||
|
|
||||||
context = {
|
|
||||||
'join_code': join_code,
|
|
||||||
'is_host': str(game.host_id) == str(request.session.get('host_id')),
|
|
||||||
'participant_id': participant_id if participant else None,
|
|
||||||
'rating_enabled': settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM']
|
|
||||||
}
|
|
||||||
return render(request, 'play/game/finished.html', context)
|
|
||||||
except QuizGame.DoesNotExist:
|
|
||||||
return redirect('home')
|
|
||||||
|
|
||||||
def scores(request, join_code):
|
def scores(request, join_code):
|
||||||
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
||||||
@@ -207,8 +188,9 @@ def scores(request, join_code):
|
|||||||
'question_index': quiz_game.current_question_index,
|
'question_index': quiz_game.current_question_index,
|
||||||
'total_questions': len(questions)
|
'total_questions': len(questions)
|
||||||
})
|
})
|
||||||
|
"""
|
||||||
def finished(request, join_code):
|
def finished(request, join_code):
|
||||||
|
|
||||||
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
||||||
|
|
||||||
# Verify game state
|
# Verify game state
|
||||||
@@ -240,6 +222,46 @@ def finished(request, join_code):
|
|||||||
'is_host': is_host,
|
'is_host': is_host,
|
||||||
'participant_id': participant_id if participant else None
|
'participant_id': participant_id if participant else None
|
||||||
})
|
})
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def finished(request, join_code):
|
||||||
|
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
||||||
|
|
||||||
|
if quiz_game.current_state != 'finished':
|
||||||
|
return redirect('play:lobby', join_code=join_code)
|
||||||
|
try:
|
||||||
|
game = QuizGame.objects.get(join_code=join_code)
|
||||||
|
# Get participants sorted by score
|
||||||
|
participants = QuizGameParticipant.objects.filter(quiz_game=quiz_game).order_by('-score')
|
||||||
|
|
||||||
|
|
||||||
|
# Get participant if exists
|
||||||
|
participant_id = request.COOKIES.get('participant_id')
|
||||||
|
participant = None
|
||||||
|
if participant_id:
|
||||||
|
participant = QuizGameParticipant.objects.filter(
|
||||||
|
quiz_game=quiz_game,
|
||||||
|
participant_id=participant_id
|
||||||
|
).first()
|
||||||
|
|
||||||
|
is_host = False
|
||||||
|
if 'host_id' in request.COOKIES and request.COOKIES['host_id'] == quiz_game.host_id:
|
||||||
|
is_host = True
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'join_code': join_code,
|
||||||
|
'is_host': is_host,
|
||||||
|
'participants': participants,
|
||||||
|
'participant_id': participant_id if participant else None,
|
||||||
|
'rating_enabled': settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM']
|
||||||
|
}
|
||||||
|
return render(request, 'play/game/finished.html', context)
|
||||||
|
except QuizGame.DoesNotExist:
|
||||||
|
return redirect('home')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def question(request, join_code):
|
def question(request, join_code):
|
||||||
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load humanize %}
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
@@ -126,6 +126,8 @@
|
|||||||
<span class="text-gray-800">{{ quiz.status }}</span>
|
<span class="text-gray-800">{{ quiz.status }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Rating -->
|
<!-- Rating -->
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
{% if quiz.rating_count > 0 %}
|
{% if quiz.rating_count > 0 %}
|
||||||
@@ -142,20 +144,31 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!--
|
||||||
<!-- Authors -->
|
{% if quiz.user_id %}
|
||||||
{% if quiz.authors.all %}
|
|
||||||
<div class="flex items-center gap-2 text-sm mt-2">
|
<div class="flex items-center gap-2 text-sm mt-2">
|
||||||
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span class="text-gray-600">
|
<span class="text-gray-600">
|
||||||
{% for author in quiz.authors.all %}
|
{{ quiz.user_id.username }}
|
||||||
{{ author.username }}{% if not forloop.last %}, {% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Zeit-->
|
||||||
|
{% if quiz.published_at != None %}
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2 ">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-green-400 size-4">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||||
|
</svg>
|
||||||
|
<span class="text-gray-800 text-sm "><span class="font-medium">{{ quiz.published_at |naturaltime }}</span> <span class="text-sm">erst. veröffentlicht</span> </span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex justify-between items-center gap-2 mt-3 border-t pt-3">
|
<div class="flex justify-between items-center gap-2 mt-3 border-t pt-3">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load humanize %}
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
@@ -148,6 +148,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Authors -->
|
<!-- Authors -->
|
||||||
|
<!--
|
||||||
{% if quiz.authors.all %}
|
{% if quiz.authors.all %}
|
||||||
<div class="flex items-center gap-2 text-sm mt-2">
|
<div class="flex items-center gap-2 text-sm mt-2">
|
||||||
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -159,7 +160,18 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}-->
|
||||||
|
|
||||||
|
<!-- Zeit-->
|
||||||
|
{% if quiz.published_at != None %}
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2 ">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-green-400 size-4">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||||
|
</svg>
|
||||||
|
<span class="text-gray-800 text-sm "><span class="font-medium">{{ quiz.published_at |naturaltime }}</span> <span class="text-sm">erst. veröffentlicht</span> </span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex justify-between items-center gap-2 mt-3 border-t pt-3">
|
<div class="flex justify-between items-center gap-2 mt-3 border-t pt-3">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load humanize %}
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
@@ -145,6 +145,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Authors -->
|
<!-- Authors -->
|
||||||
|
<!--
|
||||||
{% if quiz.authors.all %}
|
{% if quiz.authors.all %}
|
||||||
<div class="flex items-center gap-2 text-sm mt-2">
|
<div class="flex items-center gap-2 text-sm mt-2">
|
||||||
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -157,6 +158,19 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Zeit-->
|
||||||
|
{% if quiz.published_at != None %}
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2 ">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-green-400 size-4">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||||
|
</svg>
|
||||||
|
<span class="text-gray-800 text-sm "><span class="font-medium">{{ quiz.published_at |naturaltime }}</span> <span class="text-sm">erst. veröffentlicht</span> </span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex justify-between items-center gap-2 mt-3 border-t pt-3">
|
<div class="flex justify-between items-center gap-2 mt-3 border-t pt-3">
|
||||||
|
|||||||
Reference in New Issue
Block a user