mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-20 22:40:31 -04:00
Add a page to choose a contact list
You’ll be able to use a contact list by first choosing a template, then choosing the list you want to use. At the moment this shows all lists, not just the ones that are compatible with your template.
This commit is contained in:
@@ -42,7 +42,7 @@ from app.main.forms import (
|
|||||||
SetSenderForm,
|
SetSenderForm,
|
||||||
get_placeholder_form_instance,
|
get_placeholder_form_instance,
|
||||||
)
|
)
|
||||||
from app.models.contact_list import ContactList
|
from app.models.contact_list import ContactList, ContactLists
|
||||||
from app.models.user import Users
|
from app.models.user import Users
|
||||||
from app.s3_client.s3_csv_client import (
|
from app.s3_client.s3_csv_client import (
|
||||||
s3download,
|
s3download,
|
||||||
@@ -492,6 +492,19 @@ def send_test_preview(service_id, template_id, filetype):
|
|||||||
return TemplatePreview.from_utils_template(template, filetype, page=request.args.get('page'))
|
return TemplatePreview.from_utils_template(template, filetype, page=request.args.get('page'))
|
||||||
|
|
||||||
|
|
||||||
|
@main.route(
|
||||||
|
'/services/<uuid:service_id>/send/<uuid:template_id>'
|
||||||
|
'/from-contact-list'
|
||||||
|
)
|
||||||
|
@user_has_permissions('send_messages')
|
||||||
|
def choose_from_contact_list(service_id, template_id):
|
||||||
|
return render_template(
|
||||||
|
'views/send-contact-list.html',
|
||||||
|
contact_lists=ContactLists(current_service.id),
|
||||||
|
template=current_service.get_template(template_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@main.route(
|
@main.route(
|
||||||
'/services/<uuid:service_id>/send/<uuid:template_id>'
|
'/services/<uuid:service_id>/send/<uuid:template_id>'
|
||||||
'/from-contact-list/<uuid:contact_list_id>'
|
'/from-contact-list/<uuid:contact_list_id>'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from notifications_utils.formatters import strip_whitespace
|
|||||||
from notifications_utils.recipients import RecipientCSV
|
from notifications_utils.recipients import RecipientCSV
|
||||||
from werkzeug.utils import cached_property
|
from werkzeug.utils import cached_property
|
||||||
|
|
||||||
from app.models import JSONModel
|
from app.models import JSONModel, ModelList
|
||||||
from app.notify_client.contact_list_api_client import contact_list_api_client
|
from app.notify_client.contact_list_api_client import contact_list_api_client
|
||||||
from app.s3_client.s3_csv_client import (
|
from app.s3_client.s3_csv_client import (
|
||||||
get_csv_metadata,
|
get_csv_metadata,
|
||||||
@@ -28,9 +28,9 @@ class ContactList(JSONModel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_id(cls, contact_list_id, *, service_id):
|
def from_id(cls, contact_list_id, *, service_id):
|
||||||
# This is temporary until we have a get single list endpoint
|
# This is temporary until we have a get single list endpoint
|
||||||
for contact_list in contact_list_api_client.get_contact_lists(service_id):
|
for contact_list in ContactLists(service_id):
|
||||||
if contact_list['id'] == contact_list_id:
|
if contact_list.id == contact_list_id:
|
||||||
return cls(contact_list)
|
return contact_list
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -77,7 +77,7 @@ class ContactList(JSONModel):
|
|||||||
metadata = ContactList.get_metadata(service_id, upload_id)
|
metadata = ContactList.get_metadata(service_id, upload_id)
|
||||||
new_upload_id = s3upload(
|
new_upload_id = s3upload(
|
||||||
service_id,
|
service_id,
|
||||||
contents,
|
{'data': contents},
|
||||||
current_app.config['AWS_REGION'],
|
current_app.config['AWS_REGION'],
|
||||||
)
|
)
|
||||||
set_metadata_on_csv_upload(
|
set_metadata_on_csv_upload(
|
||||||
@@ -111,3 +111,8 @@ class ContactList(JSONModel):
|
|||||||
international_sms=True,
|
international_sms=True,
|
||||||
max_initial_rows_shown=50,
|
max_initial_rows_shown=50,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ContactLists(ModelList):
|
||||||
|
client_method = contact_list_api_client.get_contact_lists
|
||||||
|
model = ContactList
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ class HeaderNavigation(Navigation):
|
|||||||
'check_notification',
|
'check_notification',
|
||||||
'no_cookie.check_notification_preview',
|
'no_cookie.check_notification_preview',
|
||||||
'choose_account',
|
'choose_account',
|
||||||
|
'choose_from_contact_list',
|
||||||
'choose_service',
|
'choose_service',
|
||||||
'choose_template',
|
'choose_template',
|
||||||
'choose_template_to_copy',
|
'choose_template_to_copy',
|
||||||
@@ -368,6 +369,7 @@ class MainNavigation(Navigation):
|
|||||||
'add_service_template',
|
'add_service_template',
|
||||||
'check_messages',
|
'check_messages',
|
||||||
'check_notification',
|
'check_notification',
|
||||||
|
'choose_from_contact_list',
|
||||||
'choose_template',
|
'choose_template',
|
||||||
'choose_template_to_copy',
|
'choose_template_to_copy',
|
||||||
'confirm_redact_template',
|
'confirm_redact_template',
|
||||||
@@ -658,6 +660,7 @@ class CaseworkNavigation(Navigation):
|
|||||||
|
|
||||||
mapping = {
|
mapping = {
|
||||||
'send-one-off': {
|
'send-one-off': {
|
||||||
|
'choose_from_contact_list',
|
||||||
'choose_template',
|
'choose_template',
|
||||||
'send_one_off',
|
'send_one_off',
|
||||||
'send_one_off_step',
|
'send_one_off_step',
|
||||||
@@ -1018,6 +1021,7 @@ class OrgNavigation(Navigation):
|
|||||||
'check_notification',
|
'check_notification',
|
||||||
'no_cookie.check_notification_preview',
|
'no_cookie.check_notification_preview',
|
||||||
'choose_account',
|
'choose_account',
|
||||||
|
'choose_from_contact_list',
|
||||||
'choose_service',
|
'choose_service',
|
||||||
'choose_template',
|
'choose_template',
|
||||||
'choose_template_to_copy',
|
'choose_template_to_copy',
|
||||||
|
|||||||
53
app/templates/views/send-contact-list.html
Normal file
53
app/templates/views/send-contact-list.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{% extends "withnav_template.html" %}
|
||||||
|
{% from "components/big-number.html" import big_number -%}
|
||||||
|
{% from "components/message-count-label.html" import recipient_count_label %}
|
||||||
|
{% from "components/page-header.html" import page_header %}
|
||||||
|
{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading %}
|
||||||
|
|
||||||
|
{% block service_page_title %}
|
||||||
|
Choose a saved contact list
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
|
{{ page_header(
|
||||||
|
'Choose a saved contact list',
|
||||||
|
back_link=url_for('.send_one_off', service_id=current_service.id, template_id=template.id)
|
||||||
|
) }}
|
||||||
|
|
||||||
|
<div class='dashboard-table ajax-block-container'>
|
||||||
|
{% call(item, row_number) list_table(
|
||||||
|
contact_lists,
|
||||||
|
caption="Existing contact lists",
|
||||||
|
caption_visible=False,
|
||||||
|
empty_message=(
|
||||||
|
'You don’t have any contact lists yet'
|
||||||
|
),
|
||||||
|
field_headings=[
|
||||||
|
'File',
|
||||||
|
'Status'
|
||||||
|
],
|
||||||
|
field_headings_visible=False
|
||||||
|
) %}
|
||||||
|
{% call row_heading() %}
|
||||||
|
<div class="file-list">
|
||||||
|
<a class="file-list-filename-large govuk-link govuk-link--no-visited-state" href="{{ url_for('main.send_from_contact_list', service_id=current_service.id, template_id=template.id, contact_list_id=item.id) }}">{{ item.original_file_name }}</a>
|
||||||
|
<span class="file-list-hint">
|
||||||
|
Uploaded {{ item.created_at|format_datetime_relative }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endcall %}
|
||||||
|
{% call field() %}
|
||||||
|
{{ big_number(
|
||||||
|
item.row_count,
|
||||||
|
smallest=True,
|
||||||
|
label=recipient_count_label(
|
||||||
|
item.row_count,
|
||||||
|
item.template_type
|
||||||
|
)
|
||||||
|
) }}
|
||||||
|
{% endcall %}
|
||||||
|
{% endcall %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -13,6 +13,7 @@ from zipfile import BadZipFile
|
|||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
|
from freezegun import freeze_time
|
||||||
from notifications_python_client.errors import HTTPError
|
from notifications_python_client.errors import HTTPError
|
||||||
from notifications_utils.recipients import RecipientCSV
|
from notifications_utils.recipients import RecipientCSV
|
||||||
from notifications_utils.template import (
|
from notifications_utils.template import (
|
||||||
@@ -3783,6 +3784,37 @@ def test_redirects_to_template_if_job_exists_already(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time('2020-03-13 13:00')
|
||||||
|
def test_choose_from_contact_list(
|
||||||
|
mocker,
|
||||||
|
client_request,
|
||||||
|
mock_get_service_template,
|
||||||
|
mock_get_contact_lists,
|
||||||
|
fake_uuid,
|
||||||
|
):
|
||||||
|
page = client_request.get(
|
||||||
|
'main.choose_from_contact_list',
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
template_id=fake_uuid,
|
||||||
|
)
|
||||||
|
assert len(page.select('.file-list-filename-large')) == 2
|
||||||
|
assert normalize_spaces(page.select_one('.file-list-filename-large').text) == (
|
||||||
|
'EmergencyContactList.xls'
|
||||||
|
)
|
||||||
|
assert page.select_one('a.file-list-filename-large')['href'] == url_for(
|
||||||
|
'main.send_from_contact_list',
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
template_id=fake_uuid,
|
||||||
|
contact_list_id=fake_uuid,
|
||||||
|
)
|
||||||
|
assert normalize_spaces(page.select_one('.file-list-hint').text) == (
|
||||||
|
'Uploaded today at 10:59am'
|
||||||
|
)
|
||||||
|
assert normalize_spaces(page.select_one('.big-number-smallest').text) == (
|
||||||
|
'100 email addresses'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_send_from_contact_list(
|
def test_send_from_contact_list(
|
||||||
mocker,
|
mocker,
|
||||||
client_request,
|
client_request,
|
||||||
@@ -3816,7 +3848,7 @@ def test_send_from_contact_list(
|
|||||||
SERVICE_ONE_ID, fake_uuid, bucket='test-contact-list'
|
SERVICE_ONE_ID, fake_uuid, bucket='test-contact-list'
|
||||||
)
|
)
|
||||||
mock_upload.assert_called_once_with(
|
mock_upload.assert_called_once_with(
|
||||||
SERVICE_ONE_ID, 'contents', ANY
|
SERVICE_ONE_ID, {'data': 'contents'}, ANY
|
||||||
)
|
)
|
||||||
mock_set_metadata.assert_called_once_with(
|
mock_set_metadata.assert_called_once_with(
|
||||||
SERVICE_ONE_ID, new_uuid, example_key='example value'
|
SERVICE_ONE_ID, new_uuid, example_key='example value'
|
||||||
|
|||||||
@@ -1864,7 +1864,7 @@ def mock_get_contact_lists(mocker, api_user_active, fake_uuid):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
return mocker.patch(
|
return mocker.patch(
|
||||||
'app.contact_list_api_client.get_contact_lists',
|
'app.models.contact_list.ContactLists.client_method',
|
||||||
side_effect=_get,
|
side_effect=_get,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user