diff --git a/app/broadcast_areas/__init__.py b/app/broadcast_areas/__init__.py index a9e86c1c1..f7488d0dc 100644 --- a/app/broadcast_areas/__init__.py +++ b/app/broadcast_areas/__init__.py @@ -44,7 +44,7 @@ class BroadcastArea(SortableMixin): BroadcastAreasRepository().get_simple_polygons_for_area(self.id) ) - @property + @cached_property def sub_areas(self): return [ BroadcastArea(row) diff --git a/app/broadcast_areas/repo.py b/app/broadcast_areas/repo.py index 3527d0abd..e1aec1333 100644 --- a/app/broadcast_areas/repo.py +++ b/app/broadcast_areas/repo.py @@ -166,11 +166,16 @@ class BroadcastAreasRepository(object): return areas def get_all_areas_for_library(self, library_id): + # only interested in areas with children - local authorities, counties, unitary authorities. not wards. q = """ SELECT id, name FROM broadcast_areas + JOIN ( + SELECT DISTINCT broadcast_area_library_group_id + FROM broadcast_areas + WHERE broadcast_area_library_group_id IS NOT NULL + ) AS parent_broadcast_areas ON parent_broadcast_areas.broadcast_area_library_group_id = broadcast_areas.id WHERE broadcast_area_library_id = ? - AND broadcast_area_library_group_id IS NULL """ results = self.query(q, library_id) diff --git a/app/main/views/broadcast.py b/app/main/views/broadcast.py index 0ec91c4f1..16b820f65 100644 --- a/app/main/views/broadcast.py +++ b/app/main/views/broadcast.py @@ -160,8 +160,10 @@ def choose_broadcast_sub_area(service_id, broadcast_message_id, library_slug, ar ) area = BroadcastMessage.libraries.get_areas(area_slug)[0] + is_county = any(sub_area.sub_areas for sub_area in area.sub_areas) + form = BroadcastAreaFormWithSelectAll.from_library( - area.sub_areas, + [] if is_county else area.sub_areas, select_all_choice=(area.id, f'All of {area.name}'), ) if form.validate_on_submit(): @@ -171,6 +173,20 @@ def choose_broadcast_sub_area(service_id, broadcast_message_id, library_slug, ar service_id=current_service.id, broadcast_message_id=broadcast_message.id, )) + + if is_county: + # area = county. sub_areas = districts. they have wards, so link to individual district pages + return render_template( + 'views/broadcast/counties.html', + form=form, + search_form=SearchByNameForm(), + show_search_form=(len(area.sub_areas) > 7), + library_slug=library_slug, + page_title=f'Choose an area of {area.name}', + broadcast_message=broadcast_message, + county=area, + ) + return render_template( 'views/broadcast/sub-areas.html', form=form, diff --git a/app/templates/views/broadcast/counties.html b/app/templates/views/broadcast/counties.html new file mode 100644 index 000000000..25a317c21 --- /dev/null +++ b/app/templates/views/broadcast/counties.html @@ -0,0 +1,42 @@ +{% from "components/page-header.html" import page_header %} +{% from "components/live-search.html" import live_search %} +{% from "components/page-footer.html" import sticky_page_footer %} +{% from "components/form.html" import form_wrapper %} + + + +{% extends "withnav_template.html" %} + +{% block service_page_title %} + {{ page_title }} +{% endblock %} + +{% block maincolumn_content %} + + {{ page_header( + page_title, + back_link=url_for('.choose_broadcast_library', service_id=current_service.id, broadcast_message_id=broadcast_message.id), + )}} + + {% call form_wrapper() %} + +
+ {{ form.select_all }} +
+ {{ live_search(target_selector='.file-list-item', show=show_search_form, form=search_form, label='Or by district') }} + + {% for area in county.sub_areas|sort %} +
+ {# these are districts within a county#} + {{ area.name }} +
+ {% endfor %} + + {{ sticky_page_footer('Add to broadcast') }} + + {% endcall %} + +{% endblock %} diff --git a/tests/app/broadcast_areas/test_broadcast_area.py b/tests/app/broadcast_areas/test_broadcast_area.py index d14f1b1e8..5a10fe338 100644 --- a/tests/app/broadcast_areas/test_broadcast_area.py +++ b/tests/app/broadcast_areas/test_broadcast_area.py @@ -16,7 +16,7 @@ def test_loads_libraries(): False, ), ( - 'wd20-lad20', + 'wd20-lad20-ctyua19', 'Local authorities', True, ), @@ -40,7 +40,7 @@ def test_examples(): countries = broadcast_area_libraries.get('ctry19').get_examples() assert countries == 'England, Northern Ireland, Scotland, and Wales' - wards = broadcast_area_libraries.get('wd20-lad20').get_examples() + wards = broadcast_area_libraries.get('wd20-lad20-ctyua19').get_examples() assert wards == 'Aberdeen City, Aberdeenshire, Adur, and 375 more…' diff --git a/tests/app/main/views/test_broadcast.py b/tests/app/main/views/test_broadcast.py index 37b8d7ce6..088ff76b7 100644 --- a/tests/app/main/views/test_broadcast.py +++ b/tests/app/main/views/test_broadcast.py @@ -412,7 +412,7 @@ def test_choose_broadcast_area_page_for_area_with_sub_areas( '.choose_broadcast_area', service_id=SERVICE_ONE_ID, broadcast_message_id=fake_uuid, - library_slug='wd20-lad20', + library_slug='wd20-lad20-ctyua19', ) assert normalize_spaces(page.select_one('h1').text) == ( 'Choose a local authority' @@ -425,7 +425,7 @@ def test_choose_broadcast_area_page_for_area_with_sub_areas( 'main.choose_broadcast_sub_area', service_id=SERVICE_ONE_ID, broadcast_message_id=fake_uuid, - library_slug='wd20-lad20', + library_slug='wd20-lad20-ctyua19', ) choices = [ ( @@ -453,7 +453,7 @@ def test_choose_broadcast_area_page_for_area_with_sub_areas( ] -def test_choose_broadcast_sub_area_page( +def test_choose_broadcast_sub_area_page_for_district_shows_checkboxes_for_wards( client_request, service_one, mock_get_draft_broadcast_message, @@ -464,7 +464,7 @@ def test_choose_broadcast_sub_area_page( 'main.choose_broadcast_sub_area', service_id=SERVICE_ONE_ID, broadcast_message_id=fake_uuid, - library_slug='wd20-lad20', + library_slug='wd20-lad20-ctyua19', area_slug='lad20-S12000033', ) assert normalize_spaces(page.select_one('h1').text) == ( @@ -502,6 +502,62 @@ def test_choose_broadcast_sub_area_page( ] +def test_choose_broadcast_sub_area_page_for_county_shows_links_for_districts( + client_request, + service_one, + mock_get_draft_broadcast_message, + fake_uuid, +): + service_one['permissions'] += ['broadcast'] + page = client_request.get( + 'main.choose_broadcast_sub_area', + service_id=SERVICE_ONE_ID, + broadcast_message_id=fake_uuid, + library_slug='wd20-lad20-ctyua19', + area_slug='ctyua19-E10000016', # Kent + ) + assert normalize_spaces(page.select_one('h1').text) == ( + 'Choose an area of Kent' + ) + live_search = page.select_one("[data-module=live-search]") + assert live_search['data-targets'] == '.file-list-item' + assert live_search.select_one('input')['type'] == 'search' + all_choices_checkbox = [ + ( + choice.select_one('input')['value'], + normalize_spaces(choice.select_one('label').text), + ) + for choice in page.select('form[method=post] .govuk-checkboxes__item') + ] + districts = [ + ( + district['href'], + district.text, + ) + for district in page.select('form[method=post] a') + ] + assert all_choices_checkbox == [ + ('y', 'All of Kent'), + ] + assert len(districts) == 12 + assert districts[0][0] == url_for( + 'main.choose_broadcast_sub_area', + service_id=SERVICE_ONE_ID, + broadcast_message_id=fake_uuid, + library_slug='wd20-lad20-ctyua19', + area_slug='lad20-E07000105' + ) + assert districts[0][1] == 'Ashford' + assert districts[-1][0] == url_for( + 'main.choose_broadcast_sub_area', + service_id=SERVICE_ONE_ID, + broadcast_message_id=fake_uuid, + library_slug='wd20-lad20-ctyua19', + area_slug='lad20-E07000116' + ) + assert districts[-1][1] == 'Tunbridge Wells' + + def test_add_broadcast_area( client_request, service_one, @@ -554,7 +610,7 @@ def test_add_broadcast_area( 'wd20-S13002836', ]), )) -def test_add_broadcast_sub_area( +def test_add_broadcast_sub_area_district_view( client_request, service_one, mock_get_draft_broadcast_message, @@ -574,7 +630,7 @@ def test_add_broadcast_sub_area( '.choose_broadcast_sub_area', service_id=SERVICE_ONE_ID, broadcast_message_id=fake_uuid, - library_slug='wd20-lad20', + library_slug='wd20-lad20-ctyua19', area_slug='lad20-S12000033', _data=post_data, ) @@ -592,6 +648,44 @@ def test_add_broadcast_sub_area( ) +def test_add_broadcast_sub_area_county_view( + client_request, + service_one, + mock_get_draft_broadcast_message, + mock_update_broadcast_message, + fake_uuid, + mocker, +): + service_one['permissions'] += ['broadcast'] + polygon_class = namedtuple("polygon_class", ["as_coordinate_pairs_lat_long"]) + coordinates = [[50.1, 0.1], [50.2, 0.2], [50.3, 0.2]] + polygons = polygon_class(as_coordinate_pairs_lat_long=coordinates) + mocker.patch('app.models.broadcast_message.BroadcastMessage.get_simple_polygons', return_value=polygons) + + client_request.post( + '.choose_broadcast_sub_area', + service_id=SERVICE_ONE_ID, + broadcast_message_id=fake_uuid, + library_slug='wd20-lad20-ctyua19', + area_slug='ctyua19-E10000016', # Kent + _data={'select_all': 'y'}, + ) + mock_update_broadcast_message.assert_called_once_with( + service_id=SERVICE_ONE_ID, + broadcast_message_id=fake_uuid, + data={ + 'simple_polygons': coordinates, + 'areas': [ + # These two areas are on the broadcast already + 'ctry19-E92000001', + 'ctry19-S92000003', + ] + [ + 'ctyua19-E10000016' + ] + }, + ) + + def test_remove_broadcast_area_page( client_request, service_one,