diff --git a/scoring/filters.py b/scoring/filters.py index f06a895f7..735e831ca 100644 --- a/scoring/filters.py +++ b/scoring/filters.py @@ -63,7 +63,7 @@ class QuestionScoreFilter(django_filters.FilterSet): ) population = django_filters.ChoiceFilter( - field_name="plans_core__population", + field_name="plan_score__population", choices=PlanScore.POPULATION_ALL_FILTER_CHOICES, ) @@ -73,6 +73,15 @@ class QuestionScoreFilter(django_filters.FilterSet): control = django_filters.CharFilter(field_name="plan_score__political_control") + region = django_filters.ChoiceFilter( + field_name="plan_score__council__region", choices=Council.REGION_CHOICES + ) + + county = django_filters.ChoiceFilter( + field_name="plan_score__council__county", + choices=Council.get_county_choices(), + ) + class Meta: model = PlanQuestionScore fields = [] diff --git a/scoring/models.py b/scoring/models.py index 48c1b5d6e..4b345a36b 100644 --- a/scoring/models.py +++ b/scoring/models.py @@ -717,6 +717,19 @@ def get_scores_breakdown(self, year=None, scoring_group=None): return counts + def get_score_breakdown_for_councils(self, council_ids, year): + counts = ( + PlanQuestionScore.objects.filter( + plan_score__year=year, + plan_question=self, + plan_score__council_id__in=council_ids, + ) + .values("score") + .annotate(score_count=Count("id")) + ) + + return counts + class PlanQuestionScore(ScoreFilterMixin, models.Model): """ diff --git a/scoring/static/scoring/js/main.js b/scoring/static/scoring/js/main.js index d6596f47f..e62dd1983 100644 --- a/scoring/static/scoring/js/main.js +++ b/scoring/static/scoring/js/main.js @@ -73,82 +73,126 @@ updateUIFromHashState(); // Monitor for future changes of the hash state window.addEventListener('hashchange', updateUIFromHashState); -forEachElement('.js-location-search-autocomplete', function(input){ - var ac = new Awesomplete( - input, - { - list: councils.map(function(council){ - return council.name; - }), - minChars: 3, - autoFirst: true - } - ); - input.parentNode.addEventListener('awesomplete-select', function(data){ - data.preventDefault(); - var council = findItem(councils, {'name': data.text }); - window.location.href = council['council_url']; +function setUpAutocompletes() { + forEachElement('.js-location-search-autocomplete', function(input){ + var ac = new Awesomplete( + input, + { + list: councils.map(function(council){ + return council.name; + }), + minChars: 3, + autoFirst: true + } + ); + input.parentNode.addEventListener('awesomplete-select', function(data){ + data.preventDefault(); + var council = findItem(councils, {'name': data.text }); + window.location.href = council['council_url']; + }); + input.placeholder = 'Council name or postcode'; + }); + + forEachElement('.js-location-jump-autocomplete', function(input){ + var ac = new Awesomplete( + input, + { + list: councils.map(function(council){ + return council.name; + }), + minChars: 3, + autoFirst: true + } + ); + input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ + var council = findItem(councils, {'name': data.text }); + window.location.href = council.scoring_url + '#' + serialiseObject({ + 'jump': council.slug + }); + }); }); - input.placeholder = 'Council name or postcode'; -}); -forEachElement('.js-location-jump-autocomplete', function(input){ - var ac = new Awesomplete( - input, - { - list: councils.map(function(council){ - return council.name; - }), - minChars: 3, - autoFirst: true - } - ); - input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ - var council = findItem(councils, {'name': data.text }); - window.location.href = council.scoring_url + '#' + serialiseObject({ - 'jump': council.slug + forEachElement('.js-question-jump-autocomplete', function(input){ + var ac = new Awesomplete( + input, + { + list: councils.map(function(council){ + return council.name; + }), + minChars: 3, + autoFirst: true + } + ); + input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ + var council = findItem(councils, {'name': data.text }); + window.location.href = window.location.pathname + '?type=' + council.council_type + '#' + serialiseObject({ + 'jump': council.slug + }); }); }); -}); -forEachElement('.js-question-jump-autocomplete', function(input){ - var ac = new Awesomplete( - input, - { - list: councils.map(function(council){ - return council.name; - }), - minChars: 3, - autoFirst: true - } - ); - input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ - var council = findItem(councils, {'name': data.text }); - window.location.href = window.location.pathname + '?type=' + council.council_type + '#' + serialiseObject({ - 'jump': council.slug + forEachElement('.js-location-compare-autocomplete', function(input){ + var council_type = input.dataset.council_type; + var ac = new Awesomplete( + input, + { + list: councils.filter(function(council){ + if (typeof council_type === "undefined") { return true; } + if (council.council_type === council_type) { return true; } + return false; + }).map(function(council) { return council.name; }), + minChars: 3, + autoFirst: true + } + ); + + input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ + handleCouncilSelection(data.text); }); }); -}); -forEachElement('.js-location-compare-autocomplete', function(input){ - var council_type = input.dataset.council_type; - var ac = new Awesomplete( - input, - { - list: councils.filter(function(council){ - if (typeof council_type === "undefined") { return true; } - if (council.council_type === council_type) { return true; } - return false; - }).map(function(council) { return council.name; }), - minChars: 3, - autoFirst: true - } - ); + forEachElement('.js-methodology-council-autocomplete', function(input){ + var ac = new Awesomplete( + input, + { + list: councils.map(function(council){ + return council.name; + }), + minChars: 3, + autoFirst: true + } + ); + input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ + var council = findItem(councils, {'name': data.text }); + console.log(council); + var container = document.querySelector('.js-dynamic-content'); + container.setAttribute('data-methodology-active-council-type', council.council_type); + }); + }); - input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ - handleCouncilSelection(data.text); + forEachElement('.js-section-council-autocomplete', function(input){ + var ac = new Awesomplete( + input, + { + list: councils.map(function(council){ + return council.name; + }), + minChars: 3, + autoFirst: true + } + ); + input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ + var council = findItem(councils, {'name': data.text }); + var sp = new URLSearchParams(window.location.search) + sp.delete('type'); + sp.delete('council'); + sp.append('council', council.slug); + window.location.href = window.location.pathname + '?' + sp.toString() + '#questions'; + }); }); -}); +} + +setUpAutocompletes(); // Function to handle selection from both autocomplete and suggestions function handleCouncilSelection(councilName) { @@ -388,46 +432,6 @@ forEachElement('[data-methodology-switch-council-type]', function(trigger){ }); }); -forEachElement('.js-methodology-council-autocomplete', function(input){ - var ac = new Awesomplete( - input, - { - list: councils.map(function(council){ - return council.name; - }), - minChars: 3, - autoFirst: true - } - ); - input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ - var council = findItem(councils, {'name': data.text }); - console.log(council); - var container = document.querySelector('.js-dynamic-content'); - container.setAttribute('data-methodology-active-council-type', council.council_type); - }); -}); - -forEachElement('.js-section-council-autocomplete', function(input){ - var ac = new Awesomplete( - input, - { - list: councils.map(function(council){ - return council.name; - }), - minChars: 3, - autoFirst: true - } - ); - input.parentNode.addEventListener('awesomplete-selectcomplete', function(data){ - var council = findItem(councils, {'name': data.text }); - var sp = new URLSearchParams(window.location.search) - sp.delete('type'); - sp.delete('council'); - sp.append('council', council.slug); - window.location.href = window.location.pathname + '?' + sp.toString() + '#questions'; - }); -}); - // Previous year comparison toggle on council page forEachElement('#js-toggle-previous-year-score', function(el) { el.addEventListener('change', function() { @@ -480,16 +484,15 @@ function setUpMobileCategorySelect() { } setUpMobileCategorySelect(); -function ajaxLoadCouncilTypeScorecard(url) { +function ajaxLoadPageFragments(url) { const selectors = [ - '#home-page-main-filter', + '#main-filter', '.scorecard-table', - '.js-category-select-form' + '.js-category-select-form', + '.question-performance' ]; - selectors.forEach(selector => { - document.querySelector(selector)?.classList.add('loading-shimmer'); - }); + document.documentElement.classList.add('loading-shimmer'); fetch(url) .then(response => response.text()) @@ -505,9 +508,13 @@ function ajaxLoadCouncilTypeScorecard(url) { } }); + document.documentElement.classList.remove('loading-shimmer'); + setUpTableSorting(); showOrHideYearDifference(); setUpMobileCategorySelect(); + setUpAutocompletes(); + setUpImprovedWorsenedCouncilCheckboxes(); const advancedFilter = document.querySelector('#advancedFilter'); if (advancedFilter) { @@ -524,7 +531,7 @@ function ajaxLoadCouncilTypeScorecard(url) { function handleFilterChange(e) { e.preventDefault(); - const mainForm = document.getElementById('home-page-main-filter'); + const mainForm = document.getElementById('main-filter'); if (!mainForm) return; const formData = new FormData(mainForm); @@ -536,7 +543,7 @@ function handleFilterChange(e) { const url = `${baseUrl}?${params.toString()}`; history.pushState({}, '', url); - ajaxLoadCouncilTypeScorecard(url); + ajaxLoadPageFragments(url); } if (typeof window.fetch !== 'undefined') { @@ -545,21 +552,21 @@ if (typeof window.fetch !== 'undefined') { e.preventDefault(); const href = e.target.href; history.pushState({}, '', href); - ajaxLoadCouncilTypeScorecard(href); + ajaxLoadPageFragments(href); } }); // Handle form submission (Apply filters button) document.addEventListener('submit', e => { - if (e.target.matches('#home-page-main-filter')) { + if (e.target.matches('#main-filter')) { handleFilterChange(e); } }); // Handle radio buttons and select changes document.addEventListener('change', e => { - if (e.target.matches('#home-page-main-filter input[type="radio"]') || - e.target.matches('#home-page-main-filter select')) { + if (e.target.matches('#main-filter input[type="radio"]') || + e.target.matches('#main-filter select')) { handleFilterChange(new Event('submit')); } }); @@ -569,7 +576,7 @@ if (typeof window.fetch !== 'undefined') { if (e.target.matches('#resetButton')) { e.preventDefault(); - const mainForm = document.getElementById('home-page-main-filter'); + const mainForm = document.getElementById('main-filter'); if (mainForm) { // Reset radio buttons mainForm.querySelectorAll('input[type="radio"]').forEach(radio => { @@ -597,7 +604,7 @@ if (typeof window.fetch !== 'undefined') { window.addEventListener('popstate', e => { const url = new URL(window.location.href); if (councilTypePaths.includes(url.pathname)) { - ajaxLoadCouncilTypeScorecard(window.location.href); + ajaxLoadPageFragments(window.location.href); } }); } @@ -651,26 +658,30 @@ function updateTableVisibility() { }); } -forEachElement('.js-checkbox-improved-councils', function(checkbox) { - checkbox.addEventListener('change', function() { - // If this checkbox is checked, uncheck the other one - if (this.checked) { - forEachElement('.js-checkbox-worsened-councils', function(otherCheckbox) { - otherCheckbox.checked = false; - }); - } - updateTableVisibility(); +function setUpImprovedWorsenedCouncilCheckboxes() { + forEachElement('.js-checkbox-improved-councils', function(checkbox) { + checkbox.addEventListener('change', function() { + // If this checkbox is checked, uncheck the other one + if (this.checked) { + forEachElement('.js-checkbox-worsened-councils', function(otherCheckbox) { + otherCheckbox.checked = false; + }); + } + updateTableVisibility(); + }); }); -}); -forEachElement('.js-checkbox-worsened-councils', function(checkbox) { - checkbox.addEventListener('change', function() { - // If this checkbox is checked, uncheck the other one - if (this.checked) { - forEachElement('.js-checkbox-improved-councils', function(otherCheckbox) { - otherCheckbox.checked = false; - }); - } - updateTableVisibility(); + forEachElement('.js-checkbox-worsened-councils', function(checkbox) { + checkbox.addEventListener('change', function() { + // If this checkbox is checked, uncheck the other one + if (this.checked) { + forEachElement('.js-checkbox-improved-councils', function(otherCheckbox) { + otherCheckbox.checked = false; + }); + } + updateTableVisibility(); + }); }); -}); +} + +setUpImprovedWorsenedCouncilCheckboxes(); diff --git a/scoring/static/scoring/scss/loading-shimmer.scss b/scoring/static/scoring/scss/loading-shimmer.scss index 7e5402320..97af8df7e 100644 --- a/scoring/static/scoring/scss/loading-shimmer.scss +++ b/scoring/static/scoring/scss/loading-shimmer.scss @@ -1,4 +1,13 @@ -.loading-shimmer { +@keyframes shimmer { + 0% { + background-position: right; + } + 100% { + background-position: left; + } +} + +%loading-shimmer { position: relative; filter: grayscale(50%); opacity: 0.5; @@ -15,13 +24,15 @@ background-size: 300% 100%; animation: shimmer 2s infinite; } +} - @keyframes shimmer { - 0% { - background-position: right; - } - 100% { - background-position: left; - } +.loading-shimmer { + #main-filter, + .scorecard-table, + .js-category-select-form, + .question-performance > h3 .text-muted, + .question-performance .card, + .table-council-question-performance { + @extend %loading-shimmer; } } diff --git a/scoring/static/scoring/scss/methodology.scss b/scoring/static/scoring/scss/methodology.scss index 2e76a99e6..73984dc31 100644 --- a/scoring/static/scoring/scss/methodology.scss +++ b/scoring/static/scoring/scss/methodology.scss @@ -84,6 +84,16 @@ $council-types: ( .radio-btn { margin: 0 !important; } + + .btn:last-of-type { + margin-right: auto; // push searchbar/autocomplete to the right + } + + .searchbar { + width: 100%; + max-width: 20em; + border-color: #999; + } } .question-card--removed { diff --git a/scoring/templates/scoring/includes/advanced-filter.html b/scoring/templates/scoring/includes/advanced-filter.html index 0395888a9..60ac95dfb 100644 --- a/scoring/templates/scoring/includes/advanced-filter.html +++ b/scoring/templates/scoring/includes/advanced-filter.html @@ -1,5 +1,3 @@ -

Advanced filters

-
{% if filter_auth_type %} @@ -33,7 +31,7 @@

Advanced filters

{% endif %} - {% if authority_type == 'district' %} + {% if authority_type == 'district' or scoring_group.slug == 'district' %}
- {% if authority_type != 'combined' and authority_type != 'northern-ireland' %} + {% if authority_type != 'combined' and authority_type != 'northern-ireland' or scoring_group.slug != 'combined' and scoring_group.slug != 'northern-ireland' %}
diff --git a/scoring/templates/scoring/includes/main-filter.html b/scoring/templates/scoring/includes/main-filter.html index 60a6335ab..eb6698e6e 100644 --- a/scoring/templates/scoring/includes/main-filter.html +++ b/scoring/templates/scoring/includes/main-filter.html @@ -1,4 +1,4 @@ -
+ {% if current_page == 'home-page' %}
Single Tier @@ -27,29 +27,54 @@
+ {% elif current_page == 'question-detail' %} + + {% if request.GET.type %} + + {% endif %} + {% endif %}
- {% if current_page == 'home-page' and scoring_group.slug == 'single' %} -
- Filter by nation -
- - -
-
- - -
-
- - -
-
- - -
-
+ {% if current_page == 'home-page' or current_page == 'question-detail' %} + {% if scoring_group.slug == 'single' %} +
+ Filter by nation +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ {% endif %} {% endif %}
-
-
-

Question performance

+ {% if question_removed %} - {% if applicable_scoring_groups|length > 1 %} - - {% endif %} -
+ - {% if question_removed %} - + {% else %} + + {% if applicable_scoring_groups|length > 1 %} +

Question performance by council type

+ {% include 'scoring/includes/main-filter.html' %} {% else %} +

Question performance

+ {% endif %} + +
+ {% if scoring_group and totals %} -
+

+ Points distribution + + {% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=1 %} + +

+
{% for t in totals %} -
+

@@ -130,25 +117,24 @@

{% endfor %}

- {% if previous_year %} + {% if previous_year %} {% if max_score_changed %} - +

It is not possible to compare performance on this question between {{ plan_year }} and {{ previous_year }} because this question’s maximum score was modified in {{ plan_year }}.

{% elif comparison_overridden %} - +

It is not possible to compare performance on this question between {{ plan_year }} and {{ previous_year }} data because this question was modified in {{ plan_year }}.

{% elif no_comparison %} - - {% elif not question.is_negatively_marked %} -

Performance comparison between {{ previous_year }} and {{ plan_year }}

-

{% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=1 %}

+

This question was introduced in the {{ plan_year }} Action Scorecards and has no historical data for comparison.

+ {% else %} +

Note: “in {{ previous_year }}” counts show how the councils listed below were marked on this question in {{ previous_year }}. This list of councils may be slightly different to the list of councils originally assessed on this question in {{ previous_year }}, due to the creation and abolition of councils{% if filter_params.ruc_cluser or filter_params.population or filter_params.imdq or filter_params.control %}, or changes in your filtered properties{% endif %} between Scorecard years.

+ {% endif %} + + {% if not max_score_changed and not comparison_overridden and not no_comparison and not question.is_negatively_marked %} +

+ Rising and falling + + {% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=1 %} + +

@@ -197,27 +183,25 @@

Performance comparison between {{ previous_year }} and

{% endif %} - -
-
-
-
-

Legends for difference column

-
- -- No change -
-
- NA New question (not in previous scorecards) -
-
-
-
-
{% endif %} + {% endif %} + {% if scoring_group and not scores %} +
+

No councils match your filters

+

Try adjusting your filter criteria or + + clear all filters.

+
{% endif %} {% if scores %} +

+ Scores and evidence + + {% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=1 %} + +

@@ -264,7 +248,7 @@

Legends for difference column

{% if score.score != 0 %}

Evidence

-
    +
      {% for evidence_link in score.evidence_links_cleaned %}
    • {% if evidence_link|slice:":4" == "http" %} @@ -302,7 +286,7 @@

      Legends for difference column

      {% endif %}
{% if score.score != 0 %} -
    +
      {% for evidence_link in score.evidence_links_cleaned %}
    • {% if evidence_link|slice:":4" == "http" %} @@ -322,6 +306,9 @@

      Legends for difference column

{% endif %} - {% endif %} + +
+ + {% endif %}
{% endblock %} diff --git a/scoring/tests/test_views.py b/scoring/tests/test_views.py index e0e021554..f00f6ecc7 100644 --- a/scoring/tests/test_views.py +++ b/scoring/tests/test_views.py @@ -633,3 +633,84 @@ def test_answer_view(self): }, ], ) + + +@override_settings(PLAN_YEAR="2023") +class TestQuestionViewFilters(TestCase): + """Test filtering functionality on QuestionView""" + + fixtures = ["test_answers.json"] + + def setUp(self): + self.client = Client() + + def test_question_view_without_filters(self): + """Test question view loads without filters applied""" + url = reverse("scoring:question", urlconf="scoring.urls", args=["s1_b_h_q1"]) + response = self.client.get(url, HTTP_HOST="councilclimatescorecards.com") + + self.assertEqual(response.status_code, 200) + # Note: test fixture doesn't have scoring groups, so no scores context + + def test_question_view_with_country_filter(self): + """Test filtering by country parameter""" + url = reverse("scoring:question", urlconf="scoring.urls", args=["s1_b_h_q1"]) + response = self.client.get( + url, {"country": "1"}, HTTP_HOST="councilclimatescorecards.com" # England + ) + + # Verify page loads successfully with filter parameter + self.assertEqual(response.status_code, 200) + + def test_question_view_with_population_filter(self): + """Test filtering by population parameter""" + url = reverse("scoring:question", urlconf="scoring.urls", args=["s1_b_h_q1"]) + response = self.client.get( + url, {"population": "50k-80k"}, HTTP_HOST="councilclimatescorecards.com" + ) + + # Verify page loads successfully with filter parameter + self.assertEqual(response.status_code, 200) + + def test_question_view_with_multiple_filters(self): + """Test applying multiple filters simultaneously""" + url = reverse("scoring:question", urlconf="scoring.urls", args=["s1_b_h_q1"]) + response = self.client.get( + url, + {"country": "1", "ruc_cluster": "urban"}, + HTTP_HOST="councilclimatescorecards.com", + ) + + # Verify page loads successfully with multiple filter parameters + self.assertEqual(response.status_code, 200) + + def test_question_view_filter_with_type_parameter(self): + """Test that filters work alongside authority type parameter""" + url = reverse("scoring:question", urlconf="scoring.urls", args=["s1_b_h_q1"]) + response = self.client.get( + url, + {"type": "single", "country": "1"}, + HTTP_HOST="councilclimatescorecards.com", + ) + + # Verify page loads successfully with type and filter parameters + self.assertEqual(response.status_code, 200) + + def test_question_view_accepts_all_filter_parameters(self): + """Test that all filter parameters are accepted without errors""" + url = reverse("scoring:question", urlconf="scoring.urls", args=["s1_b_h_q1"]) + response = self.client.get( + url, + { + "country": "1", + "ruc_cluster": "urban", + "population": "50k-80k", + "imdq": "1", + "control": "Labour", + "region": "London", + }, + HTTP_HOST="councilclimatescorecards.com", + ) + + # Verify page loads successfully with all filter parameters + self.assertEqual(response.status_code, 200) diff --git a/scoring/views.py b/scoring/views.py index 85c0f2c8e..34aaabe86 100644 --- a/scoring/views.py +++ b/scoring/views.py @@ -1324,7 +1324,12 @@ def get_context_data(self, **kwargs): @method_decorator(cache_control(**cache_settings), name="dispatch") -class QuestionView(PrivateScorecardsAccessMixin, SearchAutocompleteMixin, DetailView): +class QuestionView( + PrivateScorecardsAccessMixin, + SearchAutocompleteMixin, + AdvancedFilterMixin, + DetailView, +): model = PlanQuestion context_object_name = "question" template_name = "scoring/question.html" @@ -1336,9 +1341,29 @@ def get_object(self): section__year=self.request.year.year, ) + def get_filter_queryset(self, question, scoring_group): + """Build the base queryset for scores that will be filtered.""" + return ( + PlanQuestionScore.objects.filter( + plan_score__year=self.request.year.year, + plan_question=question, + plan_score__council__authority_type__in=scoring_group["types"], + ) + .select_related("plan_score", "plan_score__council") + .order_by("-score", "plan_score__council__name") + ) + + def get_filterset(self, queryset): + """Instantiate and return the filterset for filtering scores.""" + return QuestionScoreFilter( + data=self.request.GET or None, queryset=queryset, request=self.request + ) + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + context["current_page"] = "question-detail" + question = context["question"] context["page_title"] = question.text context["plan_year"] = self.request.year.year @@ -1385,15 +1410,12 @@ def get_context_data(self, **kwargs): if scoring_group is not None: context["scoring_group"] = scoring_group - context["scores"] = ( - PlanQuestionScore.objects.filter( - plan_score__year=self.request.year.year, - plan_question=question, - plan_score__council__authority_type__in=scoring_group["types"], - ) - .select_related("plan_score", "plan_score__council") - .order_by("-score", "plan_score__council__name") - ) + + # Build base queryset and apply filters + base_queryset = self.get_filter_queryset(question, scoring_group) + filterset = self.get_filterset(base_queryset) + context["filter"] = filterset + context["scores"] = filterset.qs prev_counts = None if self.request.year.previous_year: @@ -1411,6 +1433,13 @@ def get_context_data(self, **kwargs): .annotate(change=(F("score") - F("previous_score"))) ) + # Save the queryset before we iterate (iteration evaluates it) + scores_for_breakdown = context["scores"] + filtered_ids = list( + scores_for_breakdown.values_list("plan_score__council_id", flat=True) + ) + + if self.request.year.previous_year: context["increased"] = 0 context["decreased"] = 0 for score in context["scores"]: @@ -1426,13 +1455,27 @@ def get_context_data(self, **kwargs): previous_q_overriden = True if previous_q: - prev_counts = previous_q.get_scores_breakdown( - year=self.request.year.previous_year.year, - scoring_group=scoring_group, + prev_counts = list( + previous_q.get_score_breakdown_for_councils( + filtered_ids, self.request.year.previous_year.year + ) ) - score_counts = question.get_scores_breakdown( - year=self.request.year.year, scoring_group=scoring_group + # Setup filter UI context + context = self.setup_filter_context(context, filterset, scoring_group) + + # Show region filter only for England + context["show_region_filter"] = False + if context.get("filter_params"): + country = context["filter_params"].get("country") + if country == "1" or country == "" or country is None: + context["show_region_filter"] = True + + # Calculate score breakdown from filtered queryset + score_counts = list( + context["question"].get_score_breakdown_for_councils( + filtered_ids, self.request.year.year + ) ) totals = {}