diff --git a/src/agenda_culturel/urls.py b/src/agenda_culturel/urls.py index a4c3c84..4c89592 100644 --- a/src/agenda_culturel/urls.py +++ b/src/agenda_culturel/urls.py @@ -37,6 +37,15 @@ from .views import ( add_import, cancel_import, update_orphan_events, + # Import récurrent + RecurrentImportCreateView, + RecurrentImportDeleteView, + RecurrentImportUpdateView, + recurrent_imports, + run_all_fb_rimports, + run_all_rimports, + run_rimport, + view_rimport, # Moderation EventModerateView, moderate_event_next, @@ -83,14 +92,8 @@ from .views import ( clear_cache, export_event_ical, MessageDeleteView, - run_all_fb_rimports, - run_all_rimports, EventDetailView, EventUpdateView, - RecurrentImportCreateView, - RecurrentImportDeleteView, - RecurrentImportUpdateView, - run_rimport, duplicates, DuplicatedEventsDetailView, StaticContentCreateView, @@ -100,7 +103,6 @@ from .views import ( EventCreateView, event_search, event_search_full, - recurrent_imports, delete_cm_spam, update_from_source, change_status_event, @@ -112,7 +114,6 @@ from .views import ( view_messages, MessageUpdateView, statistics, - view_rimport, update_duplicate_event, UserProfileUpdateView, ) @@ -181,6 +182,33 @@ urlpatterns = [ update_orphan_events, name="update_orphan_events", ), + # Import récurrent + path("rimports/add", RecurrentImportCreateView.as_view(), name="add_rimport"), + path( + "rimports//delete", + RecurrentImportDeleteView.as_view(), + name="delete_rimport", + ), + path( + "rimports//edit", + RecurrentImportUpdateView.as_view(), + name="edit_rimport", + ), + path("rimports/", recurrent_imports, name="recurrent_imports"), + path( + "rimports/status/", + recurrent_imports, + name="recurrent_imports_status", + ), + path("rimports/fb/run", run_all_fb_rimports, name="run_all_fb_rimports"), + path("rimports/run", run_all_rimports, name="run_all_rimports"), + path( + "rimports/status//run", + run_all_rimports, + name="run_all_rimports_status", + ), + path("rimports//run", run_rimport, name="run_rimport"), + path("rimports//view", view_rimport, name="view_rimport"), # Moderation path("moderate", EventModerateView.as_view(), name="moderate"), path( @@ -434,33 +462,7 @@ urlpatterns = [ MessageDeleteView.as_view(), name="delete_message", ), - path("rimports/", recurrent_imports, name="recurrent_imports"), - path("rimports/run", run_all_rimports, name="run_all_rimports"), - path("rimports/fb/run", run_all_fb_rimports, name="run_all_fb_rimports"), - path( - "rimports/status/", - recurrent_imports, - name="recurrent_imports_status", - ), - path( - "rimports/status//run", - run_all_rimports, - name="run_all_rimports_status", - ), - path("rimports/add", RecurrentImportCreateView.as_view(), name="add_rimport"), - path("rimports//view", view_rimport, name="view_rimport"), path("rimports//stats", statistics, name="stats_rimport"), - path( - "rimports//edit", - RecurrentImportUpdateView.as_view(), - name="edit_rimport", - ), - path( - "rimports//delete", - RecurrentImportDeleteView.as_view(), - name="delete_rimport", - ), - path("rimports//run", run_rimport, name="run_rimport"), path("duplicates/", duplicates, name="duplicates"), path( "duplicates/", diff --git a/src/agenda_culturel/views/__init__.py b/src/agenda_culturel/views/__init__.py index 2911fa1..507c829 100644 --- a/src/agenda_culturel/views/__init__.py +++ b/src/agenda_culturel/views/__init__.py @@ -3,6 +3,7 @@ from .categorisation_rules_view import * from .errors import * from .general_pages_views import * from .import_batch_views import * +from .import_recurrent_views import * from .moderation_views import * from .organisations_views import * from .places_views import * diff --git a/src/agenda_culturel/views/import_recurrent_views.py b/src/agenda_culturel/views/import_recurrent_views.py new file mode 100644 index 0000000..656d585 --- /dev/null +++ b/src/agenda_culturel/views/import_recurrent_views.py @@ -0,0 +1,202 @@ +from django.contrib import messages +from django.contrib.auth.decorators import login_required, permission_required +from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +from django.contrib.messages.views import SuccessMessageMixin +from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage +from django.db.models import OuterRef, Subquery +from django.http import HttpResponseRedirect +from django.shortcuts import render, get_object_or_404 +from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ +from django.views.generic import CreateView, UpdateView, DeleteView + +from . import PaginatorFilter +from ..celery import ( + run_all_recurrent_imports, + run_all_recurrent_imports_canceled, + run_all_recurrent_imports_failed, + run_recurrent_import, +) +from ..filters import RecurrentImportFilter +from ..forms import RecurrentImportForm +from ..models import BatchImportation, RecurrentImport + + +@login_required(login_url="/accounts/login/") +@permission_required("agenda_culturel.view_recurrentimport") +def recurrent_imports(request, status=None): + newest = BatchImportation.objects.filter(recurrentImport=OuterRef("pk")).order_by( + "-created_date" + ) + + qs = ( + RecurrentImport.objects.all() + .annotate(last_run_status=Subquery(newest.values("status")[:1])) + .order_by("-pk") + ) + + nb_failed = qs.filter(last_run_status=BatchImportation.STATUS.FAILED).count() + nb_canceled = qs.filter(last_run_status=BatchImportation.STATUS.CANCELED).count() + nb_running = qs.filter(last_run_status=BatchImportation.STATUS.RUNNING).count() + nb_all = qs.count() + + if status is not None: + qs = qs.filter(last_run_status=status) + + filter = RecurrentImportFilter(request.GET, queryset=qs) + + paginator = PaginatorFilter(filter, 20, 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/rimports.html", + { + "paginator_filter": response, + "filter": filter, + "nb_all": nb_all, + "nb_failed": nb_failed, + "nb_canceled": nb_canceled, + "nb_running": nb_running, + "status": status, + }, + ) + + +class RecurrentImportCreateView( + LoginRequiredMixin, PermissionRequiredMixin, CreateView +): + model = RecurrentImport + permission_required = "agenda_culturel.add_recurrentimport" + success_url = reverse_lazy("recurrent_imports") + form_class = RecurrentImportForm + + +class RecurrentImportUpdateView( + SuccessMessageMixin, + PermissionRequiredMixin, + LoginRequiredMixin, + UpdateView, +): + model = RecurrentImport + permission_required = "agenda_culturel.change_recurrentimport" + form_class = RecurrentImportForm + success_message = _("The recurrent import has been successfully modified.") + + +class RecurrentImportDeleteView( + SuccessMessageMixin, + PermissionRequiredMixin, + LoginRequiredMixin, + DeleteView, +): + model = RecurrentImport + permission_required = "agenda_culturel.delete_recurrentimport" + success_url = reverse_lazy("recurrent_imports") + success_message = _("The recurrent import has been successfully deleted.") + + +@login_required(login_url="/accounts/login/") +@permission_required( + [ + "agenda_culturel.view_recurrentimport", + "agenda_culturel.view_batchimportation", + ] +) +def view_rimport(request, pk): + obj = get_object_or_404(RecurrentImport, pk=pk) + paginator = Paginator( + BatchImportation.objects.filter(recurrentImport=pk).order_by("-created_date"), + 10, + ) + 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/page-rimport.html", + {"paginator_filter": response, "object": obj}, + ) + + +@login_required(login_url="/accounts/login/") +@permission_required( + [ + "agenda_culturel.view_recurrentimport", + "agenda_culturel.run_recurrentimport", + ] +) +def run_rimport(request, pk): + rimport = get_object_or_404(RecurrentImport, pk=pk) + + if request.method == "POST": + # run recurrent import + run_recurrent_import.delay(pk) + + messages.success(request, _("The import has been launched.")) + return HttpResponseRedirect(reverse_lazy("view_rimport", args=[pk])) + else: + return render( + request, + "agenda_culturel/run_rimport_confirm.html", + {"object": rimport}, + ) + + +@login_required(login_url="/accounts/login/") +@permission_required( + [ + "agenda_culturel.view_recurrentimport", + "agenda_culturel.run_recurrentimport", + ] +) +def run_all_rimports(request, status=None): + if request.method == "POST": + # run recurrent import + if status == BatchImportation.STATUS.FAILED: + run_all_recurrent_imports_failed.delay() + elif status == BatchImportation.STATUS.CANCELED: + run_all_recurrent_imports_canceled.delay() + else: + run_all_recurrent_imports.delay() + + messages.success(request, _("Imports has been launched.")) + return HttpResponseRedirect(reverse_lazy("recurrent_imports")) + else: + if status == BatchImportation.STATUS.FAILED: + return render(request, "agenda_culturel/run_failed_rimports_confirm.html") + elif status == BatchImportation.STATUS.CANCELED: + return render(request, "agenda_culturel/run_canceled_rimports_confirm.html") + else: + return render(request, "agenda_culturel/run_all_rimports_confirm.html") + + +@login_required(login_url="/accounts/login/") +@permission_required( + [ + "agenda_culturel.view_recurrentimport", + "agenda_culturel.run_recurrentimport", + ] +) +def run_all_fb_rimports(request, status=None): + if request.method == "POST": + run_all_recurrent_imports.delay(True) + + messages.success(request, _("Facebook imports has been launched.")) + return HttpResponseRedirect(reverse_lazy("recurrent_imports")) + else: + return render(request, "agenda_culturel/run_all_fb_rimports_confirm.html") diff --git a/src/agenda_culturel/views/oldviews.py b/src/agenda_culturel/views/oldviews.py index c26225c..2890b9c 100644 --- a/src/agenda_culturel/views/oldviews.py +++ b/src/agenda_culturel/views/oldviews.py @@ -46,17 +46,12 @@ from ..calendar import CalendarDay, CalendarList, CalendarMonth, CalendarWeek from ..celery import ( import_events_from_url, import_events_from_urls, - run_all_recurrent_imports, - run_all_recurrent_imports_canceled, - run_all_recurrent_imports_failed, - run_recurrent_import, ) from ..filters import ( DuplicatedEventsFilter, EventFilter, EventFilterAdmin, MessagesFilterAdmin, - RecurrentImportFilter, SearchEventFilter, SimpleSearchEventFilter, ) @@ -67,7 +62,6 @@ from ..forms import ( MergeDuplicates, MessageEventForm, MessageForm, - RecurrentImportForm, SelectEventInList, SimpleContactForm, URLSubmissionFormSet, @@ -1299,191 +1293,6 @@ def event_search_full(request): return event_search(request, True) -######################### -## recurrent importations -######################### - - -@login_required(login_url="/accounts/login/") -@permission_required("agenda_culturel.view_recurrentimport") -def recurrent_imports(request, status=None): - newest = BatchImportation.objects.filter(recurrentImport=OuterRef("pk")).order_by( - "-created_date" - ) - - qs = ( - RecurrentImport.objects.all() - .annotate(last_run_status=Subquery(newest.values("status")[:1])) - .order_by("-pk") - ) - - nb_failed = qs.filter(last_run_status=BatchImportation.STATUS.FAILED).count() - nb_canceled = qs.filter(last_run_status=BatchImportation.STATUS.CANCELED).count() - nb_running = qs.filter(last_run_status=BatchImportation.STATUS.RUNNING).count() - nb_all = qs.count() - - if status is not None: - qs = qs.filter(last_run_status=status) - - filter = RecurrentImportFilter(request.GET, queryset=qs) - - paginator = PaginatorFilter(filter, 20, 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/rimports.html", - { - "paginator_filter": response, - "filter": filter, - "nb_all": nb_all, - "nb_failed": nb_failed, - "nb_canceled": nb_canceled, - "nb_running": nb_running, - "status": status, - }, - ) - - -class RecurrentImportCreateView( - LoginRequiredMixin, PermissionRequiredMixin, CreateView -): - model = RecurrentImport - permission_required = "agenda_culturel.add_recurrentimport" - success_url = reverse_lazy("recurrent_imports") - form_class = RecurrentImportForm - - -class RecurrentImportUpdateView( - SuccessMessageMixin, - PermissionRequiredMixin, - LoginRequiredMixin, - UpdateView, -): - model = RecurrentImport - permission_required = "agenda_culturel.change_recurrentimport" - form_class = RecurrentImportForm - success_message = _("The recurrent import has been successfully modified.") - - -class RecurrentImportDeleteView( - SuccessMessageMixin, - PermissionRequiredMixin, - LoginRequiredMixin, - DeleteView, -): - model = RecurrentImport - permission_required = "agenda_culturel.delete_recurrentimport" - success_url = reverse_lazy("recurrent_imports") - success_message = _("The recurrent import has been successfully deleted.") - - -@login_required(login_url="/accounts/login/") -@permission_required( - [ - "agenda_culturel.view_recurrentimport", - "agenda_culturel.view_batchimportation", - ] -) -def view_rimport(request, pk): - obj = get_object_or_404(RecurrentImport, pk=pk) - paginator = Paginator( - BatchImportation.objects.filter(recurrentImport=pk).order_by("-created_date"), - 10, - ) - 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/page-rimport.html", - {"paginator_filter": response, "object": obj}, - ) - - -@login_required(login_url="/accounts/login/") -@permission_required( - [ - "agenda_culturel.view_recurrentimport", - "agenda_culturel.run_recurrentimport", - ] -) -def run_rimport(request, pk): - rimport = get_object_or_404(RecurrentImport, pk=pk) - - if request.method == "POST": - # run recurrent import - run_recurrent_import.delay(pk) - - messages.success(request, _("The import has been launched.")) - return HttpResponseRedirect(reverse_lazy("view_rimport", args=[pk])) - else: - return render( - request, - "agenda_culturel/run_rimport_confirm.html", - {"object": rimport}, - ) - - -@login_required(login_url="/accounts/login/") -@permission_required( - [ - "agenda_culturel.view_recurrentimport", - "agenda_culturel.run_recurrentimport", - ] -) -def run_all_rimports(request, status=None): - if request.method == "POST": - # run recurrent import - if status == BatchImportation.STATUS.FAILED: - run_all_recurrent_imports_failed.delay() - elif status == BatchImportation.STATUS.CANCELED: - run_all_recurrent_imports_canceled.delay() - else: - run_all_recurrent_imports.delay() - - messages.success(request, _("Imports has been launched.")) - return HttpResponseRedirect(reverse_lazy("recurrent_imports")) - else: - if status == BatchImportation.STATUS.FAILED: - return render(request, "agenda_culturel/run_failed_rimports_confirm.html") - elif status == BatchImportation.STATUS.CANCELED: - return render(request, "agenda_culturel/run_canceled_rimports_confirm.html") - else: - return render(request, "agenda_culturel/run_all_rimports_confirm.html") - - -@login_required(login_url="/accounts/login/") -@permission_required( - [ - "agenda_culturel.view_recurrentimport", - "agenda_culturel.run_recurrentimport", - ] -) -def run_all_fb_rimports(request, status=None): - if request.method == "POST": - run_all_recurrent_imports.delay(True) - - messages.success(request, _("Facebook imports has been launched.")) - return HttpResponseRedirect(reverse_lazy("recurrent_imports")) - else: - return render(request, "agenda_culturel/run_all_fb_rimports_confirm.html") - - ######################### ## duplicated events #########################