diff --git a/opentech/apply/funds/tables.py b/opentech/apply/funds/tables.py index c9e2cc7246700da837755d34a6fb7e645049e5fe..3d8b2dcc52a65905e544ccc702be8ac99c34f271 100644 --- a/opentech/apply/funds/tables.py +++ b/opentech/apply/funds/tables.py @@ -170,6 +170,9 @@ class RoundsTable(tables.Table): def render_progress(self, record): return f'{record.progress}%' + def _order_by(self, field, desc): + return getattr(F(f'{field}'), 'desc' if desc else 'asc')(nulls_last=True) + def _order(self, qs, desc, field, round=True, lab=True): annotated_name = field.split('__')[0] fields = [ @@ -186,12 +189,11 @@ class RoundsTable(tables.Table): **{annotated_name: lookup} ) - new_order = getattr(F(f'{annotated_name}'), 'desc' if desc else 'asc')(nulls_last=True) - qs = qs.order_by(new_order) + qs = qs.order_by(self._order_by(annotated_name, desc)) return qs, True def order_lead(self, qs, desc): - return self._order(qs, desc, 'lead__full_name') + return qs.order_by(self._order_by('lead', desc)), True def order_start_date(self, qs, desc): return self._order(qs, desc, 'start_date', lab=False) @@ -205,12 +207,10 @@ class RoundsTable(tables.Table): parent_path=Left(F('path'), Length('path') - ApplicationBase.steplen, output_field=CharField()), fund=Subquery(funds.values('title')[:1]), ) - new_order = getattr(F('fund'), 'desc' if desc else 'asc')(nulls_last=True) - return qs.order_by(new_order), True + return qs.order_by(self._order_by('fund', desc)), True def order_progress(self, qs, desc): - new_order = getattr(F('progress'), 'desc' if desc else 'asc')(nulls_last=True) - return qs.order_by(new_order), True + return qs.order_by(self._order_by('progress', desc)), True # TODO remove in django 2.1 where this is fixed @@ -234,3 +234,23 @@ class Left(Func): def get_substr(self): return Substr(self.source_expressions[0], Value(1), self.source_expressions[1]) + + +class ActiveRoundFilter(Select2MultipleChoiceFilter): + def __init__(self, *args, **kwargs): + super().__init__(self, *args, choices=[('active', 'Active'), ('inactive', 'Inactive')], **kwargs) + + def filter(self, qs, value): + if value is None or len(value) > 1: + return qs + + value = value[0] + if value == 'active': + return qs.filter(Q(progress__lt=100) | Q(progress__isnull=True)) + else: + return qs.filter(progress=100) + + +class RoundsFilter(filters.FilterSet): + lead = Select2ModelMultipleChoiceFilter(queryset=get_round_leads, label='Leads') + active = ActiveRoundFilter(label='Active') diff --git a/opentech/apply/funds/views.py b/opentech/apply/funds/views.py index 294bda17a63544bec91c459084e347d0b325d34a..1851db7f9c3675e5f6ef94fa0c19d29069d194aa 100644 --- a/opentech/apply/funds/views.py +++ b/opentech/apply/funds/views.py @@ -34,7 +34,12 @@ from .differ import compare from .forms import ProgressSubmissionForm, ScreeningSubmissionForm, UpdateReviewersForm, UpdateSubmissionLeadForm from .models import ApplicationSubmission, ApplicationRevision, RoundBase, LabBase from .models.utils import SubmittableStreamForm -from .tables import AdminSubmissionsTable, RoundsTable, SubmissionFilterAndSearch +from .tables import ( + AdminSubmissionsTable, + RoundsTable, + RoundsFilter, + SubmissionFilterAndSearch, +) from .workflow import STAGE_CHANGE_ACTIONS @@ -468,9 +473,10 @@ class RevisionCompareView(DetailView): @method_decorator(staff_required, name='dispatch') -class RoundListView(SingleTableMixin, ListView): +class RoundListView(SingleTableMixin, FilterView): template_name = 'funds/rounds.html' table_class = RoundsTable + filterset_class = RoundsFilter def get_queryset(self): submissions = ApplicationSubmission.objects.filter(Q(round=OuterRef('pk')) | Q(page=OuterRef('pk'))).current() @@ -491,6 +497,10 @@ class RoundListView(SingleTableMixin, ListView): ), 0, ), + lead=Coalesce( + F('roundbase__lead__full_name'), + F('labbase__lead__full_name'), + ) ).annotate( progress=Case( When(total_submissions=0, then=None),