Séparation des vues event dupliqués
This commit is contained in:
parent
b529a33b24
commit
9ec22919f1
@ -26,6 +26,13 @@ from .views import (
|
|||||||
# Errors
|
# Errors
|
||||||
internal_server_error,
|
internal_server_error,
|
||||||
page_not_found,
|
page_not_found,
|
||||||
|
# Event duplicates
|
||||||
|
DuplicatedEventsDetailView,
|
||||||
|
duplicates,
|
||||||
|
fix_duplicate,
|
||||||
|
merge_duplicate,
|
||||||
|
set_duplicate,
|
||||||
|
update_duplicate_event,
|
||||||
# General pages
|
# General pages
|
||||||
about,
|
about,
|
||||||
import_requirements,
|
import_requirements,
|
||||||
@ -88,18 +95,14 @@ from .views import (
|
|||||||
recent,
|
recent,
|
||||||
administration,
|
administration,
|
||||||
activite,
|
activite,
|
||||||
fix_duplicate,
|
|
||||||
clear_cache,
|
clear_cache,
|
||||||
export_event_ical,
|
export_event_ical,
|
||||||
MessageDeleteView,
|
MessageDeleteView,
|
||||||
EventDetailView,
|
EventDetailView,
|
||||||
EventUpdateView,
|
EventUpdateView,
|
||||||
duplicates,
|
|
||||||
DuplicatedEventsDetailView,
|
|
||||||
StaticContentCreateView,
|
StaticContentCreateView,
|
||||||
StaticContentUpdateView,
|
StaticContentUpdateView,
|
||||||
MessageCreateView,
|
MessageCreateView,
|
||||||
merge_duplicate,
|
|
||||||
EventCreateView,
|
EventCreateView,
|
||||||
event_search,
|
event_search,
|
||||||
event_search_full,
|
event_search_full,
|
||||||
@ -107,14 +110,12 @@ from .views import (
|
|||||||
update_from_source,
|
update_from_source,
|
||||||
change_status_event,
|
change_status_event,
|
||||||
EventDeleteView,
|
EventDeleteView,
|
||||||
set_duplicate,
|
|
||||||
import_event_proxy,
|
import_event_proxy,
|
||||||
import_from_url,
|
import_from_url,
|
||||||
import_from_urls,
|
import_from_urls,
|
||||||
view_messages,
|
view_messages,
|
||||||
MessageUpdateView,
|
MessageUpdateView,
|
||||||
statistics,
|
statistics,
|
||||||
update_duplicate_event,
|
|
||||||
UserProfileUpdateView,
|
UserProfileUpdateView,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -167,6 +168,25 @@ urlpatterns = [
|
|||||||
# Errors
|
# Errors
|
||||||
path("500/", internal_server_error, name="internal_server_error"),
|
path("500/", internal_server_error, name="internal_server_error"),
|
||||||
path("404/", page_not_found, name="page_not_found"),
|
path("404/", page_not_found, name="page_not_found"),
|
||||||
|
path("duplicates/<int:pk>/merge", merge_duplicate, name="merge_duplicate"),
|
||||||
|
path(
|
||||||
|
"event/<int:year>/<int:month>/<int:day>/<int:pk>/set_duplicate",
|
||||||
|
set_duplicate,
|
||||||
|
name="set_duplicate",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"duplicates/<int:pk>/update/<int:epk>",
|
||||||
|
update_duplicate_event,
|
||||||
|
name="update_event",
|
||||||
|
),
|
||||||
|
# Event duplicates
|
||||||
|
path(
|
||||||
|
"duplicates/<int:pk>",
|
||||||
|
DuplicatedEventsDetailView.as_view(),
|
||||||
|
name="view_duplicate",
|
||||||
|
),
|
||||||
|
path("duplicates/", duplicates, name="duplicates"),
|
||||||
|
path("duplicates/<int:pk>/fix", fix_duplicate, name="fix_duplicate"),
|
||||||
# General pages
|
# General pages
|
||||||
path("a-propos", about, name="about"),
|
path("a-propos", about, name="about"),
|
||||||
path("besoin-pour-import", import_requirements, name="import_requirements"),
|
path("besoin-pour-import", import_requirements, name="import_requirements"),
|
||||||
@ -424,11 +444,6 @@ urlpatterns = [
|
|||||||
name="change_status_event",
|
name="change_status_event",
|
||||||
),
|
),
|
||||||
path("event/<int:pk>/delete", EventDeleteView.as_view(), name="delete_event"),
|
path("event/<int:pk>/delete", EventDeleteView.as_view(), name="delete_event"),
|
||||||
path(
|
|
||||||
"event/<int:year>/<int:month>/<int:day>/<int:pk>/set_duplicate",
|
|
||||||
set_duplicate,
|
|
||||||
name="set_duplicate",
|
|
||||||
),
|
|
||||||
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"),
|
||||||
@ -463,19 +478,6 @@ urlpatterns = [
|
|||||||
name="delete_message",
|
name="delete_message",
|
||||||
),
|
),
|
||||||
path("rimports/<int:pk>/stats", statistics, name="stats_rimport"),
|
path("rimports/<int:pk>/stats", statistics, name="stats_rimport"),
|
||||||
path("duplicates/", duplicates, name="duplicates"),
|
|
||||||
path(
|
|
||||||
"duplicates/<int:pk>",
|
|
||||||
DuplicatedEventsDetailView.as_view(),
|
|
||||||
name="view_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>/update/<int:epk>",
|
|
||||||
update_duplicate_event,
|
|
||||||
name="update_event",
|
|
||||||
),
|
|
||||||
path(
|
path(
|
||||||
"organisme/<int:organisation_pk>/ical",
|
"organisme/<int:organisation_pk>/ical",
|
||||||
export_ical,
|
export_ical,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from .oldviews import *
|
from .oldviews import *
|
||||||
from .categorisation_rules_view import *
|
from .categorisation_rules_view import *
|
||||||
|
from .event_duplicate_views import *
|
||||||
from .errors import *
|
from .errors import *
|
||||||
from .general_pages_views import *
|
from .general_pages_views import *
|
||||||
from .import_batch_views import *
|
from .import_batch_views import *
|
||||||
|
344
src/agenda_culturel/views/event_duplicate_views.py
Normal file
344
src/agenda_culturel/views/event_duplicate_views.py
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
from datetime import date
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.core.paginator import PageNotAnInteger, EmptyPage
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.shortcuts import get_object_or_404, render
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views.generic import DetailView, UpdateView
|
||||||
|
|
||||||
|
from src.agenda_culturel.calendar import CalendarDay
|
||||||
|
from src.agenda_culturel.filters import DuplicatedEventsFilter
|
||||||
|
from src.agenda_culturel.forms import MergeDuplicates, FixDuplicates, SelectEventInList
|
||||||
|
from src.agenda_culturel.models import DuplicatedEvents, Event
|
||||||
|
from src.agenda_culturel.views import PaginatorFilter
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicatedEventsDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
model = DuplicatedEvents
|
||||||
|
template_name = "agenda_culturel/duplicate.html"
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url="/accounts/login/")
|
||||||
|
@permission_required(
|
||||||
|
["agenda_culturel.change_event", "agenda_culturel.change_duplicatedevents"]
|
||||||
|
)
|
||||||
|
def update_duplicate_event(request, pk, epk):
|
||||||
|
edup = get_object_or_404(DuplicatedEvents, pk=pk)
|
||||||
|
event = get_object_or_404(Event, pk=epk)
|
||||||
|
|
||||||
|
form = MergeDuplicates(duplicates=edup, event=event)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = MergeDuplicates(request.POST, duplicates=edup)
|
||||||
|
if form.is_valid():
|
||||||
|
for f in edup.get_items_comparison():
|
||||||
|
if not f["similar"]:
|
||||||
|
selected = form.get_selected_events(f["key"])
|
||||||
|
if selected is not None:
|
||||||
|
if isinstance(selected, list):
|
||||||
|
values = [
|
||||||
|
x
|
||||||
|
for x in [getattr(s, f["key"]) for s in selected]
|
||||||
|
if x is not None
|
||||||
|
]
|
||||||
|
if len(values) != 0:
|
||||||
|
if isinstance(values[0], str):
|
||||||
|
setattr(event, f["key"], "\n".join(values))
|
||||||
|
else:
|
||||||
|
setattr(event, f["key"], sum(values, []))
|
||||||
|
else:
|
||||||
|
if f["key"] == "organisers":
|
||||||
|
event.organisers.set(selected.organisers.all())
|
||||||
|
else:
|
||||||
|
setattr(
|
||||||
|
event,
|
||||||
|
f["key"],
|
||||||
|
getattr(selected, f["key"]),
|
||||||
|
)
|
||||||
|
if f["key"] == "image":
|
||||||
|
setattr(
|
||||||
|
event,
|
||||||
|
"local_image",
|
||||||
|
getattr(selected, "local_image"),
|
||||||
|
)
|
||||||
|
|
||||||
|
event.other_versions.fix(event)
|
||||||
|
event.save()
|
||||||
|
|
||||||
|
messages.info(request, _("Update successfully completed."))
|
||||||
|
return HttpResponseRedirect(event.get_absolute_url())
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"agenda_culturel/update_duplicate.html",
|
||||||
|
context={
|
||||||
|
"form": form,
|
||||||
|
"object": edup,
|
||||||
|
"event_id": edup.get_event_index(event),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url="/accounts/login/")
|
||||||
|
@permission_required(
|
||||||
|
["agenda_culturel.change_event", "agenda_culturel.change_duplicatedevents"]
|
||||||
|
)
|
||||||
|
def merge_duplicate(request, pk):
|
||||||
|
edup = get_object_or_404(DuplicatedEvents, pk=pk)
|
||||||
|
form = MergeDuplicates(duplicates=edup)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = MergeDuplicates(request.POST, duplicates=edup)
|
||||||
|
if form.is_valid():
|
||||||
|
events = edup.get_duplicated()
|
||||||
|
|
||||||
|
# build fields for the new event
|
||||||
|
new_event_data = {}
|
||||||
|
for f in edup.get_items_comparison():
|
||||||
|
if f["similar"]:
|
||||||
|
new_event_data[f["key"]] = getattr(events[0], f["key"])
|
||||||
|
else:
|
||||||
|
selected = form.get_selected_events(f["key"])
|
||||||
|
if selected is None:
|
||||||
|
new_event_data[f["key"]] = None
|
||||||
|
elif isinstance(selected, list):
|
||||||
|
values = [
|
||||||
|
x
|
||||||
|
for x in [getattr(s, f["key"]) for s in selected]
|
||||||
|
if x is not None
|
||||||
|
]
|
||||||
|
if len(values) == 0:
|
||||||
|
new_event_data[f["key"]] = None
|
||||||
|
else:
|
||||||
|
if isinstance(values[0], str):
|
||||||
|
new_event_data[f["key"]] = "\n".join(values)
|
||||||
|
else:
|
||||||
|
new_event_data[f["key"]] = sum(values, [])
|
||||||
|
else:
|
||||||
|
new_event_data[f["key"]] = getattr(selected, f["key"])
|
||||||
|
if f["key"] == "image" and "local_image" not in new_event_data:
|
||||||
|
new_event_data["local_image"] = getattr(
|
||||||
|
selected, "local_image"
|
||||||
|
)
|
||||||
|
|
||||||
|
organisers = new_event_data.pop("organisers", None)
|
||||||
|
# create a new event that merge the selected events
|
||||||
|
new_event = Event(**new_event_data)
|
||||||
|
new_event.status = Event.STATUS.PUBLISHED
|
||||||
|
new_event.other_versions = edup
|
||||||
|
new_event.save()
|
||||||
|
if organisers is not None:
|
||||||
|
new_event.organisers.set(organisers.all())
|
||||||
|
edup.fix(new_event)
|
||||||
|
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
_("Creation of a merged event has been successfully completed."),
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect(new_event.get_absolute_url())
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"agenda_culturel/merge_duplicate.html",
|
||||||
|
context={"form": form, "object": edup},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url="/accounts/login/")
|
||||||
|
@permission_required(
|
||||||
|
["agenda_culturel.change_event", "agenda_culturel.change_duplicatedevents"]
|
||||||
|
)
|
||||||
|
def fix_duplicate(request, pk):
|
||||||
|
edup = get_object_or_404(DuplicatedEvents.objects.select_related(), pk=pk)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = FixDuplicates(request.POST, edup=edup)
|
||||||
|
|
||||||
|
if form.is_valid():
|
||||||
|
if form.is_action_no_duplicates():
|
||||||
|
# all events are different
|
||||||
|
events = edup.get_duplicated()
|
||||||
|
|
||||||
|
# get redirection date
|
||||||
|
if len(events) == 0:
|
||||||
|
date = None
|
||||||
|
else:
|
||||||
|
s_events = [e for e in events if not e.has_recurrences()]
|
||||||
|
if len(s_events) != 0:
|
||||||
|
s_event = s_events[0]
|
||||||
|
else:
|
||||||
|
s_event = events[0]
|
||||||
|
date = s_event.start_day
|
||||||
|
|
||||||
|
messages.success(request, _("Events have been marked as unduplicated."))
|
||||||
|
# delete the duplicated event (other_versions will be set to None on all events)
|
||||||
|
edup.delete()
|
||||||
|
if date is None:
|
||||||
|
return HttpResponseRedirect(reverse_lazy("home"))
|
||||||
|
else:
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse_lazy("day_view", args=[date.year, date.month, date.day])
|
||||||
|
)
|
||||||
|
|
||||||
|
elif form.is_action_select():
|
||||||
|
# one element has been selected to be the representative
|
||||||
|
selected = form.get_selected_event(edup)
|
||||||
|
if selected is None:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_(
|
||||||
|
"The selected item is no longer included in the list of duplicates. Someone else has probably modified the list in the meantime."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
edup.fix(selected)
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The selected event has been set as representative"),
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect(edup.get_absolute_url())
|
||||||
|
elif form.is_action_remove():
|
||||||
|
# one element is removed from the set
|
||||||
|
event = form.get_selected_event(edup)
|
||||||
|
if event is None:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_(
|
||||||
|
"The selected item is no longer included in the list of duplicates. Someone else has probably modified the list in the meantime."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect(edup.get_absolute_url())
|
||||||
|
else:
|
||||||
|
event.other_versions = None
|
||||||
|
if edup.representative == event:
|
||||||
|
edup.representative = None
|
||||||
|
event.set_no_modification_date_changed()
|
||||||
|
event.save()
|
||||||
|
edup.save()
|
||||||
|
edup.events = [e for e in edup.events if e.pk != event.pk]
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_(
|
||||||
|
"The event has been withdrawn from the group and made independent."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if edup.nb_duplicated() == 1:
|
||||||
|
return HttpResponseRedirect(edup.get_absolute_url())
|
||||||
|
else:
|
||||||
|
form = FixDuplicates(edup=edup)
|
||||||
|
elif form.is_action_update():
|
||||||
|
# otherwise, an event will be updated using other elements
|
||||||
|
event = form.get_selected_event(edup)
|
||||||
|
if event is None:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_(
|
||||||
|
"The selected item is no longer included in the list of duplicates. Someone else has probably modified the list in the meantime."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect(edup.get_absolute_url())
|
||||||
|
else:
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse_lazy("update_event", args=[edup.pk, event.pk])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# otherwise, a new event will be created using a merging process
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse_lazy("merge_duplicate", args=[edup.pk])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
form = FixDuplicates(edup=edup)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"agenda_culturel/fix_duplicate.html",
|
||||||
|
context={"form": form, "object": edup},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicatedEventsUpdateView(
|
||||||
|
LoginRequiredMixin, UpdateView
|
||||||
|
): # Todo à supprimer, pas d’utilisation ?
|
||||||
|
model = DuplicatedEvents
|
||||||
|
fields = ()
|
||||||
|
template_name = "agenda_culturel/fix_duplicate.html"
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url="/accounts/login/")
|
||||||
|
@permission_required("agenda_culturel.view_duplicatedevents")
|
||||||
|
def duplicates(request):
|
||||||
|
nb_removed = DuplicatedEvents.remove_singletons()
|
||||||
|
if nb_removed > 0:
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("Cleaning up duplicates: {} item(s) fixed.").format(nb_removed),
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = DuplicatedEventsFilter(
|
||||||
|
request.GET, queryset=DuplicatedEvents.objects.all().order_by("-pk")
|
||||||
|
)
|
||||||
|
paginator = PaginatorFilter(filter, 10, request)
|
||||||
|
page = request.GET.get("page")
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = paginator.page(page)
|
||||||
|
except PageNotAnInteger:
|
||||||
|
response = paginator.page(1)
|
||||||
|
except EmptyPage:
|
||||||
|
response = paginator.page(paginator.num_pages)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"agenda_culturel/duplicates.html",
|
||||||
|
{
|
||||||
|
"filter": filter,
|
||||||
|
"paginator_filter": response,
|
||||||
|
"paginator": paginator,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def set_duplicate(request, year, month, day, pk):
|
||||||
|
event = get_object_or_404(Event, pk=pk)
|
||||||
|
cday = CalendarDay(date(year, month, day))
|
||||||
|
others = [
|
||||||
|
e
|
||||||
|
for e in cday.get_events()
|
||||||
|
if e != event
|
||||||
|
and (event.other_versions is None or event.other_versions != e.other_versions)
|
||||||
|
and e.status != Event.STATUS.TRASH
|
||||||
|
]
|
||||||
|
|
||||||
|
form = SelectEventInList(events=others)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = SelectEventInList(request.POST, events=others)
|
||||||
|
if form.is_valid():
|
||||||
|
selected = [o for o in others if o.pk == int(form.cleaned_data["event"])]
|
||||||
|
event.set_other_versions(selected)
|
||||||
|
# save them without updating modified date
|
||||||
|
event.set_no_modification_date_changed()
|
||||||
|
event.save()
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
messages.success(request, _("The event was successfully duplicated."))
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse_lazy("view_duplicate", args=[event.other_versions.pk])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
_(
|
||||||
|
"The event has been successfully flagged as a duplicate. The moderation team will deal with your suggestion shortly."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect(event.get_absolute_url())
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"agenda_culturel/set_duplicate.html",
|
||||||
|
context={"form": form, "event": event},
|
||||||
|
)
|
@ -42,13 +42,12 @@ from django.views.generic.edit import (
|
|||||||
from honeypot.decorators import check_honeypot
|
from honeypot.decorators import check_honeypot
|
||||||
|
|
||||||
from .utils import get_event_qs
|
from .utils import get_event_qs
|
||||||
from ..calendar import CalendarDay, CalendarList, CalendarMonth, CalendarWeek
|
from ..calendar import CalendarList, CalendarMonth, CalendarWeek
|
||||||
from ..celery import (
|
from ..celery import (
|
||||||
import_events_from_url,
|
import_events_from_url,
|
||||||
import_events_from_urls,
|
import_events_from_urls,
|
||||||
)
|
)
|
||||||
from ..filters import (
|
from ..filters import (
|
||||||
DuplicatedEventsFilter,
|
|
||||||
EventFilter,
|
EventFilter,
|
||||||
EventFilterAdmin,
|
EventFilterAdmin,
|
||||||
MessagesFilterAdmin,
|
MessagesFilterAdmin,
|
||||||
@ -58,11 +57,8 @@ from ..filters import (
|
|||||||
from ..forms import (
|
from ..forms import (
|
||||||
EventForm,
|
EventForm,
|
||||||
EventFormWithContact,
|
EventFormWithContact,
|
||||||
FixDuplicates,
|
|
||||||
MergeDuplicates,
|
|
||||||
MessageEventForm,
|
MessageEventForm,
|
||||||
MessageForm,
|
MessageForm,
|
||||||
SelectEventInList,
|
|
||||||
SimpleContactForm,
|
SimpleContactForm,
|
||||||
URLSubmissionFormSet,
|
URLSubmissionFormSet,
|
||||||
URLSubmissionFormWithContact,
|
URLSubmissionFormWithContact,
|
||||||
@ -1293,336 +1289,6 @@ def event_search_full(request):
|
|||||||
return event_search(request, True)
|
return event_search(request, True)
|
||||||
|
|
||||||
|
|
||||||
#########################
|
|
||||||
## duplicated events
|
|
||||||
#########################
|
|
||||||
|
|
||||||
|
|
||||||
class DuplicatedEventsDetailView(LoginRequiredMixin, DetailView):
|
|
||||||
model = DuplicatedEvents
|
|
||||||
template_name = "agenda_culturel/duplicate.html"
|
|
||||||
|
|
||||||
|
|
||||||
@login_required(login_url="/accounts/login/")
|
|
||||||
@permission_required(
|
|
||||||
["agenda_culturel.change_event", "agenda_culturel.change_duplicatedevents"]
|
|
||||||
)
|
|
||||||
def update_duplicate_event(request, pk, epk):
|
|
||||||
edup = get_object_or_404(DuplicatedEvents, pk=pk)
|
|
||||||
event = get_object_or_404(Event, pk=epk)
|
|
||||||
|
|
||||||
form = MergeDuplicates(duplicates=edup, event=event)
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = MergeDuplicates(request.POST, duplicates=edup)
|
|
||||||
if form.is_valid():
|
|
||||||
for f in edup.get_items_comparison():
|
|
||||||
if not f["similar"]:
|
|
||||||
selected = form.get_selected_events(f["key"])
|
|
||||||
if selected is not None:
|
|
||||||
if isinstance(selected, list):
|
|
||||||
values = [
|
|
||||||
x
|
|
||||||
for x in [getattr(s, f["key"]) for s in selected]
|
|
||||||
if x is not None
|
|
||||||
]
|
|
||||||
if len(values) != 0:
|
|
||||||
if isinstance(values[0], str):
|
|
||||||
setattr(event, f["key"], "\n".join(values))
|
|
||||||
else:
|
|
||||||
setattr(event, f["key"], sum(values, []))
|
|
||||||
else:
|
|
||||||
if f["key"] == "organisers":
|
|
||||||
event.organisers.set(selected.organisers.all())
|
|
||||||
else:
|
|
||||||
setattr(
|
|
||||||
event,
|
|
||||||
f["key"],
|
|
||||||
getattr(selected, f["key"]),
|
|
||||||
)
|
|
||||||
if f["key"] == "image":
|
|
||||||
setattr(
|
|
||||||
event,
|
|
||||||
"local_image",
|
|
||||||
getattr(selected, "local_image"),
|
|
||||||
)
|
|
||||||
|
|
||||||
event.other_versions.fix(event)
|
|
||||||
event.save()
|
|
||||||
|
|
||||||
messages.info(request, _("Update successfully completed."))
|
|
||||||
return HttpResponseRedirect(event.get_absolute_url())
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"agenda_culturel/update_duplicate.html",
|
|
||||||
context={
|
|
||||||
"form": form,
|
|
||||||
"object": edup,
|
|
||||||
"event_id": edup.get_event_index(event),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required(login_url="/accounts/login/")
|
|
||||||
@permission_required(
|
|
||||||
["agenda_culturel.change_event", "agenda_culturel.change_duplicatedevents"]
|
|
||||||
)
|
|
||||||
def merge_duplicate(request, pk):
|
|
||||||
edup = get_object_or_404(DuplicatedEvents, pk=pk)
|
|
||||||
form = MergeDuplicates(duplicates=edup)
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = MergeDuplicates(request.POST, duplicates=edup)
|
|
||||||
if form.is_valid():
|
|
||||||
events = edup.get_duplicated()
|
|
||||||
|
|
||||||
# build fields for the new event
|
|
||||||
new_event_data = {}
|
|
||||||
for f in edup.get_items_comparison():
|
|
||||||
if f["similar"]:
|
|
||||||
new_event_data[f["key"]] = getattr(events[0], f["key"])
|
|
||||||
else:
|
|
||||||
selected = form.get_selected_events(f["key"])
|
|
||||||
if selected is None:
|
|
||||||
new_event_data[f["key"]] = None
|
|
||||||
elif isinstance(selected, list):
|
|
||||||
values = [
|
|
||||||
x
|
|
||||||
for x in [getattr(s, f["key"]) for s in selected]
|
|
||||||
if x is not None
|
|
||||||
]
|
|
||||||
if len(values) == 0:
|
|
||||||
new_event_data[f["key"]] = None
|
|
||||||
else:
|
|
||||||
if isinstance(values[0], str):
|
|
||||||
new_event_data[f["key"]] = "\n".join(values)
|
|
||||||
else:
|
|
||||||
new_event_data[f["key"]] = sum(values, [])
|
|
||||||
else:
|
|
||||||
new_event_data[f["key"]] = getattr(selected, f["key"])
|
|
||||||
if f["key"] == "image" and "local_image" not in new_event_data:
|
|
||||||
new_event_data["local_image"] = getattr(
|
|
||||||
selected, "local_image"
|
|
||||||
)
|
|
||||||
|
|
||||||
organisers = new_event_data.pop("organisers", None)
|
|
||||||
# create a new event that merge the selected events
|
|
||||||
new_event = Event(**new_event_data)
|
|
||||||
new_event.status = Event.STATUS.PUBLISHED
|
|
||||||
new_event.other_versions = edup
|
|
||||||
new_event.save()
|
|
||||||
if organisers is not None:
|
|
||||||
new_event.organisers.set(organisers.all())
|
|
||||||
edup.fix(new_event)
|
|
||||||
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
_("Creation of a merged event has been successfully completed."),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(new_event.get_absolute_url())
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"agenda_culturel/merge_duplicate.html",
|
|
||||||
context={"form": form, "object": edup},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required(login_url="/accounts/login/")
|
|
||||||
@permission_required(
|
|
||||||
["agenda_culturel.change_event", "agenda_culturel.change_duplicatedevents"]
|
|
||||||
)
|
|
||||||
def fix_duplicate(request, pk):
|
|
||||||
edup = get_object_or_404(DuplicatedEvents.objects.select_related(), pk=pk)
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = FixDuplicates(request.POST, edup=edup)
|
|
||||||
|
|
||||||
if form.is_valid():
|
|
||||||
if form.is_action_no_duplicates():
|
|
||||||
# all events are different
|
|
||||||
events = edup.get_duplicated()
|
|
||||||
|
|
||||||
# get redirection date
|
|
||||||
if len(events) == 0:
|
|
||||||
date = None
|
|
||||||
else:
|
|
||||||
s_events = [e for e in events if not e.has_recurrences()]
|
|
||||||
if len(s_events) != 0:
|
|
||||||
s_event = s_events[0]
|
|
||||||
else:
|
|
||||||
s_event = events[0]
|
|
||||||
date = s_event.start_day
|
|
||||||
|
|
||||||
messages.success(request, _("Events have been marked as unduplicated."))
|
|
||||||
# delete the duplicated event (other_versions will be set to None on all events)
|
|
||||||
edup.delete()
|
|
||||||
if date is None:
|
|
||||||
return HttpResponseRedirect(reverse_lazy("home"))
|
|
||||||
else:
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse_lazy("day_view", args=[date.year, date.month, date.day])
|
|
||||||
)
|
|
||||||
|
|
||||||
elif form.is_action_select():
|
|
||||||
# one element has been selected to be the representative
|
|
||||||
selected = form.get_selected_event(edup)
|
|
||||||
if selected is None:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_(
|
|
||||||
"The selected item is no longer included in the list of duplicates. Someone else has probably modified the list in the meantime."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
edup.fix(selected)
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
_("The selected event has been set as representative"),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(edup.get_absolute_url())
|
|
||||||
elif form.is_action_remove():
|
|
||||||
# one element is removed from the set
|
|
||||||
event = form.get_selected_event(edup)
|
|
||||||
if event is None:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_(
|
|
||||||
"The selected item is no longer included in the list of duplicates. Someone else has probably modified the list in the meantime."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(edup.get_absolute_url())
|
|
||||||
else:
|
|
||||||
event.other_versions = None
|
|
||||||
if edup.representative == event:
|
|
||||||
edup.representative = None
|
|
||||||
event.set_no_modification_date_changed()
|
|
||||||
event.save()
|
|
||||||
edup.save()
|
|
||||||
edup.events = [e for e in edup.events if e.pk != event.pk]
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
_(
|
|
||||||
"The event has been withdrawn from the group and made independent."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if edup.nb_duplicated() == 1:
|
|
||||||
return HttpResponseRedirect(edup.get_absolute_url())
|
|
||||||
else:
|
|
||||||
form = FixDuplicates(edup=edup)
|
|
||||||
elif form.is_action_update():
|
|
||||||
# otherwise, an event will be updated using other elements
|
|
||||||
event = form.get_selected_event(edup)
|
|
||||||
if event is None:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_(
|
|
||||||
"The selected item is no longer included in the list of duplicates. Someone else has probably modified the list in the meantime."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(edup.get_absolute_url())
|
|
||||||
else:
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse_lazy("update_event", args=[edup.pk, event.pk])
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# otherwise, a new event will be created using a merging process
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse_lazy("merge_duplicate", args=[edup.pk])
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
form = FixDuplicates(edup=edup)
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"agenda_culturel/fix_duplicate.html",
|
|
||||||
context={"form": form, "object": edup},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DuplicatedEventsUpdateView(LoginRequiredMixin, UpdateView):
|
|
||||||
model = DuplicatedEvents
|
|
||||||
fields = ()
|
|
||||||
template_name = "agenda_culturel/fix_duplicate.html"
|
|
||||||
|
|
||||||
|
|
||||||
@login_required(login_url="/accounts/login/")
|
|
||||||
@permission_required("agenda_culturel.view_duplicatedevents")
|
|
||||||
def duplicates(request):
|
|
||||||
nb_removed = DuplicatedEvents.remove_singletons()
|
|
||||||
if nb_removed > 0:
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
_("Cleaning up duplicates: {} item(s) fixed.").format(nb_removed),
|
|
||||||
)
|
|
||||||
|
|
||||||
filter = DuplicatedEventsFilter(
|
|
||||||
request.GET, queryset=DuplicatedEvents.objects.all().order_by("-pk")
|
|
||||||
)
|
|
||||||
paginator = PaginatorFilter(filter, 10, request)
|
|
||||||
page = request.GET.get("page")
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = paginator.page(page)
|
|
||||||
except PageNotAnInteger:
|
|
||||||
response = paginator.page(1)
|
|
||||||
except EmptyPage:
|
|
||||||
response = paginator.page(paginator.num_pages)
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"agenda_culturel/duplicates.html",
|
|
||||||
{
|
|
||||||
"filter": filter,
|
|
||||||
"paginator_filter": response,
|
|
||||||
"paginator": paginator,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def set_duplicate(request, year, month, day, pk):
|
|
||||||
event = get_object_or_404(Event, pk=pk)
|
|
||||||
cday = CalendarDay(date(year, month, day))
|
|
||||||
others = [
|
|
||||||
e
|
|
||||||
for e in cday.get_events()
|
|
||||||
if e != event
|
|
||||||
and (event.other_versions is None or event.other_versions != e.other_versions)
|
|
||||||
and e.status != Event.STATUS.TRASH
|
|
||||||
]
|
|
||||||
|
|
||||||
form = SelectEventInList(events=others)
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = SelectEventInList(request.POST, events=others)
|
|
||||||
if form.is_valid():
|
|
||||||
selected = [o for o in others if o.pk == int(form.cleaned_data["event"])]
|
|
||||||
event.set_other_versions(selected)
|
|
||||||
# save them without updating modified date
|
|
||||||
event.set_no_modification_date_changed()
|
|
||||||
event.save()
|
|
||||||
if request.user.is_authenticated:
|
|
||||||
messages.success(request, _("The event was successfully duplicated."))
|
|
||||||
return HttpResponseRedirect(
|
|
||||||
reverse_lazy("view_duplicate", args=[event.other_versions.pk])
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
_(
|
|
||||||
"The event has been successfully flagged as a duplicate. The moderation team will deal with your suggestion shortly."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return HttpResponseRedirect(event.get_absolute_url())
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"agenda_culturel/set_duplicate.html",
|
|
||||||
context={"form": form, "event": event},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def statistics(request, pk=None):
|
def statistics(request, pk=None):
|
||||||
if pk is not None:
|
if pk is not None:
|
||||||
rimport = RecurrentImport.objects.filter(pk=pk)
|
rimport = RecurrentImport.objects.filter(pk=pk)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user