Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion isic/core/templates/core/collection_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@
{% block content %}
<header class="border-b border-gray-100 flex items-center justify-between py-2 pb-4">
<div class="flex-col">
<div class="heading-1">Collections ({{ page.paginator.count|intcomma }})</div>
{% if cohort %}
<div class="heading-1">Collections derived from {{ cohort.name }} ({{ page.paginator.count|intcomma }})</div>
<a href="{% querystring cohort=None page=None %}" class="text-sm text-gray-500 hover:text-gray-700">Show all collections</a>
{% else %}
<div class="heading-1">Collections ({{ page.paginator.count|intcomma }})</div>
{% endif %}
</div>
{% if request.user.is_authenticated %}
<a href="{% url 'core/collection-create' %}" class="btn btn-primary btn-sm">
Expand Down
51 changes: 51 additions & 0 deletions isic/core/tests/test_collection_list_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,54 @@ def test_collection_list_mobile(
expect(
page.locator("tbody tr").filter(has_text=collection_private.name).get_by_text("Private")
).to_be_visible()


@pytest.mark.playwright
def test_collection_list_cohort_filter(
staff_authenticated_page,
authenticated_page,
cohort_factory,
accession_factory,
collection_factory,
image_factory,
):
page = staff_authenticated_page

cohort = cohort_factory()
derived_collection = collection_factory(public=True, pinned=False, locked=False)
unrelated_collection = collection_factory(public=True, pinned=False, locked=False)

for _ in range(2):
add_images_to_collection(
collection=derived_collection,
image=image_factory(public=True, accession=accession_factory(cohort=cohort)),
)

add_images_to_collection(collection=unrelated_collection, image=image_factory(public=True))

_refresh_collection_counts()

page.goto(reverse("ingest/cohort-detail", args=[cohort.pk]))
page.get_by_role("button", name="Actions").click()
page.get_by_role("link", name="View Derived Collections").click()
page.wait_for_url("**/collections/?*")

expect(page.get_by_text(f"Collections derived from {cohort.name}")).to_be_visible()
expect(page.get_by_role("link", name=derived_collection.name)).to_be_visible()
expect(page.get_by_role("link", name=unrelated_collection.name)).not_to_be_visible()

# Clearing the filter brings back the collections that aren't derived from the cohort
page.get_by_role("link", name="Show all collections").click()
page.wait_for_load_state("networkidle")
expect(page.get_by_text(f"Collections derived from {cohort.name}")).not_to_be_visible()
expect(page.get_by_role("link", name=unrelated_collection.name)).to_be_visible()

# Non-staff users can't narrow by cohort, so the parameter is ignored
non_staff_page = authenticated_page
non_staff_page.goto(
reverse("core/collection-list", query={"cohort": cohort.pk, "magic_filter": "all"})
)
expect(
non_staff_page.get_by_text(f"Collections derived from {cohort.name}")
).not_to_be_visible()
expect(non_staff_page.get_by_role("link", name=unrelated_collection.name)).to_be_visible()
13 changes: 12 additions & 1 deletion isic/core/views/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from isic.core.services.collection import create_collection, update_collection
from isic.core.utils.csv import EscapingDictWriter
from isic.core.utils.http import Echo
from isic.ingest.models import Contributor
from isic.ingest.models import Cohort, Contributor


@login_required
Expand Down Expand Up @@ -194,6 +194,16 @@ def collection_list(request: HttpRequest) -> HttpResponse:
pinned_filter = request.GET.get("pinned_filter", "all")
exclude_empty = request.GET.get("exclude_empty", "1") == "1"

cohort_filter = request.GET.get("cohort", "")
cohort = None
if request.user.is_staff and cohort_filter.isdigit():
cohort = get_object_or_404(Cohort, pk=cohort_filter)
collections = collections.filter(
pk__in=Collection.images.through.objects.filter(image__accession__cohort=cohort).values(
"collection_id"
)
)

if magic_filter == "only":
collections = collections.magic()
elif magic_filter == "exclude":
Expand Down Expand Up @@ -243,5 +253,6 @@ def collection_list(request: HttpRequest) -> HttpResponse:
"magic_filter": magic_filter,
"pinned_filter": pinned_filter,
"exclude_empty": exclude_empty,
"cohort": cohort,
},
)
6 changes: 6 additions & 0 deletions isic/ingest/models/cohort.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ def __str__(self) -> str:
def get_absolute_url(self):
return reverse("ingest/cohort-detail", args=[self.id])

@property
def derived_collections_url(self) -> str:
# magic_filter is overridden because the collection list excludes magic collections by
# default, which would hide the cohort's own collection.
return reverse("core/collection-list", query={"cohort": self.id, "magic_filter": "all"})

@property
def num_lesions(self):
return self.accessions.exclude(lesion=None).values("lesion__id").distinct().count()
Expand Down
4 changes: 4 additions & 0 deletions isic/ingest/templates/ingest/partials/cohort_actions.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@
<li>
<a href="{% url 'upload/cohort-publish' cohort.pk %}">Publish Cohort</a>
</li>
<hr class="my-1 border-base-content/10">
<li>
<a href="{{ cohort.derived_collections_url }}">View Derived Collections</a>
</li>
</ul>