From 6f3000c51b066d9e5d796ab9dc6ac7f5764afd4d Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Sat, 13 Apr 2024 11:30:58 +0200
Subject: [PATCH] =?UTF-8?q?Ajout=20mod=C3=A9ration=20par=20questions?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix #68
---
src/agenda_culturel/forms.py | 20 +++++++++
.../migrations/0046_event_moderated_date.py | 18 ++++++++
src/agenda_culturel/models.py | 43 +++++++++++++++++++
.../agenda_culturel/edit-buttons-inc.html | 3 +-
.../agenda_culturel/event-info-inc.html | 30 +++++++++++++
.../templates/agenda_culturel/event_form.html | 30 +------------
.../event_moderation_form.html | 34 +++++++++++++++
.../single-event/event-single-inc.html | 5 ++-
src/agenda_culturel/urls.py | 1 +
src/agenda_culturel/views.py | 23 +++++++++-
10 files changed, 175 insertions(+), 32 deletions(-)
create mode 100644 src/agenda_culturel/migrations/0046_event_moderated_date.py
create mode 100644 src/agenda_culturel/templates/agenda_culturel/event-info-inc.html
create mode 100644 src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html
diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py
index 93bed5c..1613ec9 100644
--- a/src/agenda_culturel/forms.py
+++ b/src/agenda_culturel/forms.py
@@ -250,3 +250,23 @@ class ModerationAnswerForm(ModelForm):
'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
diff --git a/src/agenda_culturel/migrations/0046_event_moderated_date.py b/src/agenda_culturel/migrations/0046_event_moderated_date.py
new file mode 100644
index 0000000..7843fb5
--- /dev/null
+++ b/src/agenda_culturel/migrations/0046_event_moderated_date.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.7 on 2024-04-13 09:25
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('agenda_culturel', '0045_auto_20240405_1941'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='event',
+ name='moderated_date',
+ field=models.DateTimeField(blank=True, null=True),
+ ),
+ ]
diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py
index 82d9f43..02cbb1d 100644
--- a/src/agenda_culturel/models.py
+++ b/src/agenda_culturel/models.py
@@ -1,6 +1,7 @@
from django.db import models
from django_better_admin_arrayfield.models.fields import ArrayField
from django.utils.translation import gettext_lazy as _
+from django.utils.safestring import mark_safe
from django.template.defaultfilters import slugify
from django.urls import reverse
from colorfield.fields import ColorField
@@ -161,6 +162,7 @@ class Event(models.Model):
created_date = models.DateTimeField(editable=False)
imported_date = models.DateTimeField(blank=True, null=True)
modified_date = models.DateTimeField(blank=True, null=True)
+ moderated_date = models.DateTimeField(blank=True, null=True)
recurrence_dtstart = models.DateTimeField(editable=False, blank=True, null=True)
recurrence_dtend = models.DateTimeField(editable=False, blank=True, null=True)
@@ -880,6 +882,9 @@ class ModerationQuestion(models.Model):
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):
@@ -890,3 +895,41 @@ class ModerationAnswer(models.Model):
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 + '
'
+ if self.adds_tags:
+ result += ' '.join(['' + a + '' for a in self.adds_tags])
+ if self.removes_tags:
+ result += ' '.join(['' + a + '' for a in self.removes_tags])
+ result += ""
+ return mark_safe(result)
+
+ def valid_event(self, event):
+ if event.tags:
+ for t in self.adds_tags:
+ if t not in event.tags:
+ return False
+
+ 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 = []
+
+ logger.info('on applique la réponse ' + self.answer)
+ if event.tags:
+ event.tags = list((set(event.tags) | set(self.adds_tags)) - set(self.removes_tags))
+ else:
+ event.tags = self.adds_tags
diff --git a/src/agenda_culturel/templates/agenda_culturel/edit-buttons-inc.html b/src/agenda_culturel/templates/agenda_culturel/edit-buttons-inc.html
index 49a151a..78152ec 100644
--- a/src/agenda_culturel/templates/agenda_culturel/edit-buttons-inc.html
+++ b/src/agenda_culturel/templates/agenda_culturel/edit-buttons-inc.html
@@ -1,6 +1,7 @@
{% load utils_extra %}
-modifier {% picto_from_name "edit" %}
+modérer {% picto_from_name "edit" %}
+modifier {% picto_from_name "edit-3" %}
{% if event.status != "published" %}
publier {% picto_from_name "eye" %}
diff --git a/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html b/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html
new file mode 100644
index 0000000..36ecd6d
--- /dev/null
+++ b/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/src/agenda_culturel/templates/agenda_culturel/event_form.html b/src/agenda_culturel/templates/agenda_culturel/event_form.html
index 2ca5b2c..fbbb4be 100644
--- a/src/agenda_culturel/templates/agenda_culturel/event_form.html
+++ b/src/agenda_culturel/templates/agenda_culturel/event_form.html
@@ -46,35 +46,7 @@
{% if object %}
-
+{% include "agenda_culturel/event-info-inc.html" %}
{% endif %}
diff --git a/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html b/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html
new file mode 100644
index 0000000..c44f54d
--- /dev/null
+++ b/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html
@@ -0,0 +1,34 @@
+{% extends "agenda_culturel/event_form.html" %}
+{% load static %}
+
+
+{% block title %}Modérer {{ object.title }}{% endblock %}
+
+
+
+{% block content %}
+
+{% load static_content_extra %}
+
+
+
+ Modération de l'événement {{ object.title }} ({{ object.start_day }})
+
+
+ {% include "agenda_culturel/single-event/event-single-inc.html" with event=object noedit=1 %}
+
+
+
+
+{% include "agenda_culturel/event-info-inc.html" %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html b/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html
index 31ac2d9..379c729 100644
--- a/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html
+++ b/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html
@@ -65,9 +65,12 @@
{% if event.modified %}
— dernière modification : {{ event.modified_date }}
{% endif %}
+ {% if event.moderated_date %}
+ — dernière modération : {{ event.moderated_date }}
+ {% endif %}
- {% if perms.agenda_culturel.change_event %}
+ {% if perms.agenda_culturel.change_event and not noedit %}
{% include "agenda_culturel/edit-buttons-inc.html" with event=event %}
diff --git a/src/agenda_culturel/urls.py b/src/agenda_culturel/urls.py
index 785a86e..e13a1df 100644
--- a/src/agenda_culturel/urls.py
+++ b/src/agenda_culturel/urls.py
@@ -25,6 +25,7 @@ urlpatterns = [
path("event//change-status/", change_status_event, name="change_status_event"),
path("event//delete", EventDeleteView.as_view(), name="delete_event"),
path("event/////set_duplicate", set_duplicate, name="set_duplicate"),
+ path("event//moderate", EventModerateView.as_view(), name="moderate_event"),
path("ajouter", import_from_url, name="add_event"),
path("admin/", admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py
index 6d312a3..bfa5fcb 100644
--- a/src/agenda_culturel/views.py
+++ b/src/agenda_culturel/views.py
@@ -11,7 +11,7 @@ from django.http import HttpResponseRedirect
from django.urls import reverse
import urllib
-from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm
+from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm, ModerateForm
from .models import Event, Category, StaticContent, ContactMessage, BatchImportation, DuplicatedEvents, RecurrentImport, CategorisationRule, remove_accents, ModerationQuestion, ModerationAnswer
from django.utils import timezone
@@ -259,6 +259,27 @@ class EventDetailView(UserPassesTestMixin, DetailView):
return obj
+class EventModerateView(SuccessMessageMixin, PermissionRequiredMixin, LoginRequiredMixin, UpdateView):
+ model = Event
+ permission_required = ["agenda_culturel.changes_event", "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):
+
+ mas = ModerationAnswer.objects.all()
+ logger.warning("ON valide la forme")
+
+ 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/")
@permission_required('agenda_culturel.change_event')
def change_status_event(request, pk, status):