Ajout d'un outil de modération pour ajouter modifier quelques éléments simples d'un événement sans le modifiier
This commit is contained in:
parent
e3c14437ac
commit
11d5cf9aa4
@ -182,6 +182,57 @@ class EventForm(ModelForm):
|
|||||||
self.cleaned_data['local_image'] = File(name=basename, file=open(old, "rb"))
|
self.cleaned_data['local_image'] = File(name=basename, file=open(old, "rb"))
|
||||||
|
|
||||||
|
|
||||||
|
class MultipleChoiceFieldAcceptAll(MultipleChoiceField):
|
||||||
|
def validate(self, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class EventModerateForm(ModelForm):
|
||||||
|
|
||||||
|
tags = MultipleChoiceField(
|
||||||
|
label=_("Tags"),
|
||||||
|
help_text=_('Select tags from existing ones.'),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
new_tags = MultipleChoiceFieldAcceptAll(
|
||||||
|
label=_("New tags"),
|
||||||
|
help_text=_('Create new labels (sparingly).'),
|
||||||
|
widget=DynamicArrayWidget(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
fields = [
|
||||||
|
"status",
|
||||||
|
"category",
|
||||||
|
"exact_location",
|
||||||
|
"tags"
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.fields['category'].queryset = self.fields['category'].queryset.order_by('name')
|
||||||
|
self.fields['category'].empty_label = None
|
||||||
|
self.fields['category'].initial = Category.get_default_category()
|
||||||
|
self.fields['tags'].choices = Tag.get_tag_groups(all=True)
|
||||||
|
|
||||||
|
def clean_new_tags(self):
|
||||||
|
return list(set(self.cleaned_data.get("new_tags")))
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
super().clean()
|
||||||
|
|
||||||
|
if self.cleaned_data['tags'] is None:
|
||||||
|
self.cleaned_data['tags'] = []
|
||||||
|
|
||||||
|
if not self.cleaned_data.get('new_tags') is None:
|
||||||
|
self.cleaned_data['tags'] += self.cleaned_data.get('new_tags')
|
||||||
|
|
||||||
|
self.cleaned_data['tags'] = list(set(self.cleaned_data['tags']))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BatchImportationForm(Form):
|
class BatchImportationForm(Form):
|
||||||
json = CharField(
|
json = CharField(
|
||||||
@ -270,7 +321,6 @@ class FixDuplicates(Form):
|
|||||||
|
|
||||||
def get_selected_event(self, edup):
|
def get_selected_event(self, edup):
|
||||||
selected = self.get_selected_event_code()
|
selected = self.get_selected_event_code()
|
||||||
logger.warning("selected " + str(selected))
|
|
||||||
for e in edup.get_duplicated():
|
for e in edup.get_duplicated():
|
||||||
if e.pk == selected:
|
if e.pk == selected:
|
||||||
return e
|
return e
|
||||||
|
@ -790,6 +790,12 @@ class Event(models.Model):
|
|||||||
def set_no_modification_date_changed(self):
|
def set_no_modification_date_changed(self):
|
||||||
self.no_modification_date_changed = True
|
self.no_modification_date_changed = True
|
||||||
|
|
||||||
|
def set_in_moderation_process(self):
|
||||||
|
self.in_moderation_process = True
|
||||||
|
|
||||||
|
def is_in_moderation_process(self):
|
||||||
|
return hasattr(self, "in_moderation_process")
|
||||||
|
|
||||||
def update_modification_dates(self):
|
def update_modification_dates(self):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
if not self.id:
|
if not self.id:
|
||||||
@ -798,6 +804,8 @@ class Event(models.Model):
|
|||||||
self.imported_date = now
|
self.imported_date = now
|
||||||
if self.modified_date is None or not self.is_no_modification_date_changed():
|
if self.modified_date is None or not self.is_no_modification_date_changed():
|
||||||
self.modified_date = now
|
self.modified_date = now
|
||||||
|
if self.is_in_moderation_process():
|
||||||
|
self.moderated_date = now
|
||||||
|
|
||||||
def get_recurrence_at_date(self, year, month, day):
|
def get_recurrence_at_date(self, year, month, day):
|
||||||
dtstart = timezone.make_aware(
|
dtstart = timezone.make_aware(
|
||||||
|
@ -1399,4 +1399,9 @@ form.messages div, form.moderation-events {
|
|||||||
clear: both;
|
clear: both;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.moderate-preview .event-body {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
@ -1,6 +1,12 @@
|
|||||||
|
|
||||||
{% load utils_extra %}
|
{% load utils_extra %}
|
||||||
|
|
||||||
|
{% if event.moderated_date %}
|
||||||
|
<a href="{% url 'moderate_event' event.id %}" role="button">Modérer de nouveau {% picto_from_name "check-square" %}</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'moderate_event' event.id %}" role="button">Modérer {% picto_from_name "check-square" %}</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% 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 %}
|
||||||
|
@ -60,7 +60,7 @@ Création d'une copie de {% else %}
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div id="container"></div>
|
|
||||||
{% if form.is_clone_from_url %}
|
{% if form.is_clone_from_url %}
|
||||||
{% url "add_event_details" as urlparam %}
|
{% url "add_event_details" as urlparam %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
{% extends "agenda_culturel/page.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}{% block og_title %}Modération de l'événement {{ object.title }} ({{ object.start_day }}){% endblock %}{% endblock %}
|
||||||
|
|
||||||
|
{% block ajouter-bouton %}{% block ajouter-menu %}{% endblock %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block entete_header %}
|
||||||
|
<script src="{% static 'choicejs/choices.min.js' %}"></script>
|
||||||
|
|
||||||
|
<script src="{% url 'jsi18n' %}"></script>
|
||||||
|
<script src="/static/admin/js/vendor/jquery/jquery.js"></script>
|
||||||
|
<script src="/static/admin/js/jquery.init.js"></script>
|
||||||
|
<script src="/static/admin/js/admin/DateTimeShortcuts.js"></script>
|
||||||
|
<script src="{% static 'recurrence/js/recurrence.js' %}"></script>
|
||||||
|
<script src="{% static 'recurrence/js/recurrence.js' %}"></script>
|
||||||
|
<script src="/static/admin/js/admin/RelatedObjectLookups.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<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 fluid %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% load static_content_extra %}
|
||||||
|
|
||||||
|
<article class="moderate-preview">
|
||||||
|
<header>
|
||||||
|
<h1>Modération de l'événement {{ object.title }} ({{ object.start_day }})</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{% include "agenda_culturel/single-event/event-single-inc.html" with event=event filter=filter %}
|
||||||
|
|
||||||
|
<form method="post" enctype="multipart/form-data">{% csrf_token %}
|
||||||
|
{{ form.media }}
|
||||||
|
{{ 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="Enregistrer">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if object %}
|
||||||
|
{% include "agenda_culturel/event-info-inc.html" %}
|
||||||
|
{% endif %}
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const element = document.querySelector('#id_exact_location');
|
||||||
|
const choices = new Choices(element);
|
||||||
|
|
||||||
|
show_firstgroup = {
|
||||||
|
choice(classes, choice) {
|
||||||
|
const i = Choices.defaults.templates.choice.call(this, classes, choice);
|
||||||
|
i.classList.add("visible");
|
||||||
|
return i;
|
||||||
|
},
|
||||||
|
choiceGroup(classes, group) {
|
||||||
|
const g = Choices.defaults.templates.choiceGroup.call(this, classes, group);
|
||||||
|
g.classList.add("visible");
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const tags = document.querySelector('#id_tags');
|
||||||
|
const choices_tags = new Choices(tags,
|
||||||
|
{
|
||||||
|
placeholderValue: 'Sélectionner les étiquettes à ajouter',
|
||||||
|
allowHTML: true,
|
||||||
|
delimiter: ',',
|
||||||
|
removeItemButton: true,
|
||||||
|
shouldSort: false,
|
||||||
|
callbackOnCreateTemplates: () => (show_firstgroup)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -49,6 +49,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
<div class="event-body">
|
||||||
|
|
||||||
|
|
||||||
{% if event.has_image_url %}
|
{% if event.has_image_url %}
|
||||||
@ -58,6 +59,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<p>{{ event.description |linebreaks | robust_urlize }}</p>
|
<p>{{ event.description |linebreaks | robust_urlize }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<footer class="infos-and-buttons">
|
<footer class="infos-and-buttons">
|
||||||
<div class="infos">
|
<div class="infos">
|
||||||
|
@ -32,6 +32,7 @@ urlpatterns = [
|
|||||||
name="view_event",
|
name="view_event",
|
||||||
),
|
),
|
||||||
path("event/<int:pk>/edit", EventUpdateView.as_view(), name="edit_event"),
|
path("event/<int:pk>/edit", EventUpdateView.as_view(), name="edit_event"),
|
||||||
|
path("event/<int:pk>/moderate", EventModerateView.as_view(), name="moderate_event"),
|
||||||
path("event/<int:pk>/clone/edit", EventUpdateView.as_view(), name="clone_edit"),
|
path("event/<int:pk>/clone/edit", EventUpdateView.as_view(), name="clone_edit"),
|
||||||
path("event/<int:pk>/update-from-source", update_from_source, name="update_from_source"),
|
path("event/<int:pk>/update-from-source", update_from_source, name="update_from_source"),
|
||||||
path(
|
path(
|
||||||
|
@ -31,7 +31,8 @@ from .forms import (
|
|||||||
CategorisationForm,
|
CategorisationForm,
|
||||||
EventAddPlaceForm,
|
EventAddPlaceForm,
|
||||||
PlaceForm,
|
PlaceForm,
|
||||||
MultipleHiddenInput
|
MultipleHiddenInput,
|
||||||
|
EventModerateForm
|
||||||
)
|
)
|
||||||
|
|
||||||
from .filters import (
|
from .filters import (
|
||||||
@ -333,6 +334,23 @@ class EventUpdateView(
|
|||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class EventModerateView(
|
||||||
|
SuccessMessageMixin, PermissionRequiredMixin, LoginRequiredMixin, UpdateView
|
||||||
|
):
|
||||||
|
model = Event
|
||||||
|
permission_required = "agenda_culturel.change_event"
|
||||||
|
template_name = "agenda_culturel/event_form_moderate.html"
|
||||||
|
form_class = EventModerateForm
|
||||||
|
success_message = _("The event has been successfully moderated.")
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
|
||||||
|
form.instance.set_no_modification_date_changed()
|
||||||
|
form.instance.set_in_moderation_process()
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EventDeleteView(
|
class EventDeleteView(
|
||||||
SuccessMessageMixin, PermissionRequiredMixin, LoginRequiredMixin, DeleteView
|
SuccessMessageMixin, PermissionRequiredMixin, LoginRequiredMixin, DeleteView
|
||||||
):
|
):
|
||||||
|
Loading…
Reference in New Issue
Block a user