diff --git a/apps/participation/templates/participation/participation_detail.html b/apps/participation/templates/participation/participation_detail.html
index 02d6dca..8d1de32 100644
--- a/apps/participation/templates/participation/participation_detail.html
+++ b/apps/participation/templates/participation/participation_detail.html
@@ -181,13 +181,23 @@
{% url "participation:add_question" pk=participation.pk as modal_action %}
{% include "base_modal.html" with modal_id="addQuestion" modal_button_type="success" %}
{% for question in participation.questions.all %}
- {% trans "Update question" as modal_title %}
- {% trans "Update" as modal_button %}
- {% url "participation:update_question" pk=question.pk as modal_action %}
- {% with number_str=forloop.counter|stringformat:"d" %}
- {% with modal_id="updateQuestion"|add:number_str %}
- {% include "base_modal.html" %}
- {% endwith %}
+ {% with number_str=forloop.counter|stringformat:"d"%}
+ {% with modal_id="updateQuestion"|add:number_str %}
+ {% trans "Delete" as delete %}
+ {% with extra_modal_button='"|safe %}
+ {% trans "Update question" as modal_title %}
+ {% trans "Update" as modal_button %}
+ {% url "participation:update_question" pk=question.pk as modal_action %}
+ {% include "base_modal.html" %}
+ {% endwith %}
+ {% endwith %}
+
+ {% with modal_id="deleteQuestion"|add:number_str %}
+ {% trans "Delete question" as modal_title %}
+ {% trans "Delete" as modal_button %}
+ {% url "participation:delete_question" pk=question.pk as modal_action %}
+ {% include "base_modal.html" with modal_button_type="danger" %}
+ {% endwith %}
{% endwith %}
{% endfor %}
{% endif %}
@@ -223,6 +233,12 @@
if (!modalBody.html().trim())
modalBody.load("{% url "participation:update_question" pk=question.pk %} #form-content");
});
+
+ $('button[data-target="#deleteQuestion{{ forloop.counter }}Modal"]').click(function() {
+ let modalBody = $("#deleteQuestion{{ forloop.counter }}Modal div.modal-body");
+ if (!modalBody.html().trim())
+ modalBody.load("{% url "participation:delete_question" pk=question.pk %} #form-content");
+ });
{% endfor %}
{% endif %}
diff --git a/apps/participation/templates/participation/question_confirm_delete.html b/apps/participation/templates/participation/question_confirm_delete.html
new file mode 100644
index 0000000..6c64cb5
--- /dev/null
+++ b/apps/participation/templates/participation/question_confirm_delete.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+
+{% load crispy_forms_filters i18n %}
+
+{% block content %}
+
+{% endblock content %}
+
diff --git a/apps/participation/urls.py b/apps/participation/urls.py
index 489b7e8..b3233dc 100644
--- a/apps/participation/urls.py
+++ b/apps/participation/urls.py
@@ -1,10 +1,10 @@
from django.urls import path
from django.views.generic import TemplateView
-from .views import CalendarView, CreateQuestionView, CreateTeamView, JoinTeamView, MyParticipationDetailView, \
- MyTeamDetailView, ParticipationDetailView, PhaseUpdateView, SetParticipationReceiveParticipationView, \
- SetParticipationSendParticipationView, TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamUpdateView, \
- UpdateQuestionView, UploadVideoView
+from .views import CalendarView, CreateQuestionView, CreateTeamView, DeleteQuestionView, JoinTeamView, \
+ MyParticipationDetailView, MyTeamDetailView, ParticipationDetailView, PhaseUpdateView, \
+ SetParticipationReceiveParticipationView, SetParticipationSendParticipationView, TeamAuthorizationsView, \
+ TeamDetailView, TeamLeaveView, TeamUpdateView, UpdateQuestionView, UploadVideoView
app_name = "participation"
@@ -26,6 +26,7 @@ urlpatterns = [
name="participation_send_participation"),
path("detail//add-question/", CreateQuestionView.as_view(), name="add_question"),
path("update-question//", UpdateQuestionView.as_view(), name="update_question"),
+ path("delete-question//", DeleteQuestionView.as_view(), name="delete_question"),
path("calendar/", CalendarView.as_view(), name="calendar"),
path("calendar//", PhaseUpdateView.as_view(), name="update_phase"),
path("chat/", TemplateView.as_view(template_name="participation/chat.html"), name="chat")
diff --git a/apps/participation/views.py b/apps/participation/views.py
index 4832ed1..0d72b5a 100644
--- a/apps/participation/views.py
+++ b/apps/participation/views.py
@@ -13,8 +13,7 @@ from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
-from django.views.generic import CreateView, DetailView, FormView, RedirectView, UpdateView
-from django.views.generic.base import TemplateView
+from django.views.generic import CreateView, DeleteView, DetailView, FormView, RedirectView, TemplateView, UpdateView
from django.views.generic.edit import FormMixin, ProcessFormView
from django_tables2 import SingleTableView
from magic import Magic
@@ -430,6 +429,27 @@ class UpdateQuestionView(LoginRequiredMixin, UpdateView):
return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,))
+class DeleteQuestionView(LoginRequiredMixin, DeleteView):
+ """
+ Remove a question.
+ """
+ model = Question
+
+ def dispatch(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ if not request.user.is_authenticated:
+ return self.handle_no_permission()
+ if request.user.registration.is_admin or \
+ request.user.registration.participates and \
+ request.user.registration.team.pk == self.object.participation.team_id:
+ return super().dispatch(request, *args, **kwargs)
+ raise PermissionDenied
+
+ def get_success_url(self):
+ return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,))
+
+
+
class UploadVideoView(LoginRequiredMixin, UpdateView):
"""
Upload a solution video for a team.
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index fae4206..9ea9b49 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Corres2math\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-10-31 18:56+0100\n"
+"POT-Creation-Date: 2020-10-31 22:13+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Yohann D'ANELLO \n"
"Language-Team: LANGUAGE \n"
@@ -30,7 +30,7 @@ msgid "This task failed successfully."
msgstr "Cette tâche a échoué avec succès."
#: apps/eastereggs/templates/eastereggs/xp_modal.html:16
-#: templates/base_modal.html:18
+#: templates/base_modal.html:19
msgid "Close"
msgstr "Fermer"
@@ -429,7 +429,7 @@ msgstr "Définir la vidéo reçue"
#: apps/participation/templates/participation/participation_detail.html:151
#: apps/participation/templates/participation/participation_detail.html:156
-#: apps/participation/templates/participation/participation_detail.html:185
+#: apps/participation/templates/participation/participation_detail.html:189
#: apps/participation/templates/participation/phase_form.html:11
#: apps/participation/templates/participation/phase_list.html:18
#: apps/participation/templates/participation/receive_participation_form.html:11
@@ -469,9 +469,19 @@ msgstr "Ajouter une question"
msgid "Add"
msgstr "Ajouter"
-#: apps/participation/templates/participation/participation_detail.html:184
+#: apps/participation/templates/participation/participation_detail.html:186
+#: apps/participation/templates/participation/participation_detail.html:197
+#: apps/participation/templates/participation/question_confirm_delete.html:14
+msgid "Delete"
+msgstr "Supprimer"
+
+#: apps/participation/templates/participation/participation_detail.html:188
msgid "Update question"
-msgstr "Modifier une question"
+msgstr "Modifier la question"
+
+#: apps/participation/templates/participation/participation_detail.html:196
+msgid "Delete question"
+msgstr "Supprimer la question"
#: apps/participation/templates/participation/phase_list.html:10
#: templates/base.html:68 templates/base.html:70 templates/base.html:217
@@ -482,6 +492,10 @@ msgstr "Calendrier"
msgid "Update phase"
msgstr "Modifier la phase"
+#: apps/participation/templates/participation/question_confirm_delete.html:9
+msgid "Are you sure you want to delete this question?"
+msgstr "Êtes-vous sûr·e de vouloir supprimer cette question ?"
+
#: apps/participation/templates/participation/question_form.html:11
msgid "Send"
msgstr "Envoyer"
@@ -589,74 +603,74 @@ msgstr "Quitter l'équipe"
msgid "Are you sure that you want to leave this team?"
msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?"
-#: apps/participation/views.py:37 templates/base.html:77
+#: apps/participation/views.py:36 templates/base.html:77
#: templates/base.html:230
msgid "Create team"
msgstr "Créer une équipe"
-#: apps/participation/views.py:44 apps/participation/views.py:90
+#: apps/participation/views.py:43 apps/participation/views.py:89
msgid "You don't participate, so you can't create a team."
msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe."
-#: apps/participation/views.py:46 apps/participation/views.py:92
+#: apps/participation/views.py:45 apps/participation/views.py:91
msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe."
-#: apps/participation/views.py:83 templates/base.html:82
+#: apps/participation/views.py:82 templates/base.html:82
#: templates/base.html:226
msgid "Join team"
msgstr "Rejoindre une équipe"
-#: apps/participation/views.py:134 apps/participation/views.py:301
-#: apps/participation/views.py:334
+#: apps/participation/views.py:133 apps/participation/views.py:300
+#: apps/participation/views.py:333
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
-#: apps/participation/views.py:135 apps/participation/views.py:335
+#: apps/participation/views.py:134 apps/participation/views.py:334
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
-#: apps/participation/views.py:180
+#: apps/participation/views.py:179
msgid "You don't participate, so you can't request the validation of the team."
msgstr ""
"Vous ne participez pas, vous ne pouvez pas demander la validation de "
"l'équipe."
-#: apps/participation/views.py:183
+#: apps/participation/views.py:182
msgid "The validation of the team is already done or pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
-#: apps/participation/views.py:196
+#: apps/participation/views.py:195
msgid "You are not an administrator."
msgstr "Vous n'êtes pas administrateur."
-#: apps/participation/views.py:199
+#: apps/participation/views.py:198
msgid "This team has no pending validation."
msgstr "L'équipe n'a pas de validation en attente."
-#: apps/participation/views.py:218
+#: apps/participation/views.py:217
msgid "You must specify if you validate the registration or not."
msgstr "Vous devez spécifier si vous validez l'inscription ou non."
-#: apps/participation/views.py:281 apps/registration/views.py:235
+#: apps/participation/views.py:280 apps/registration/views.py:235
#, python-brace-format
msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}"
-#: apps/participation/views.py:285
+#: apps/participation/views.py:284
#, python-brace-format
msgid "Photo authorizations of team {trigram}.zip"
msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip"
-#: apps/participation/views.py:303
+#: apps/participation/views.py:302
msgid "The team is already validated or the validation is pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
-#: apps/participation/views.py:347
+#: apps/participation/views.py:346
msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée."
-#: apps/participation/views.py:356
+#: apps/participation/views.py:355
#, python-brace-format
msgid "Participation of team {trigram}"
msgstr "Participation de l'équipe {trigram}"
diff --git a/templates/base_modal.html b/templates/base_modal.html
index 083a9b4..ab9cf2a 100644
--- a/templates/base_modal.html
+++ b/templates/base_modal.html
@@ -12,6 +12,7 @@
{{ modal_content }}