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 %} + +
+
{% csrf_token %} + {{ form.media }} + {{ form.as_p }} +
+ Annuler + +
+
+ +{% 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):