Skip to content

Commit

Permalink
feat(source list): add country filter to source list page
Browse files Browse the repository at this point in the history
- view: add 'countries' context and add country filter to query object filter
- html: add countryFilter dropdown to 'Browse Sources' page
- js: ensure countryFilter persists across multiple GET requests
- test: add tests for country filter
  • Loading branch information
lucasmarchd01 committed Aug 19, 2024
1 parent 18b8088 commit 0ec23bb
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 1 deletion.
9 changes: 9 additions & 0 deletions django/cantusdb_project/main_app/templates/source_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ <h3>Browse Sources</h3>
</div>
</div>
<div class="form-row form-row align-items-end">
<div class="form-group m-1 col-lg">
<label for="countryFilter"><small>Country</small></label>
<select id="countryFilter" name="country" class="form-control custom-select custom-select-sm">
<option value="">- Any -</option>
{% for country in countries %}
<option value="{{ country }}">{{ country }}</option>
{% endfor %}
</select>
</div>
<div class="form-group m-1 col-lg">
<label for="provenanceFilter"><small>Provenance (origin/history)</small></label>
<select id="provenanceFilter" name="provenance" class="form-control custom-select custom-select-sm">
Expand Down
42 changes: 41 additions & 1 deletion django/cantusdb_project/main_app/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4424,7 +4424,7 @@ def test_only_published_sources_visible(self):
self.assertNotIn(private_source, sources)

def test_filter_by_segment(self):
"""The source list can be filtered by `segment`, `provenance`, `century`, and `full_source`"""
"""The source list can be filtered by `segment`, `country`, `provenance`, `century`, and `full_source`"""
cantus_segment = make_fake_segment(name="cantus")
clavis_segment = make_fake_segment(name="clavis")
chant_source = make_fake_source(
Expand All @@ -4450,6 +4450,46 @@ def test_filter_by_segment(self):
self.assertIn(seq_source, sources)
self.assertNotIn(chant_source, sources)

def test_filter_by_country(self):
hold_inst_austria = make_fake_institution(country="Austria")
hold_inst_germany = make_fake_institution(country="Germany")
austria_source = make_fake_source(
holding_institution=hold_inst_austria,
published=True,
shelfmark="source from Austria",
)
germany_source = make_fake_source(
holding_institution=hold_inst_germany,
published=True,
shelfmark="source from Germany",
)
no_country_source = make_fake_source(
holding_institution=None,
published=True,
shelfmark="source with no country",
)

# Display sources from Austria only
response = self.client.get(reverse("source-list"), {"country": "Austria"})
sources = response.context["sources"]
self.assertIn(austria_source, sources)
self.assertNotIn(germany_source, sources)
self.assertNotIn(no_country_source, sources)

# Display sources from Germany only
response = self.client.get(reverse("source-list"), {"country": "Germany"})
sources = response.context["sources"]
self.assertIn(germany_source, sources)
self.assertNotIn(austria_source, sources)
self.assertNotIn(no_country_source, sources)

# Display sources with no country filter (all published sources)
response = self.client.get(reverse("source-list"))
sources = response.context["sources"]
self.assertIn(austria_source, sources)
self.assertIn(germany_source, sources)
self.assertIn(no_country_source, sources)

def test_filter_by_provenance(self):
aachen = make_fake_provenance()
albi = make_fake_provenance()
Expand Down
9 changes: 9 additions & 0 deletions django/cantusdb_project/main_app/views/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
Provenance,
Segment,
Source,
Institution,
)
from main_app.permissions import (
user_can_create_sources,
Expand Down Expand Up @@ -218,6 +219,11 @@ class SourceListView(ListView): # type: ignore

def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["countries"] = (
Institution.objects.values_list("country", flat=True)
.distinct()
.order_by("country")
)
context["provenances"] = (
Provenance.objects.all().order_by("name").values("id", "name")
)
Expand All @@ -237,6 +243,9 @@ def get_queryset(self) -> QuerySet[Source]:
else:
q_obj_filter = Q(published=True)

if country_name := self.request.GET.get("country"):
q_obj_filter &= Q(holding_institution__country__icontains=country_name)

if century_id := self.request.GET.get("century"):
century_name = Century.objects.get(id=century_id).name
q_obj_filter &= Q(century__name__icontains=century_name)
Expand Down
4 changes: 4 additions & 0 deletions django/cantusdb_project/static/js/source_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ window.addEventListener("load", function () {
// Make sure the select components keep their values across multiple GET requests
// so the user can "drill down" on what they want
const segmentFilter = document.getElementById("segmentFilter");
const countryFilter = document.getElementById("countryFilter")
const provenanceFilter = document.getElementById("provenanceFilter");
const centuryFilter = document.getElementById("centuryFilter");
const fullSourceFilter = document.getElementById("fullSourceFilter");
Expand All @@ -10,6 +11,9 @@ window.addEventListener("load", function () {
if (urlParams.has("segment")) {
segmentFilter.value = urlParams.get("segment");
}
if (urlParams.has("country")) {
countryFilter.value = urlParams.get("country");
}
if (urlParams.has("provenance")) {
provenanceFilter.value = urlParams.get("provenance");
}
Expand Down

0 comments on commit 0ec23bb

Please sign in to comment.