Ajout de la conception de questions/réponses pour modérer des événements
This commit is contained in:
parent
02d30d0fda
commit
7a6cd5737c
@ -2,7 +2,7 @@ from django.forms import ModelForm, ValidationError, TextInput, Form, URLField,
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget
|
from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget
|
||||||
|
|
||||||
from .models import Event, BatchImportation, RecurrentImport, CategorisationRule
|
from .models import Event, BatchImportation, RecurrentImport, CategorisationRule, ModerationAnswer, ModerationQuestion
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from string import ascii_uppercase as auc
|
from string import ascii_uppercase as auc
|
||||||
from .templatetags.utils_extra import int_to_abc
|
from .templatetags.utils_extra import int_to_abc
|
||||||
@ -235,3 +235,18 @@ class MergeDuplicates(Form):
|
|||||||
return [auc.rfind(v[-1]) for v in value]
|
return [auc.rfind(v[-1]) for v in value]
|
||||||
else:
|
else:
|
||||||
return auc.rfind(value[-1])
|
return auc.rfind(value[-1])
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-04-01 14:28
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django_better_admin_arrayfield.models.fields
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('agenda_culturel', '0038_auto_20240331_1815'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ModerationQuestion',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('question', models.CharField(help_text='Text that will be shown to moderators', max_length=512, unique=True, verbose_name='Question')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ModerationAnswer',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('answer', models.CharField(help_text='Text that will be shown to moderators', max_length=512, unique=True, verbose_name='Answer')),
|
||||||
|
('adds_tags', django_better_admin_arrayfield.models.fields.ArrayField(base_field=models.CharField(max_length=64), blank=True, help_text='A list of tags that will be added if you choose this answer.', null=True, size=None, verbose_name='Adds tags')),
|
||||||
|
('removes_tags', django_better_admin_arrayfield.models.fields.ArrayField(base_field=models.CharField(max_length=64), blank=True, help_text='A list of tags that will be removed if you choose this answer.', null=True, size=None, verbose_name='Removes tags')),
|
||||||
|
('description', models.ForeignKey(help_text='Associated question from moderation', on_delete=django.db.models.deletion.CASCADE, to='agenda_culturel.moderationquestion', verbose_name='Question')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
28
src/agenda_culturel/migrations/0040_auto_20240403_1924.py
Normal file
28
src/agenda_culturel/migrations/0040_auto_20240403_1924.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-04-03 17:24
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
from django.contrib.auth.management import create_permissions
|
||||||
|
from django.contrib.auth.models import Group, Permission
|
||||||
|
|
||||||
|
|
||||||
|
def update_groups_permissions(apps, schema_editor):
|
||||||
|
|
||||||
|
all_perms = Permission.objects.all()
|
||||||
|
moderator_perms = [i for i in all_perms if i.content_type.app_label == 'agenda_culturel' and i.content_type.model in ['event', 'duplicatedevents']]
|
||||||
|
read_mod_perms = [i for i in moderator_perms if i.codename.startswith('view_')]
|
||||||
|
|
||||||
|
# set permissions for receptionists
|
||||||
|
qanda_perms = [i for i in all_perms if i.content_type.app_label == 'agenda_culturel' and i.content_type.model in ['moderationquestion', 'moderationanswer']]
|
||||||
|
Group.objects.get(name="Q&A Manager").permissions.add(*qanda_perms)
|
||||||
|
Group.objects.get(name="Q&A Manager").permissions.add(*read_mod_perms)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('agenda_culturel', '0039_moderationquestion_moderationanswer'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(update_groups_permissions),
|
||||||
|
]
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-04-03 20:01
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('agenda_culturel', '0040_auto_20240403_1924'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='moderationanswer',
|
||||||
|
old_name='description',
|
||||||
|
new_name='question',
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-04-03 21:13
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('agenda_culturel', '0041_rename_description_moderationanswer_question'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='moderationanswer',
|
||||||
|
name='answer',
|
||||||
|
field=models.CharField(help_text='Text that will be shown to moderators', max_length=512, verbose_name='Answer'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-04-03 21:14
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('agenda_culturel', '0042_alter_moderationanswer_answer'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='moderationanswer',
|
||||||
|
name='question',
|
||||||
|
field=models.ForeignKey(help_text='Associated question from moderation', on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='agenda_culturel.moderationquestion', verbose_name='Question'),
|
||||||
|
),
|
||||||
|
]
|
@ -851,3 +851,27 @@ class CategorisationRule(models.Model):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class ModerationQuestion(models.Model):
|
||||||
|
|
||||||
|
question = models.CharField(verbose_name=_('Question'), help_text=_('Text that will be shown to moderators'), max_length=512, unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
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})
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
|
||||||
|
{% block title %}Supprimer la réponse #{{ object.pk }}{% 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}} « {{ object.answer }} » associée à la question « {{ object.question.question }} » ?
|
||||||
|
</p>
|
||||||
|
{{ form }}
|
||||||
|
<div class="grid">
|
||||||
|
<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 %}
|
@ -0,0 +1,31 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'une réponse de modération{% 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">
|
||||||
|
<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 %}
|
@ -0,0 +1,19 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
|
||||||
|
{% block title %}Supprimer la question #{{ object.pk }}{% 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}} « {{ object.question }} » ainsi que les réponses associées ?
|
||||||
|
</p>
|
||||||
|
{{ form }}
|
||||||
|
<div class="grid">
|
||||||
|
<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 %}
|
@ -0,0 +1,67 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
|
||||||
|
{% block title %}Question de modération #{{ object.pk }}{% endblock %}
|
||||||
|
|
||||||
|
{% load tag_extra %}
|
||||||
|
{% load utils_extra %}
|
||||||
|
{% load cat_extra %}
|
||||||
|
|
||||||
|
{% block entete_header %}
|
||||||
|
{% css_categories %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="grid two-columns">
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<a href="{% url 'view_mquestions' %}" role="button">< 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 }} :</strong> « {{ answer.answer }} »</h4>
|
||||||
|
{% if answer.adds_tags %}
|
||||||
|
<p>Cette réponse ajoute les étiquettes suivantes à l'événement :
|
||||||
|
{% 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 :
|
||||||
|
{% 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 %}
|
@ -0,0 +1,22 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'une question de modération
|
||||||
|
{% 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">
|
||||||
|
<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 %}
|
@ -0,0 +1,65 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
|
||||||
|
{% block title %}Questions de modération{% endblock %}
|
||||||
|
|
||||||
|
{% load utils_extra %}
|
||||||
|
{% load cat_extra %}
|
||||||
|
{% block entete_header %}
|
||||||
|
{% css_categories %}
|
||||||
|
{% 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 }} : {{ question.question }}</h2>
|
||||||
|
<p>{% if question.answers %}
|
||||||
|
<p>réponses possibles :</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">« 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 »</a>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
|
{% include "agenda_culturel/side-nav.html" with current="moderationquestions" %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -43,6 +43,14 @@
|
|||||||
</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>
|
||||||
|
@ -55,6 +55,14 @@ urlpatterns = [
|
|||||||
path("duplicates/<int:pk>", DuplicatedEventsDetailView.as_view(), name="view_duplicate"),
|
path("duplicates/<int:pk>", DuplicatedEventsDetailView.as_view(), name="view_duplicate"),
|
||||||
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("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"),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
@ -11,9 +11,9 @@ from django.http import HttpResponseRedirect
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm
|
from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm
|
||||||
|
|
||||||
from .models import Event, Category, StaticContent, ContactMessage, BatchImportation, DuplicatedEvents, RecurrentImport, CategorisationRule, remove_accents
|
from .models import Event, Category, StaticContent, ContactMessage, BatchImportation, DuplicatedEvents, RecurrentImport, CategorisationRule, remove_accents, ModerationQuestion, ModerationAnswer
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
@ -881,3 +881,74 @@ 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")
|
||||||
|
Loading…
Reference in New Issue
Block a user