Merge branch '23-bilder-fur-fragen-und-co' into 'master'
Resolve "Bilder für Fragen und co." Closes #23 See merge request enrichment-2024/qivip!49
This commit is contained in:
@@ -43,6 +43,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'channels',
|
'channels',
|
||||||
|
'django_cleanup',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|||||||
14
django/library/migrations/0047_merge_20250418_1334.py
Normal file
14
django/library/migrations/0047_merge_20250418_1334.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-04-18 11:34
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0035_alter_qivipquestion_time_per_question'),
|
||||||
|
('library', '0046_alter_qivipquizfavorite_favorite_date'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
]
|
||||||
18
django/library/migrations/0048_qivipquestion_image.py
Normal file
18
django/library/migrations/0048_qivipquestion_image.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-04-18 11:34
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0047_merge_20250418_1334'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='qivipquestion',
|
||||||
|
name='image',
|
||||||
|
field=models.ImageField(blank=True, height_field=900, max_length=200, null=True, upload_to='question_images/', verbose_name='Bild', width_field=1000),
|
||||||
|
),
|
||||||
|
]
|
||||||
18
django/library/migrations/0049_alter_qivipquestion_image.py
Normal file
18
django/library/migrations/0049_alter_qivipquestion_image.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-04-18 19:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0048_qivipquestion_image'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='qivipquestion',
|
||||||
|
name='image',
|
||||||
|
field=models.ImageField(blank=True, null=True, upload_to='question_images/', verbose_name='Bild'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -74,6 +74,7 @@ class QivipQuestion(models.Model):
|
|||||||
update_date = models.DateTimeField(auto_now=True)
|
update_date = models.DateTimeField(auto_now=True)
|
||||||
data = models.TextField()
|
data = models.TextField()
|
||||||
time_per_question = models.CharField(max_length=3, choices=list(TIME_VALUES.items()), default=30, help_text="Zeit pro Frage in Sekunden")
|
time_per_question = models.CharField(max_length=3, choices=list(TIME_VALUES.items()), default=30, help_text="Zeit pro Frage in Sekunden")
|
||||||
|
image = models.ImageField(verbose_name="Bild", upload_to="question_images/", blank=True, null=True)
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.data[:50]
|
return self.data[:50]
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,7 @@ def new_question(request):
|
|||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
question_text = request.POST.get('question', '')
|
question_text = request.POST.get('question', '')
|
||||||
|
question_image = request.FILES['question_image']
|
||||||
|
|
||||||
# Handle different question types
|
# Handle different question types
|
||||||
if question_type == 'true_false':
|
if question_type == 'true_false':
|
||||||
@@ -355,6 +356,7 @@ def new_question(request):
|
|||||||
question = QivipQuestion()
|
question = QivipQuestion()
|
||||||
question.data = json.dumps(json_data)
|
question.data = json.dumps(json_data)
|
||||||
question.quiz_id = quiz
|
question.quiz_id = quiz
|
||||||
|
question.image = question_image
|
||||||
question.time_per_question = request.POST.get('time_per_question', '30')
|
question.time_per_question = request.POST.get('time_per_question', '30')
|
||||||
question.save()
|
question.save()
|
||||||
#return modified(request, pk=quiz.pk)
|
#return modified(request, pk=quiz.pk)
|
||||||
@@ -403,6 +405,7 @@ def edit_question(request, pk):
|
|||||||
try:
|
try:
|
||||||
question_data = json.loads(question.data) if question.data else {}
|
question_data = json.loads(question.data) if question.data else {}
|
||||||
question_type = question_data.get('type', 'multiple_choice')
|
question_type = question_data.get('type', 'multiple_choice')
|
||||||
|
question_image = question.image
|
||||||
|
|
||||||
# For true/false questions, get the correct answer from the options
|
# For true/false questions, get the correct answer from the options
|
||||||
if question_type == 'true_false':
|
if question_type == 'true_false':
|
||||||
@@ -447,7 +450,11 @@ def edit_question(request, pk):
|
|||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
question_text = request.POST.get('question', '')
|
question_text = request.POST.get('question', '')
|
||||||
|
try:
|
||||||
|
question_image = request.FILES['question_image']
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# Handle different question types
|
# Handle different question types
|
||||||
if question_type == 'true_false':
|
if question_type == 'true_false':
|
||||||
correct_answer = request.POST.get('correct_answer') == 'true'
|
correct_answer = request.POST.get('correct_answer') == 'true'
|
||||||
@@ -489,6 +496,7 @@ def edit_question(request, pk):
|
|||||||
|
|
||||||
question.data = json.dumps(json_data)
|
question.data = json.dumps(json_data)
|
||||||
question.time_per_question = request.POST.get('time_per_question', '30')
|
question.time_per_question = request.POST.get('time_per_question', '30')
|
||||||
|
question.image = question_image
|
||||||
question.save()
|
question.save()
|
||||||
#return modified(request, question.quiz_id.pk)
|
#return modified(request, question.quiz_id.pk)
|
||||||
return redirect('library:detail_quiz', pk=question.quiz_id.pk)
|
return redirect('library:detail_quiz', pk=question.quiz_id.pk)
|
||||||
@@ -500,6 +508,7 @@ def edit_question(request, pk):
|
|||||||
'quiz_id': question.quiz_id.pk,
|
'quiz_id': question.quiz_id.pk,
|
||||||
'quiz': question.quiz_id,
|
'quiz': question.quiz_id,
|
||||||
'time_per_question': question.time_per_question,
|
'time_per_question': question.time_per_question,
|
||||||
|
'image': question_image,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, template_name, context)
|
return render(request, template_name, context)
|
||||||
|
|||||||
@@ -247,7 +247,8 @@ def question(request, join_code):
|
|||||||
'host_id': quiz_game.host_id,
|
'host_id': quiz_game.host_id,
|
||||||
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
||||||
'question_index': quiz_game.current_question_index,
|
'question_index': quiz_game.current_question_index,
|
||||||
'total_questions': len(questions)
|
'total_questions': len(questions),
|
||||||
|
'question_image': current_question.image
|
||||||
})
|
})
|
||||||
|
|
||||||
# Handle participant view
|
# Handle participant view
|
||||||
@@ -270,7 +271,7 @@ def question(request, join_code):
|
|||||||
'participant': participant,
|
'participant': participant,
|
||||||
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
||||||
'question_index': quiz_game.current_question_index,
|
'question_index': quiz_game.current_question_index,
|
||||||
'total_questions': len(questions)
|
'total_questions': len(questions),
|
||||||
})
|
})
|
||||||
|
|
||||||
def waiting_room(request, join_code):
|
def waiting_room(request, join_code):
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white rounded-lg shadow-md p-6 border-blue-600 border-2 rounded-xl shadow-md">
|
<div class="bg-white rounded-lg shadow-md p-6 border-blue-600 border-2 rounded-xl shadow-md">
|
||||||
<form method="post" class="space-y-6">
|
<form method="post" class="space-y-6" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<!-- Question Text -->
|
<!-- Question Text -->
|
||||||
@@ -23,6 +23,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% if image %}
|
||||||
|
<img src="{{ image.url }}" style="max-width: 500px;" alt="Bild der Frage">
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
<label class="font-bold" for="question_image">Bild:</label>
|
||||||
|
<input value="image.url" class="bg-blue-200 p-2 m-2 rounded-lg border-2 border-blue-400" type="file" name="question_image" id="question_image">
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Options -->
|
<!-- Options -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-2">Antwortmöglichkeiten</label>
|
<label class="block text-sm font-medium text-gray-700 mb-2">Antwortmöglichkeiten</label>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-white rounded-lg shadow-md p-6 border-blue-600 border-2 rounded-xl shadow-md">
|
<div class="bg-white rounded-lg shadow-md p-6 border-blue-600 border-2 rounded-xl shadow-md">
|
||||||
<form method="post" class="space-y-6">
|
<form method="post" class="space-y-6" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<!-- Question Text -->
|
<!-- Question Text -->
|
||||||
@@ -24,6 +24,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if image %}
|
||||||
|
<img src="{{ image.url }}" style="max-width: 500px;" alt="Bild der Frage">
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
<label class="font-bold" for="question_image">Bild:</label>
|
||||||
|
<input class="bg-blue-200 p-2 m-2 rounded-lg border-2 border-blue-400" type="file" name="question_image" id="question_image">
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- True/False Selection -->
|
<!-- True/False Selection -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-2">Richtige Antwort</label>
|
<label class="block text-sm font-medium text-gray-700 mb-2">Richtige Antwort</label>
|
||||||
|
|||||||
@@ -12,11 +12,18 @@
|
|||||||
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
|
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
|
||||||
<p class="text-gray-700 font-bold text-xl mb-4">Frage {{ question_index|add:1 }} von {{ total_questions }}</p>
|
<p class="text-gray-700 font-bold text-xl mb-4">Frage {{ question_index|add:1 }} von {{ total_questions }}</p>
|
||||||
<h1 class="text-3xl font-bold mb-6">{{ question_data.question }}</h1>
|
<h1 class="text-3xl font-bold mb-6">{{ question_data.question }}</h1>
|
||||||
|
|
||||||
|
{% if question_image %}
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<img class="m-4" src="{{ question_image.url }}" style="max-width: 500px;" alt="Bild der Frage">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if request.session.mode == "learn" %}
|
{% if request.session.mode == "learn" %}
|
||||||
<div class="grid grid-cols-1 gap-4 mb-6">
|
<div class="grid grid-cols-1 gap-4 mb-6">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="grid grid-cols-2 gap-4 mb-6">
|
<div class="grid grid-cols-2 gap-4 mb-6">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if request.session.mode != "learn" %}
|
{% if request.session.mode != "learn" %}
|
||||||
<div class="p-4 bg-blue-50 rounded-lg">
|
<div class="p-4 bg-blue-50 rounded-lg">
|
||||||
<p class="text-blue-600 text-xl mb-2">Verbleibende Zeit </p>
|
<p class="text-blue-600 text-xl mb-2">Verbleibende Zeit </p>
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ django~=5.1.4
|
|||||||
channels~=4.2.0 # WebSocket support
|
channels~=4.2.0 # WebSocket support
|
||||||
daphne~=4.1.2 # ASGI server
|
daphne~=4.1.2 # ASGI server
|
||||||
pillow~=11.1.0 # Image handling
|
pillow~=11.1.0 # Image handling
|
||||||
whitenoise~=6.6.0 # Static file serving
|
whitenoise~=6.6.0 # Static file serving
|
||||||
|
django-cleanup
|
||||||
Reference in New Issue
Block a user