Suppression des questions de migration pas utilisées (branche à part)

This commit is contained in:
Jean-Marie Favreau 2024-11-13 10:56:45 +01:00
parent 4936365488
commit 4c2dd9e98c
13 changed files with 19 additions and 548 deletions

View File

@ -20,8 +20,6 @@ from .models import (
Event, Event,
RecurrentImport, RecurrentImport,
CategorisationRule, CategorisationRule,
ModerationAnswer,
ModerationQuestion,
Place, Place,
Category, Category,
) )
@ -417,46 +415,6 @@ class MergeDuplicates(Form):
return None return None
class ModerationQuestionForm(ModelForm):
class Meta:
model = ModerationQuestion
fields = "__all__"
class ModerationAnswerForm(ModelForm):
class Meta:
model = ModerationAnswer
exclude = ["question"]
widgets = {
"adds_tags": DynamicArrayWidgetTags(),
"removes_tags": DynamicArrayWidgetTags(),
}
class ModerateForm(ModelForm):
class Meta:
model = Event
fields = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
mqs = ModerationQuestion.objects.all()
mas = ModerationAnswer.objects.all()
for q in mqs:
self.fields[q.complete_id()] = ChoiceField(
widget=RadioSelect,
label=q.question,
choices=[(a.pk, a.html_description()) for a in mas if a.question == q],
required=True,
)
for a in mas:
if a.question == q and a.valid_event(self.instance):
self.fields[q.complete_id()].initial = a.pk
break
class CategorisationForm(Form): class CategorisationForm(Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if "events" in kwargs: if "events" in kwargs:

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.9 on 2024-11-13 09:56
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('agenda_culturel', '0108_remove_duplicated_categories'),
]
operations = [
migrations.DeleteModel(
name='ModerationAnswer',
),
migrations.DeleteModel(
name='ModerationQuestion',
),
]

View File

@ -1826,113 +1826,3 @@ class CategorisationRule(models.Model):
return True return True
class ModerationQuestion(models.Model):
question = models.CharField(
verbose_name=_("Question"),
help_text=_("Text that will be shown to moderators"),
max_length=512,
unique=True,
)
class Meta:
verbose_name = _("Moderation question")
verbose_name_plural = _("Moderation questions")
permissions = [
("use_moderation_question", "Can use a moderation question to tag an event")
]
def __str__(self):
char_limit = 30
return (
(self.question[:char_limit] + "...")
if char_limit < len(self.question)
else self.question
)
def get_absolute_url(self):
return reverse("view_mquestion", kwargs={"pk": self.pk})
def complete_id(self):
return "question_" + str(self.pk)
class ModerationAnswer(models.Model):
question = models.ForeignKey(
ModerationQuestion,
related_name="answers",
verbose_name=_("Question"),
help_text=_("Associated question from moderation"),
on_delete=models.CASCADE,
)
answer = models.CharField(
verbose_name=_("Answer"),
help_text=_("Text that will be shown to moderators"),
max_length=512,
)
adds_tags = ArrayField(
models.CharField(max_length=64),
verbose_name=_("Adds tags"),
help_text=_("A list of tags that will be added if you choose this answer."),
blank=True,
null=True,
)
removes_tags = ArrayField(
models.CharField(max_length=64),
verbose_name=_("Removes tags"),
help_text=_("A list of tags that will be removed if you choose this answer."),
blank=True,
null=True,
)
def complete_id(self):
return "answer_" + str(self.question.pk) + "_" + str(self.pk)
def html_description(self):
result = self.answer + '<br /><span class="helptext">'
if self.adds_tags:
result += " ".join(
[
'<span role="button" class="small-cat">' + a + "</span>"
for a in self.adds_tags
]
)
if self.removes_tags:
result += " ".join(
[
'<span role="button" class="small-cat strike">' + a + "</span>"
for a in self.removes_tags
]
)
result += "</span>"
return mark_safe(result)
def valid_event(self, event):
if event.tags:
if self.adds_tags:
for t in self.adds_tags:
if t not in event.tags:
return False
if self.removes_tags:
for t in self.removes_tags:
if t in event.tags:
return False
return True
else:
return not self.adds_tags or len(self.adds_tags) == 0
def apply_answer(self, event):
if not self.adds_tags:
self.adds_tags = []
if not self.removes_tags:
self.removes_tags = []
if event.tags:
event.tags = list(
(set(event.tags) | set(self.adds_tags)) - set(self.removes_tags)
)
else:
event.tags = self.adds_tags

View File

@ -1,7 +1,6 @@
{% load utils_extra %} {% load utils_extra %}
<!-- a href="{% url 'moderate_event' event.id %}" role="button">modérer {% picto_from_name "edit" %}</a-->
{% if event.pure_import %} {% if event.pure_import %}
{% with event.get_local_version as local %} {% with event.get_local_version as local %}
{% if local %} {% if local %}

View File

@ -1,20 +0,0 @@
{% extends "agenda_culturel/page-admin.html" %}
{% block title %}{% block og_title %}Supprimer la réponse #{{ object.pk }}{% endblock %}{% endblock %}
{% block fluid %}{% endblock %}
{% block content %}
<h1>Suppression de la réponse de modération {{ object.pk }}</h1>
<form method="post">{% csrf_token %}
<p>Êtes-vous sûr·e de vouloir supprimer la réponse de modération #{{object.pk}} «&nbsp;{{ object.answer }}&nbsp;» associée à la question «&nbsp;{{ object.question.question }}&nbsp;»&nbsp;?
</p>
{{ form }}
<div class="grid buttons">
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{{ object.get_absolute_url }}{% endif %}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Confirmer">
</div>
</form>
{% endblock %}

View File

@ -1,31 +0,0 @@
{% extends "agenda_culturel/page-admin.html" %}
{% load static %}
{% block title %}{% block og_title %}{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'une réponse de modération{% endblock %}{% endblock %}
{% block entete_header %}
<script>window.CKEDITOR_BASEPATH = '/static/ckeditor/ckeditor/';</script>
<script src="/static/admin/js/vendor/jquery/jquery.js"></script>
<script src="/static/admin/js/jquery.init.js"></script>
<link href="{% static 'css/django_better_admin_arrayfield.min.css' %}" type="text/css" media="all" rel="stylesheet">
<script src="{% static 'js/django_better_admin_arrayfield.min.js' %}"></script>
<script src="{% static 'js/adjust_datetimes.js' %}"></script>
{% endblock %}
{% block content %}
<h1>{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'une réponse de modération</h1>
<p>{% if form.instance.pk %}Modifier{% else %}Ajouter{% endif %} une réponse à la question « {{ question }} »</p>
<article>
<form method="post">{% csrf_token %}
{{ form.as_p }}
<div class="grid buttons">
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{% url 'view_mquestion' question.pk %}{% endif %}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Envoyer">
</div>
</form>
</article>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "agenda_culturel/page-admin.html" %}
{% block title %}{% block og_title %}Supprimer la question #{{ object.pk }}{% endblock %}{% endblock %}
{% block fluid %}{% endblock %}
{% block content %}
<h1>Suppression de la question de modération {{ object.pk }}</h1>
<form method="post">{% csrf_token %}
<p>Êtes-vous sûr·e de vouloir supprimer la question de modération #{{object.pk}} «&nbsp;{{ object.question }}&nbsp;» ainsi que les réponses associées&nbsp;?
</p>
{{ form }}
<div class="grid buttons">
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{{ object.get_absolute_url }}{% endif %}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Confirmer">
</div>
</form>
{% endblock %}

View File

@ -1,71 +0,0 @@
{% extends "agenda_culturel/page-admin.html" %}
{% block title %}{% block og_title %}Question de modération #{{ object.pk }}{% endblock %}{% endblock %}
{% load tag_extra %}
{% load utils_extra %}
{% load cat_extra %}
{% block entete_header %}
{% css_categories %}
{% endblock %}
{% block sidemenu-bouton %}
<li><a href="#contenu-principal" aria-label="Aller au contenu">{% picto_from_name "chevron-up" %}</a></li>
<li><a href="#sidebar" aria-label="Aller au menu latéral">{% picto_from_name "chevron-down" %}</a></li>
{% endblock %}
{% block content %}
<div class="grid two-columns">
<article>
<header>
<a href="{% url 'view_mquestions' %}" role="button">&lt; Retour</a>
<div class="slide-buttons">
<a href="{% url 'delete_mquestion' object.pk %}" role="button">Supprimer</a>
<a href="{% url 'edit_mquestion' object.pk %}" role="button">Modifier</a>
<a href="{% url 'add_manswer' object.pk %}" role="button">Ajouter une réponse {% picto_from_name "plus-circle" %}</a>
</div>
<h1>Question de modération #{{ object.pk }}</h1>
<p>{{ object.question }}</p>
</header>
{% if object.answers %}
{% for answer in object.answers.all %}
<article>
<div class="slide-buttons">
<a href="{% url 'edit_manswer' object.pk answer.pk %}" role="button">Modifier</a>
<a href="{% url 'delete_manswer' object.pk answer.pk %}" role="button">Supprimer</a>
</div>
<header>
<h4><strong>Réponse #{{ answer.pk }}&nbsp;:</strong> «&nbsp;{{ answer.answer }}&nbsp;»</h4>
{% if answer.adds_tags %}
<p>Cette réponse ajoute les étiquettes suivantes à l'événement&nbsp;:
{% for tag in answer.adds_tags %}
{{ tag | tag_button }}
{% endfor %}
</p>
{% else %}
<p><em>Cette réponse n'ajoute pas d'étiquette à l'événement.</em></p>
{% endif %}
{% if answer.removes_tags %}
<p>Cette réponse supprimer les étiquettes suivantes à l'événement&nbsp;:
{% for tag in answer.removes_tags %}
{{ tag | tag_button }}
{% endfor %}
</p>
{% else %}
<p><em>Cette réponse ne supprime pas d'étiquette à l'événement.</em></p>
{% endif %}
</header>
</article>
{% endfor %}
{% else %}
Il n'y a pas encore de réponse associée à cette question.
{% endif %}
</article>
{% include "agenda_culturel/side-nav.html" with current="moderationquestions" %}
</div>
{% endblock %}

View File

@ -1,23 +0,0 @@
{% extends "agenda_culturel/page-admin.html" %}
{% load static %}
{% block title %}{% block og_title %}
{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'une question de modération
{% endblock %}{% endblock %}
{% block content %}
<h1>{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'une question de modération</h1>
<article>
<form method="post">{% csrf_token %}
{{ form.as_p }}
<div class="grid buttons">
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{{ object.get_absolute_url }}{% endif %}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Envoyer">
</div>
</form>
</article>
{% endblock %}

View File

@ -1,71 +0,0 @@
{% extends "agenda_culturel/page-admin.html" %}
{% block title %}{% block og_title %}Questions de modération{% endblock %}{% endblock %}
{% load utils_extra %}
{% load cat_extra %}
{% block entete_header %}
{% css_categories %}
{% endblock %}
{% block sidemenu-bouton %}
<li><a href="#contenu-principal" aria-label="Aller au contenu">{% picto_from_name "chevron-up" %}</a></li>
<li><a href="#sidebar" aria-label="Aller au menu latéral">{% picto_from_name "chevron-down" %}</a></li>
{% endblock %}
{% block content %}
<div class="grid two-columns">
<article>
<header>
<a class="slide-buttons" href="{% url 'add_mquestion'%}" role="button">Ajouter {% picto_from_name "plus-circle" %}</a>
<h1>Questions de modération</h1>
</header>
{% if object_list %}
{% for question in object_list %}
<article>
<header>
<a class="slide-buttons" href="{{ question.get_absolute_url }}" role="button">Détails...</a>
<h2>Question #{{ question.pk }}&nbsp;: {{ question.question }}</h2>
<p>{% if question.answers %}
<p>réponses possibles&nbsp;:</p>
<ul>
{% for answer in question.answers.all %}
<li>{{ answer.answer }}</li>
{% endfor %}
</ul>
{% else %}
<p><em>aucune réponse définie</em></p>
{% endif %}
</p>
</header>
</article>
{% endfor %}
{% else %}
<p>Il n'y a aucune question définie.</p>
{% endif %}
<footer>
<span>
{% if page_obj.has_previous %}
<a href="?page=1" role="button">&laquo; premier</a>
<a href="?page={{ page_obj.previous_page_number }}" role="button">précédent</a>
{% endif %}
<span>
Page {{ page_obj.number }} sur {{ page_obj.paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}" role="button">suivant</a>
<a href="?page={{ page_obj.paginator.num_pages }}" role="button">dernier &raquo;</a>
{% endif %}
</span>
</footer>
</article>
{% include "agenda_culturel/side-nav.html" with current="moderationquestions" %}
</div>
{% endblock %}

View File

@ -60,14 +60,6 @@
</ul> </ul>
</nav> </nav>
{% endif %} {% endif %}
{% if perms.agenda_culturel.view_moderationquestion %}
<!-- h3>Paramétrage de la modération</h3>
<nav>
<ul>
<li><a {% if current == "moderationquestions" %}class="selected" {% endif %}href="{% url 'view_mquestions' %}">Questions de modération</a></li>
</ul>
</nav-->
{% endif %}
{% if user.is_staff %} {% if user.is_staff %}
<h3>Configuration interne</h3> <h3>Configuration interne</h3>
<nav> <nav>

View File

@ -45,7 +45,6 @@ urlpatterns = [
set_duplicate, set_duplicate,
name="set_duplicate", name="set_duplicate",
), ),
path("event/<int:pk>/moderate", EventModerateView.as_view(), name="moderate_event"),
path("ajouter", import_event_proxy, name="add_event"), path("ajouter", import_event_proxy, name="add_event"),
path("ajouter/url", import_from_url, name="add_event_url"), path("ajouter/url", import_from_url, name="add_event_url"),
path("ajouter/urls", import_from_urls, name="add_event_urls"), path("ajouter/urls", import_from_urls, name="add_event_urls"),
@ -123,40 +122,6 @@ urlpatterns = [
path("duplicates/<int:pk>/fix", fix_duplicate, name="fix_duplicate"), path("duplicates/<int:pk>/fix", fix_duplicate, name="fix_duplicate"),
path("duplicates/<int:pk>/merge", merge_duplicate, name="merge_duplicate"), path("duplicates/<int:pk>/merge", merge_duplicate, name="merge_duplicate"),
path("duplicates/<int:pk>/update/<int:epk>", update_duplicate_event, name="update_event"), path("duplicates/<int:pk>/update/<int:epk>", update_duplicate_event, name="update_event"),
path("mquestions/", ModerationQuestionListView.as_view(), name="view_mquestions"),
path(
"mquestions/add", ModerationQuestionCreateView.as_view(), name="add_mquestion"
),
path(
"mquestions/<int:pk>/",
ModerationQuestionDetailView.as_view(),
name="view_mquestion",
),
path(
"mquestions/<int:pk>/edit",
ModerationQuestionUpdateView.as_view(),
name="edit_mquestion",
),
path(
"mquestions/<int:pk>/delete",
ModerationQuestionDeleteView.as_view(),
name="delete_mquestion",
),
path(
"mquestions/<int:qpk>/answers/add",
ModerationAnswerCreateView.as_view(),
name="add_manswer",
),
path(
"mquestions/<int:qpk>/answers/<int:pk>/edit",
ModerationAnswerUpdateView.as_view(),
name="edit_manswer",
),
path(
"mquestions/<int:qpk>/answers/<int:pk>/delete",
ModerationAnswerDeleteView.as_view(),
name="delete_manswer",
),
path("404/", page_not_found, name="page_not_found"), path("404/", page_not_found, name="page_not_found"),
path("500/", internal_server_error, name="internal_server_error"), path("500/", internal_server_error, name="internal_server_error"),
path("place/<int:pk>/past", PlaceDetailViewPast.as_view(), name="view_place_past"), path("place/<int:pk>/past", PlaceDetailViewPast.as_view(), name="view_place_past"),

View File

@ -29,9 +29,6 @@ from .forms import (
MergeDuplicates, MergeDuplicates,
RecurrentImportForm, RecurrentImportForm,
CategorisationRuleImportForm, CategorisationRuleImportForm,
ModerationQuestionForm,
ModerationAnswerForm,
ModerateForm,
CategorisationForm, CategorisationForm,
EventAddPlaceForm, EventAddPlaceForm,
PlaceForm, PlaceForm,
@ -49,8 +46,6 @@ from .models import (
RecurrentImport, RecurrentImport,
CategorisationRule, CategorisationRule,
remove_accents, remove_accents,
ModerationQuestion,
ModerationAnswer,
Place, Place,
ReferenceLocation ReferenceLocation
) )
@ -619,30 +614,6 @@ class EventDetailView(UserPassesTestMixin, DetailView):
return obj return obj
class EventModerateView(
SuccessMessageMixin, PermissionRequiredMixin, LoginRequiredMixin, UpdateView
):
model = Event
permission_required = (
"agenda_culturel.change_event",
"agenda_culturel.use_moderation_question",
)
success_message = _("The event has been successfully modified.")
form_class = ModerateForm
template_name = "agenda_culturel/event_moderation_form.html"
def form_valid(self, form):
ModerationAnswer.objects.all()
for f in form.cleaned_data:
ModerationAnswer.objects.get(pk=form.cleaned_data[f]).apply_answer(
form.instance
)
form.instance.moderated_date = timezone.now()
return super().form_valid(form)
@login_required(login_url="/accounts/login/") @login_required(login_url="/accounts/login/")
@permission_required("agenda_culturel.change_event") @permission_required("agenda_culturel.change_event")
@ -1964,93 +1935,6 @@ def apply_categorisation_rules(request):
return HttpResponseRedirect(reverse_lazy("categorisation_rules")) return HttpResponseRedirect(reverse_lazy("categorisation_rules"))
#########################
## Moderation Q&A
#########################
class ModerationQuestionListView(PermissionRequiredMixin, ListView):
model = ModerationQuestion
paginate_by = 10
permission_required = "agenda_culturel.view_moderationquestion"
class ModerationQuestionCreateView(
SuccessMessageMixin, PermissionRequiredMixin, CreateView
):
model = ModerationQuestion
permission_required = "agenda_culturel.add_moderationquestion"
def get_success_url(self):
return reverse_lazy("view_mquestion", kwargs={"pk": self.object.pk})
form_class = ModerationQuestionForm
success_message = _("The moderation question has been created with success.")
class ModerationQuestionDetailView(PermissionRequiredMixin, DetailView):
model = ModerationQuestion
permission_required = (
"agenda_culturel.view_moderationquestion",
"agenda_culturel.view_moderationanswer",
)
class ModerationQuestionUpdateView(PermissionRequiredMixin, UpdateView):
model = ModerationQuestion
fields = ["question"]
permission_required = "agenda_culturel.change_moderationquestion"
class ModerationQuestionDeleteView(PermissionRequiredMixin, DeleteView):
model = ModerationQuestion
permission_required = "agenda_culturel.delete_moderationquestion"
success_url = reverse_lazy("view_mquestions")
class ModerationAnswerCreateView(
PermissionRequiredMixin, SuccessMessageMixin, CreateView
):
model = ModerationAnswer
permission_required = "agenda_culturel.add_answerquestion"
form_class = ModerationAnswerForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["question"] = get_object_or_404(
ModerationQuestion, pk=self.kwargs["qpk"]
)
return context
def form_valid(self, form):
form.instance.question = ModerationQuestion.objects.get(pk=self.kwargs["qpk"])
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("view_mquestion", kwargs={"pk": self.kwargs["qpk"]})
class ModerationAnswerUpdateView(PermissionRequiredMixin, UpdateView):
model = ModerationAnswer
fields = ["answer", "adds_tags", "removes_tags"]
permission_required = "agenda_culturel.change_answerquestion"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["question"] = get_object_or_404(
ModerationQuestion, pk=self.kwargs["qpk"]
)
return context
def get_success_url(self):
return reverse_lazy("view_mquestion", kwargs={"pk": self.kwargs["qpk"]})
class ModerationAnswerDeleteView(PermissionRequiredMixin, DeleteView):
model = ModerationAnswer
permission_required = "agenda_culturel.delete_answerquestion"
######################### #########################
## Places ## Places
######################### #########################