From 891b71d6c12eacb7712e297ee9eca94e700f51c5 Mon Sep 17 00:00:00 2001 From: Lucas Brandstaetter <lucas@brandstaetter.tech> Date: Thu, 28 Nov 2024 02:01:10 +0100 Subject: [PATCH] Update assembly team views - Use FilteredListView and AlphabeticalPaginatorView for assembly team views - Add multi-tag filtering to assembly list view - Migrate old filters to new system --- src/backoffice/views/assemblyteam.py | 58 ++++++++++++++-------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/backoffice/views/assemblyteam.py b/src/backoffice/views/assemblyteam.py index 84bcd9020..b679ddb7c 100644 --- a/src/backoffice/views/assemblyteam.py +++ b/src/backoffice/views/assemblyteam.py @@ -14,12 +14,13 @@ from django.urls import reverse from django.utils.html import format_html from django.utils.translation import gettext from django.utils.translation import gettext_lazy as _ -from django.views.generic import DetailView, ListView, View +from django.views.generic import DetailView, View from core.models import ActivityLogChange, ActivityLogEntry, Room from core.models.assemblies import Assembly, AssemblyMember from core.models.conference import ConferenceExportCache from core.models.users import UserCommunicationChannel +from core.views.list_views import AlphabeticalPaginatorView, FilteredListView from backoffice.templatetags.c3assemblies import get_language_item @@ -38,13 +39,13 @@ class AssemblyTeamMixin(ConferenceLoginRequiredMixin): status_field = 'state_assembly' MODES = { - 'all': (Q(), _('nav_assemblies_all')), - 'accepted': (Q(state_assembly__in=Assembly.PUBLIC_STATES), _('nav_assemblies_accepted')), - 'pending': (Q(state_assembly__in=[Assembly.State.REGISTERED]), _('nav_assemblies_pending')), - 'planned': (Q(state_assembly__in=[Assembly.State.PLANNED]), _('nav_assemblies_planned')), - 'rejected': (Q(state_assembly__in=[Assembly.State.REJECTED]), _('nav_assemblies_rejected')), - 'hidden': (Q(state_assembly__in=[Assembly.State.HIDDEN]), _('nav_assemblies_hidden')), - 'not_selected': (Q(state_assembly__in=[Assembly.State.NONE]), _('nav_assemblies_not_selected')), + 'all': (('QMode', Q()), _('nav_assemblies_all')), + 'accepted': (('QMode', Q(state_assembly__in=Assembly.PUBLIC_STATES)), _('nav_assemblies_accepted')), + 'pending': (('QMode', Q(state_assembly__in=[Assembly.State.REGISTERED])), _('nav_assemblies_pending')), + 'planned': (('QMode', Q(state_assembly__in=[Assembly.State.PLANNED])), _('nav_assemblies_planned')), + 'rejected': (('QMode', Q(state_assembly__in=[Assembly.State.REJECTED])), _('nav_assemblies_rejected')), + 'hidden': (('QMode', Q(state_assembly__in=[Assembly.State.HIDDEN])), _('nav_assemblies_hidden')), + 'not_selected': (('QMode', Q(state_assembly__in=[Assembly.State.NONE])), _('nav_assemblies_not_selected')), } def get_context_data(self, **kwargs): @@ -75,7 +76,7 @@ class AssemblyTeamMixin(ConferenceLoginRequiredMixin): { 'mode': m, 'caption': t, - 'count': self.conference.assemblies.filter(q).count(), + 'count': self.conference.assemblies.filter(q[1]).count(), 'link': reverse(self.base_view_name) + '?mode=' + m, } ) @@ -116,32 +117,39 @@ class AssemblyTeamMixin(ConferenceLoginRequiredMixin): return context -class AssembliesListMixin(AssemblyTeamMixin): +class AssembliesListMixin(AssemblyTeamMixin, FilteredListView): default_assemblies_mode = 'all' + filters = { + 'tag': ('tags__tag__slug', 'list'), + } def get_queryset(self, **kwargs): # get the mode mode = (self.request.POST if self.request.method == 'POST' else self.request.GET).get('mode', self.default_assemblies_mode) + query_filters = {} - qs = Assembly.objects.associated_with_user(conference=self.conference, user=self.request.user, staff_can_see=True) if mode == 'not_selected': pass elif self.active_page == 'assemblies': - qs = qs.exclude(state_assembly=Assembly.State.NONE) + query_filters['!state_assembly'] = Assembly.State.NONE elif self.active_page == 'channels': - qs = qs.exclude(state_channel=Assembly.State.NONE) + query_filters['!state_channel'] = Assembly.State.NONE else: logging.warning('AssembliesListMixin: unexpected active_page="%s"', self.active_page) - qs = Assembly.objects.none() + return Assembly.objects.none() if mode in self.MODES: - qs = qs.filter(self.MODES[mode][0]) + query_filters[self.MODES[mode][0][0]] = self.MODES[mode][0][1] else: messages.warning(self.request, f'unknown mode "{mode}", using "all"') mode = 'all' + query_filters[self.MODES[mode][0][0]] = self.MODES[mode][0][1] self.assemblies_mode = mode - # done + qs = super().get_queryset( + Assembly.objects.associated_with_user(conference=self.conference, user=self.request.user, staff_can_see=True), query_filters=query_filters + ) + return qs @@ -200,13 +208,13 @@ class AssemblyView(SingleAssemblyTeamMixin, DetailView): return redirect('backoffice:assemblyteam-detail', self.assembly.id) -class AssembliesView(AssembliesListMixin, ListView): +class AssembliesView(AssembliesListMixin, AlphabeticalPaginatorView): template_name = 'backoffice/assembly_list.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['filter_tag'] = self.selected_tag + # context['filter_tag'] = self.selected_tag context['mode'] = self.assemblies_mode context['mode_display'] = self.MODES[self.assemblies_mode][1] @@ -222,19 +230,8 @@ class AssembliesView(AssembliesListMixin, ListView): return context - def get_queryset(self, *args, **kwargs): - qs = super().get_queryset(*args, **kwargs) - - # tag filtering - self.selected_tag = (self.request.POST if self.request.method == 'POST' else self.request.GET).get('tag') - if self.selected_tag is not None: - qs = qs.filter(tags__tag__slug=self.selected_tag, tags__tag__is_public=True) - - # return the assembled QuerySet - return qs - -class AssembliesListsView(AssembliesListMixin, View): +class AssembliesListsView(AssembliesListMixin): DEFAULT_DELIMITER_CHAR = ';' DEFAULT_QUOTE_CHAR = '"' DELIMITER_CHARS = ',;|\t=*/' @@ -364,6 +361,7 @@ class AssembliesListsView(AssembliesListMixin, View): def get(self, *args, **kwargs): qs, variant, variant_name, variant_fields = self.prepare(*args, **kwargs) + self.object_list = qs if qs is None: assert isinstance(variant, HttpResponse) return variant -- GitLab