Skip to content

Commit

Permalink
Merge pull request #1006 from betagouv/feat/project-changelist-embarg…
Browse files Browse the repository at this point in the history
…o-filters

feat(project-changelist): add embargo filters & multi-appearance
  • Loading branch information
wiwski authored Jul 18, 2024
2 parents 121c1cb + 6742356 commit e2b8fa0
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 33 deletions.
34 changes: 8 additions & 26 deletions lab/projects/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from lab.models import Participation
from lab.permissions import is_lab_admin, is_project_leader

from . import admin_filters
from .forms import (
BaseParticipationForm,
BaseProjectForm,
Expand All @@ -27,36 +28,14 @@
from .models import BeamTimeRequest, Project


class ProjectStatusListFilter(admin.SimpleListFilter):
title = _("status")

parameter_name = "status"
template = "admin/lab/project/filter.html"

def lookups(self, request, model_admin):
return [
(enum_member.name, enum_member.value[1])
for enum_member in list(Project.Status)
if enum_member != Project.Status.TO_SCHEDULE
# exclude TO_SCHEDULE from filter as it is displayed in a separate table
]

def queryset(self, request, queryset):
if self.value():
return queryset.filter_by_status(Project.Status[self.value()])
return queryset


class ProjectChangeList(ChangeList):
def get_queryset(self, request: HttpRequest, exclude_parameters=None):
qs = super().get_queryset(request, exclude_parameters)
if request.method == "POST" and request.POST.get("action") == "delete_selected":
return qs # use more general queryset for delete action
to_schedule_ids = qs.only_to_schedule().values_list( # type: ignore[attr-defined] # pylint:disable=line-too-long
"id", flat=True
)
return (
qs.exclude(id__in=to_schedule_ids) # type: ignore[attr-defined]
# qs with projects having at least one scheduled runs
qs.filter(runs__start_date__isnull=False) # type: ignore[attr-defined]
.distinct()
.annotate_first_run_date()
.annotate(number_of_runs=Count("runs"))
Expand Down Expand Up @@ -238,7 +217,10 @@ class ProjectAdmin(LabPermissionMixin, ProjectDisplayMixin, ModelAdmin):

search_fields = ("name",)

list_filter = [ProjectStatusListFilter]
list_filter = [
admin_filters.ProjectStatusListFilter,
admin_filters.ProjectRunActiveEmbargoFilter,
]
list_per_page = 20

class Media:
Expand Down Expand Up @@ -401,7 +383,7 @@ def changelist_view(
# add scheduled projects on basic page (no search or pagination)
to_schedule_projects = (
self.get_queryset(request)
.only_to_schedule()
.has_to_schedule_runs()
.annotate(
first_run_date=Value(
None,
Expand Down
49 changes: 49 additions & 0 deletions lab/projects/admin_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from django.contrib import admin
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from lab.runs.models import Run

from .models import Project


class ProjectStatusListFilter(admin.SimpleListFilter):
title = _("status")

parameter_name = "status"
template = "admin/lab/project/filter.html"

def lookups(self, request, model_admin):
return [
(enum_member.name, enum_member.value[1])
for enum_member in list(Project.Status)
if enum_member != Project.Status.TO_SCHEDULE
# exclude TO_SCHEDULE from filter as it is displayed in a separate table
]

def queryset(self, request, queryset):
if self.value():
return queryset.filter_by_status(Project.Status[self.value()])
return queryset


class ProjectRunActiveEmbargoFilter(admin.SimpleListFilter):
title = _("embargo status")

parameter_name = "embargo"
template = "admin/lab/project/filter.html"

def lookups(self, request, model_admin):
return [("active", _("Active")), ("over", _("Over")), ("none", _("Not set"))]

def queryset(self, request, queryset):
if self.value():
if self.value() == "active":
runs = Run.objects.filter(embargo_date__gte=timezone.now())
return queryset.filter(runs__in=runs)
if self.value() == "over":
runs = Run.objects.filter(embargo_date__lt=timezone.now())
return queryset.filter(runs__in=runs)
if self.value() == "none":
return queryset.filter(runs__embargo_date__isnull=True)
return queryset
3 changes: 3 additions & 0 deletions lab/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@


class ProjectQuerySet(models.QuerySet):
def has_to_schedule_runs(self):
return self.filter(runs__start_date__isnull=True)

def only_to_schedule(self):
to_schedule_runs = Run.objects.filter(start_date__isnull=False)
return self.exclude(runs__in=to_schedule_runs)
Expand Down
23 changes: 23 additions & 0 deletions lab/projects/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,26 @@ def test_no_to_schedule_projects_in_ctx_when_paginated_results(self):
assert (
len(cl_view.context_data["extra_qs"]) == 0
), f"Test failed for query {url_query_hiding_qs}"

def test_scheduled_project_in_to_schedule_qs_when_any_to_schedule_run(self):
project_both_scheduled_and_not = ProjectFactory()
RunFactory(project=project_both_scheduled_and_not, start_date=timezone.now())
RunFactory(project=project_both_scheduled_and_not, start_date=None)

project_scheduled = ProjectFactory()
RunFactory(project=project_scheduled, start_date=timezone.now())

project_not_scheduled = ProjectFactory()
RunFactory(project=project_not_scheduled, start_date=None)

cl_view: TemplateResponse = self.admin.changelist_view(self.request)

to_schedule_qs = cl_view.context_data["extra_qs"][0]["qs"]
scheduled_qs = cl_view.context_data["cl"].queryset

assert to_schedule_qs.count() == 2
assert project_both_scheduled_and_not in to_schedule_qs.all()
assert project_not_scheduled in to_schedule_qs.all()
assert scheduled_qs.count() == 2
assert project_both_scheduled_and_not in scheduled_qs.all()
assert project_scheduled in scheduled_qs.all()
6 changes: 4 additions & 2 deletions lab/templates/admin/lab/run/change_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,20 @@
<div>
<h1>{{ original.label }}</h1>

{% if original.start_date %}
{% if original.start_date or original.embargo_date %}
<div class="run-dates">
{% if original.start_date %}
<span class="fr-icon fr-icon-calendar-line" aria-hidden="true"></span>
<p class="fr-ml-2w">
<span class="fr-text--sm">{% translate "Start" %}</span><br>{{ original.start_date|date:"SHORT_DATE_FORMAT" }} {{ original.start_date|time:"H:i" }}
</p>
{% endif %}
{% if original.end_date %}
<p class="fr-ml-2w"><span class="fr-text--sm">{% translate "End" %}</span><br>
{{ original.end_date|date:"SHORT_DATE_FORMAT" }} {{ original.end_date|time:"H:i" }}{% endif %}
</p>
{% if request.user.is_lab_admin %}
<span class="fr-icon fr-icon-lock-line fr-ml-3w" aria-hidden="true"></span>
<span class="fr-icon fr-icon-lock-line{% if original.start_date %} fr-ml-3w{% endif %}" aria-hidden="true"></span>
<p class="fr-ml-2w"><span class="fr-text--sm">{% translate "Embargo" %}</span><br>
{% if original.embargo_date %}{{ original.embargo_date|date:"SHORT_DATE_FORMAT" }}{% else %}{% translate "No embargo date" %}{% endif %}</p>
{% endif %}
Expand Down
7 changes: 6 additions & 1 deletion lab/templates/admin/lab/run/run_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h4 class="fr-card__title flex-container">
</h4>
<div class="fr-card__desc">

<div class="flex-container fr-text--sm">
<div class="flex-container fr-text--sm fr-mb-1w">
<p class="fr-text--sm fr-mb-0">
<span class="fr-text--xs">{% translate "Start" %}</span>
<br>{% if run.start_date %}{{ run.start_date|date:"SHORT_DATE_FORMAT" }} {{ run.start_date|time:"H:i" }}{% else %}-{% endif %}
Expand All @@ -33,6 +33,11 @@ <h4 class="fr-card__title flex-container">
</p>
</div>

<p class="fr-text--sm">
<span class="fr-text--xs">{% translate "Embargo date" %}</span>
<br>{% if run.embargo_date %}{{ run.embargo_date|date:"SHORT_DATE_FORMAT" }}{% else %}-{% endif %}
</p>

<div class="fr-text--xs mb-0">{% translate "Experimental conditions" %}</div>
<div class="flex-container fr-text--sm fr-mb-1v">
<p>
Expand Down
Binary file modified locale/fr/LC_MESSAGES/django.mo
Binary file not shown.
20 changes: 16 additions & 4 deletions locale/fr/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-02 12:14+0200\n"
"POT-Creation-Date: 2024-07-18 16:55+0200\n"
"PO-Revision-Date: 2021-09-09 19:04+0200\n"
"Language: \n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -468,9 +468,6 @@ msgstr "nom"
msgid "country"
msgstr "pays"

msgid "status"
msgstr "statut"

msgid "Project member"
msgstr "Membre du projet"

Expand Down Expand Up @@ -514,6 +511,21 @@ msgstr "Projets"
msgid "To schedule"
msgstr "A planifier"

msgid "status"
msgstr "statut"

msgid "embargo status"
msgstr "statut de l'embargo"

msgid "Active"
msgstr "Actif"

msgid "Over"
msgstr "Terminé"

msgid "Not set"
msgstr "Non défini"

msgid "I have read and accepted the general conditions of Euphrosyne."
msgstr "J'ai lu et accepté les conditions générales d'Euphrosyne."

Expand Down

0 comments on commit e2b8fa0

Please sign in to comment.