mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-18 21:44:11 -04:00
Add some views for selecting broadcast areas
These are just so we have some pages to click through for now. They don’t use real templates, or any of the broadcast stuff from the database. But I think it’s useful to get some skeleton pages in first so that we can see the map etc working in production, then build on that, without having to do it all in one mega PR. For that reason there are two short term things I’ve done in this commit which should be revisited soon: - no tests for the endpoints - data about which areas are selected is stored in the session
This commit is contained in:
@@ -7,6 +7,7 @@ from app.main.views import ( # noqa isort:skip
|
||||
add_service,
|
||||
agreement,
|
||||
api_keys,
|
||||
broadcast,
|
||||
choose_account,
|
||||
code_not_received,
|
||||
conversation,
|
||||
|
||||
106
app/main/views/broadcast.py
Normal file
106
app/main/views/broadcast.py
Normal file
@@ -0,0 +1,106 @@
|
||||
from flask import redirect, render_template, request, session, url_for
|
||||
from notifications_utils.broadcast_areas import broadcast_area_libraries
|
||||
from orderedset import OrderedSet
|
||||
|
||||
from app import current_service
|
||||
from app.main import main
|
||||
from app.utils import service_has_permission, user_has_permissions
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast')
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def broadcast(service_id):
|
||||
if 'broadcast_areas' in session:
|
||||
session.pop('broadcast_areas')
|
||||
return redirect(url_for(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=current_service.id,
|
||||
))
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast/areas')
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def preview_broadcast_areas(service_id):
|
||||
selected_areas_ids = session.get('broadcast_areas', [])
|
||||
return render_template(
|
||||
'views/broadcast/preview-areas.html',
|
||||
selected=list(broadcast_area_libraries.get_areas(
|
||||
*selected_areas_ids
|
||||
)),
|
||||
area_polygons=broadcast_area_libraries.get_polygons_for_areas_lat_long(
|
||||
*selected_areas_ids
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast/libraries')
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def choose_broadcast_library(service_id):
|
||||
return render_template(
|
||||
'views/broadcast/libraries.html',
|
||||
libraries=broadcast_area_libraries,
|
||||
selected=broadcast_area_libraries.get_areas(
|
||||
*session.get('broadcast_areas', [])
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast/libraries/<library_slug>')
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def choose_broadcast_area(service_id, library_slug):
|
||||
return render_template(
|
||||
'views/broadcast/areas.html',
|
||||
areas=broadcast_area_libraries.get(library_slug),
|
||||
)
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast/add/<area_slug>')
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def add_broadcast_area(service_id, area_slug):
|
||||
if not session.get('broadcast_areas'):
|
||||
session['broadcast_areas'] = []
|
||||
|
||||
session['broadcast_areas'].append(area_slug)
|
||||
|
||||
session['broadcast_areas'] = list(OrderedSet(
|
||||
session['broadcast_areas']
|
||||
))
|
||||
return redirect(url_for(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=current_service.id,
|
||||
))
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast/remove/<area_slug>')
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def remove_broadcast_area(service_id, area_slug):
|
||||
session['broadcast_areas'] = list(filter(
|
||||
lambda saved_area_id: saved_area_id != area_slug,
|
||||
session.get('broadcast_areas', []),
|
||||
))
|
||||
|
||||
return redirect(url_for(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=current_service.id,
|
||||
))
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast/preview', methods=['GET', 'POST'])
|
||||
@user_has_permissions('send_messages')
|
||||
@service_has_permission('broadcast')
|
||||
def preview_broadcast_message(service_id):
|
||||
if request.method == 'POST':
|
||||
return 'OK'
|
||||
selected_areas = session.get('broadcast_areas', [])
|
||||
return render_template(
|
||||
'views/broadcast/preview-message.html',
|
||||
selected=list(broadcast_area_libraries.get_areas(
|
||||
*selected_areas
|
||||
)),
|
||||
)
|
||||
@@ -351,6 +351,13 @@ class HeaderNavigation(Navigation):
|
||||
'old_guest_list',
|
||||
'who_can_use_notify',
|
||||
'who_its_for',
|
||||
'broadcast',
|
||||
'preview_broadcast_areas',
|
||||
'choose_broadcast_library',
|
||||
'choose_broadcast_area',
|
||||
'add_broadcast_area',
|
||||
'remove_broadcast_area',
|
||||
'preview_broadcast_message',
|
||||
}
|
||||
|
||||
# header HTML now comes from GOVUK Frontend so requires a boolean, not an attribute
|
||||
@@ -399,6 +406,13 @@ class MainNavigation(Navigation):
|
||||
'view_template',
|
||||
'view_template_version',
|
||||
'view_template_versions',
|
||||
'broadcast',
|
||||
'preview_broadcast_areas',
|
||||
'choose_broadcast_library',
|
||||
'choose_broadcast_area',
|
||||
'add_broadcast_area',
|
||||
'remove_broadcast_area',
|
||||
'preview_broadcast_message',
|
||||
},
|
||||
'uploads': {
|
||||
'upload_contact_list',
|
||||
@@ -978,6 +992,13 @@ class CaseworkNavigation(Navigation):
|
||||
'old_guest_list',
|
||||
'who_can_use_notify',
|
||||
'who_its_for',
|
||||
'broadcast',
|
||||
'preview_broadcast_areas',
|
||||
'choose_broadcast_library',
|
||||
'choose_broadcast_area',
|
||||
'add_broadcast_area',
|
||||
'remove_broadcast_area',
|
||||
'preview_broadcast_message',
|
||||
}
|
||||
|
||||
|
||||
@@ -1288,4 +1309,11 @@ class OrgNavigation(Navigation):
|
||||
'old_guest_list',
|
||||
'who_can_use_notify',
|
||||
'who_its_for',
|
||||
'broadcast',
|
||||
'preview_broadcast_areas',
|
||||
'choose_broadcast_library',
|
||||
'choose_broadcast_area',
|
||||
'add_broadcast_area',
|
||||
'remove_broadcast_area',
|
||||
'preview_broadcast_message',
|
||||
}
|
||||
|
||||
20
app/templates/views/broadcast/areas.html
Normal file
20
app/templates/views/broadcast/areas.html
Normal file
@@ -0,0 +1,20 @@
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% block service_page_title %}
|
||||
{{ page_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header(
|
||||
regions.name,
|
||||
back_link=url_for('.choose_broadcast_library', service_id=current_service.id),
|
||||
)}}
|
||||
|
||||
{% for area in areas %}
|
||||
<h2 class="govuk-heading-m"><a class="govuk-link govuk-link--no-visited-state" href="{{ url_for('.add_broadcast_area', service_id=current_service.id, area_slug=area.id) }}">{{ region.name }}</a></h2>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
21
app/templates/views/broadcast/libraries.html
Normal file
21
app/templates/views/broadcast/libraries.html
Normal file
@@ -0,0 +1,21 @@
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% block service_page_title %}
|
||||
Choose where to broadcast to
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header(
|
||||
"Choose where to broadcast to",
|
||||
back_link=url_for(".preview_broadcast_areas", service_id=current_service.id)
|
||||
) }}
|
||||
|
||||
{% for library in libraries|sort %}
|
||||
<a class="file-list-filename-large govuk-link govuk-link--no-visited-state" href="{{ url_for('.choose_broadcast_area', service_id=current_service.id, library_slug=library.id) }}">{{ library.name }}</a>
|
||||
<p class="file-list-hint-large">{{ library.examples }}</p>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
47
app/templates/views/broadcast/preview-areas.html
Normal file
47
app/templates/views/broadcast/preview-areas.html
Normal file
@@ -0,0 +1,47 @@
|
||||
{% from "components/button/macro.njk" import govukButton %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import sticky_page_footer %}
|
||||
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% block service_page_title %}
|
||||
Choose where to broadcast to
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header("Choose where to broadcast to", back_link="#") }}
|
||||
|
||||
{% for area in selected %}
|
||||
{{ area.name }} (<a href="{{ url_for('.remove_broadcast_area', service_id=current_service.id, area_slug=area.id) }}">remove</a>) 
|
||||
{% if loop.last %}
|
||||
<p class="govuk-body">
|
||||
{{ govukButton({
|
||||
"element": "a",
|
||||
"text": "Add another area",
|
||||
"href": url_for('.choose_broadcast_library', service_id=current_service.id),
|
||||
"classes": "govuk-button--secondary govuk-!-margin-top-2"
|
||||
}) }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p class="govuk-body">
|
||||
{{ govukButton({
|
||||
"element": "a",
|
||||
"text": "Add broadcast areas",
|
||||
"href": url_for('.choose_broadcast_library', service_id=current_service.id),
|
||||
"classes": "govuk-button--secondary"
|
||||
}) }}
|
||||
</p>
|
||||
{% endfor %}
|
||||
|
||||
{% if selected %}
|
||||
{% for area in area_polygons %}
|
||||
{{ area }}<br><br>
|
||||
{% endfor %}
|
||||
<form action="{{ url_for('.preview_broadcast_message', service_id=current_service.id) }}" method="get">
|
||||
{{ sticky_page_footer('Continue to preview') }}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
41
app/templates/views/broadcast/preview-message.html
Normal file
41
app/templates/views/broadcast/preview-message.html
Normal file
@@ -0,0 +1,41 @@
|
||||
{% from "components/button/macro.njk" import govukButton %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import sticky_page_footer %}
|
||||
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% block service_page_title %}
|
||||
Preview message
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header("Preview message", back_link=url_for('.preview_broadcast_areas', service_id=current_service.id)) }}
|
||||
|
||||
{% for region in selected %}
|
||||
{% if loop.first %}
|
||||
<ul class="region-list">
|
||||
{% endif %}
|
||||
<li class="region-list-item">
|
||||
{{ region.name }}
|
||||
</li>
|
||||
{% if loop.last %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if selected %}
|
||||
|
||||
<p class="govuk-body">
|
||||
{{ "<message here>" }}
|
||||
</p>
|
||||
|
||||
{% call form_wrapper() %}
|
||||
{{ sticky_page_footer('Start broadcast') }}
|
||||
{% endcall %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -29,8 +29,15 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% elif template.template_type == 'broadcast' %}
|
||||
{% if current_user.has_permissions('send_messages') %}
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<a href="{{ url_for(".broadcast", service_id=current_service.id) }}" class="govuk-link govuk-link--no-visited-state pill-separate-item">
|
||||
Prepare broadcast
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if current_user.has_permissions('manage_templates') %}
|
||||
<div class="govuk-grid-column-full">
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<a href="{{ url_for(".edit_service_template", service_id=current_service.id, template_id=template.id) }}" class="govuk-link govuk-link--no-visited-state pill-separate-item">
|
||||
Edit
|
||||
</a>
|
||||
|
||||
@@ -23,7 +23,7 @@ notifications-python-client==5.6.0
|
||||
awscli-cwlogs>=1.4,<1.5
|
||||
itsdangerous==1.1.0
|
||||
|
||||
git+https://github.com/alphagov/notifications-utils.git@40.2.1#egg=notifications-utils==40.2.1
|
||||
git+https://github.com/alphagov/notifications-utils.git@40.3.1#egg=notifications-utils==40.3.1
|
||||
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
|
||||
|
||||
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
|
||||
|
||||
@@ -25,7 +25,7 @@ notifications-python-client==5.6.0
|
||||
awscli-cwlogs>=1.4,<1.5
|
||||
itsdangerous==1.1.0
|
||||
|
||||
git+https://github.com/alphagov/notifications-utils.git@40.2.1#egg=notifications-utils==40.2.1
|
||||
git+https://github.com/alphagov/notifications-utils.git@40.3.1#egg=notifications-utils==40.3.1
|
||||
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
|
||||
|
||||
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
|
||||
@@ -33,10 +33,10 @@ prometheus-client==0.8.0
|
||||
gds-metrics==0.2.0
|
||||
|
||||
## The following requirements were added by pip freeze:
|
||||
awscli==1.18.93
|
||||
awscli==1.18.95
|
||||
bleach==3.1.4
|
||||
boto3==1.10.38
|
||||
botocore==1.17.16
|
||||
botocore==1.17.18
|
||||
cachetools==4.1.0
|
||||
certifi==2020.6.20
|
||||
chardet==3.0.4
|
||||
@@ -48,6 +48,7 @@ docutils==0.15.2
|
||||
et-xmlfile==1.0.1
|
||||
flask-redis==0.4.0
|
||||
future==0.18.2
|
||||
geojson==2.5.0
|
||||
greenlet==0.4.16
|
||||
idna==2.10
|
||||
jdcal==1.4.1
|
||||
|
||||
121
tests/app/main/views/test_broadcast.py
Normal file
121
tests/app/main/views/test_broadcast.py
Normal file
@@ -0,0 +1,121 @@
|
||||
import pytest
|
||||
from flask import url_for
|
||||
|
||||
from tests.conftest import SERVICE_ONE_ID
|
||||
|
||||
|
||||
@pytest.mark.parametrize('endpoint, extra_args', (
|
||||
('.broadcast', {}),
|
||||
('.preview_broadcast_areas', {}),
|
||||
('.choose_broadcast_library', {}),
|
||||
('.choose_broadcast_area', {'library_slug': 'countries'}),
|
||||
('.add_broadcast_area', {'area_slug': 'england'}),
|
||||
('.remove_broadcast_area', {'area_slug': 'england'}),
|
||||
('.preview_broadcast_message', {}),
|
||||
))
|
||||
def test_broadcast_pages_403_without_permission(
|
||||
client_request,
|
||||
endpoint,
|
||||
extra_args,
|
||||
):
|
||||
client_request.get(
|
||||
endpoint,
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_expected_status=403,
|
||||
**extra_args
|
||||
)
|
||||
|
||||
|
||||
def test_broadcast_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.broadcast',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_expected_redirect=url_for(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
def test_preview_broadcast_areas_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
|
||||
|
||||
def test_choose_broadcast_library_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.choose_broadcast_library',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
|
||||
|
||||
def test_choose_broadcast_area_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.choose_broadcast_area',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
library_slug='countries',
|
||||
)
|
||||
|
||||
|
||||
def test_add_broadcast_area_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.add_broadcast_area',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
area_slug='england',
|
||||
_expected_redirect=url_for(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
def test_remove_broadcast_area_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.remove_broadcast_area',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
area_slug='england',
|
||||
_expected_redirect=url_for(
|
||||
'.preview_broadcast_areas',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
def test_preview_broadcast_message_page(
|
||||
client_request,
|
||||
service_one,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
client_request.get(
|
||||
'.preview_broadcast_message',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
),
|
||||
@@ -693,6 +693,10 @@ def test_view_broadcast_template(
|
||||
(link.text.strip(), link['href'])
|
||||
for link in page.select('.pill-separate-item')
|
||||
] == [
|
||||
('Prepare broadcast', url_for(
|
||||
'.broadcast',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)),
|
||||
('Edit', url_for(
|
||||
'.edit_service_template',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
|
||||
Reference in New Issue
Block a user