mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-26 01:04:00 -04:00
Merge pull request #2105 from alphagov/platform-admin-page-for-complaints
Email complaints page for platform admins
This commit is contained in:
@@ -58,6 +58,7 @@ from app.notify_client.org_invite_api_client import OrgInviteApiClient
|
|||||||
from app.notify_client.letter_jobs_client import LetterJobsClient
|
from app.notify_client.letter_jobs_client import LetterJobsClient
|
||||||
from app.notify_client.inbound_number_client import InboundNumberClient
|
from app.notify_client.inbound_number_client import InboundNumberClient
|
||||||
from app.notify_client.billing_api_client import BillingAPIClient
|
from app.notify_client.billing_api_client import BillingAPIClient
|
||||||
|
from app.notify_client.complaint_api_client import ComplaintApiClient
|
||||||
from app.commands import setup_commands
|
from app.commands import setup_commands
|
||||||
from app.utils import get_cdn_domain
|
from app.utils import get_cdn_domain
|
||||||
from app.utils import gmt_timezones
|
from app.utils import gmt_timezones
|
||||||
@@ -84,6 +85,7 @@ zendesk_client = ZendeskClient()
|
|||||||
letter_jobs_client = LetterJobsClient()
|
letter_jobs_client = LetterJobsClient()
|
||||||
inbound_number_client = InboundNumberClient()
|
inbound_number_client = InboundNumberClient()
|
||||||
billing_api_client = BillingAPIClient()
|
billing_api_client = BillingAPIClient()
|
||||||
|
complaint_api_client = ComplaintApiClient()
|
||||||
|
|
||||||
# The current service attached to the request stack.
|
# The current service attached to the request stack.
|
||||||
current_service = LocalProxy(partial(_lookup_req_object, 'service'))
|
current_service = LocalProxy(partial(_lookup_req_object, 'service'))
|
||||||
@@ -128,6 +130,7 @@ def create_app(application):
|
|||||||
letter_jobs_client.init_app(application)
|
letter_jobs_client.init_app(application)
|
||||||
inbound_number_client.init_app(application)
|
inbound_number_client.init_app(application)
|
||||||
billing_api_client.init_app(application)
|
billing_api_client.init_app(application)
|
||||||
|
complaint_api_client.init_app(application)
|
||||||
|
|
||||||
login_manager.init_app(application)
|
login_manager.init_app(application)
|
||||||
login_manager.login_view = 'main.sign_in'
|
login_manager.login_view = 'main.sign_in'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from datetime import datetime
|
|||||||
from flask import render_template, request
|
from flask import render_template, request
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from app import service_api_client
|
from app import complaint_api_client, service_api_client
|
||||||
from app.main import main
|
from app.main import main
|
||||||
from app.main.forms import DateFilterForm
|
from app.main.forms import DateFilterForm
|
||||||
from app.statistics_utils import get_formatted_percentage
|
from app.statistics_utils import get_formatted_percentage
|
||||||
@@ -70,6 +70,18 @@ def platform_admin_services():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/platform-admin/complaints")
|
||||||
|
@login_required
|
||||||
|
@user_is_platform_admin
|
||||||
|
def platform_admin_list_complaints():
|
||||||
|
complaints = complaint_api_client.get_all_complaints()
|
||||||
|
return render_template(
|
||||||
|
'views/platform-admin/complaints.html',
|
||||||
|
complaints=complaints,
|
||||||
|
page_title='All Complaints',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def sum_service_usage(service):
|
def sum_service_usage(service):
|
||||||
total = 0
|
total = 0
|
||||||
for notification_type in service['statistics'].keys():
|
for notification_type in service['statistics'].keys():
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class HeaderNavigation(Navigation):
|
|||||||
'update_email_branding',
|
'update_email_branding',
|
||||||
'view_provider',
|
'view_provider',
|
||||||
'view_providers',
|
'view_providers',
|
||||||
|
'platform_admin_list_complaints',
|
||||||
},
|
},
|
||||||
'sign-in': {
|
'sign-in': {
|
||||||
'sign_in',
|
'sign_in',
|
||||||
@@ -418,6 +419,7 @@ class MainNavigation(Navigation):
|
|||||||
'organisation_settings',
|
'organisation_settings',
|
||||||
'organisations',
|
'organisations',
|
||||||
'platform_admin',
|
'platform_admin',
|
||||||
|
'platform_admin_list_complaints',
|
||||||
'pricing',
|
'pricing',
|
||||||
'privacy',
|
'privacy',
|
||||||
'public_agreement',
|
'public_agreement',
|
||||||
@@ -586,6 +588,7 @@ class OrgNavigation(Navigation):
|
|||||||
'old_using_notify',
|
'old_using_notify',
|
||||||
'organisations',
|
'organisations',
|
||||||
'platform_admin',
|
'platform_admin',
|
||||||
|
'platform_admin_list_complaints',
|
||||||
'pricing',
|
'pricing',
|
||||||
'privacy',
|
'privacy',
|
||||||
'public_agreement',
|
'public_agreement',
|
||||||
|
|||||||
11
app/notify_client/complaint_api_client.py
Normal file
11
app/notify_client/complaint_api_client.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from app.notify_client import NotifyAdminAPIClient
|
||||||
|
|
||||||
|
|
||||||
|
class ComplaintApiClient(NotifyAdminAPIClient):
|
||||||
|
# Fudge assert in the super __init__ so
|
||||||
|
# we can set those variables later.
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("a" * 73, "b")
|
||||||
|
|
||||||
|
def get_all_complaints(self):
|
||||||
|
return self.get('/complaint')
|
||||||
@@ -19,7 +19,8 @@
|
|||||||
('Providers', url_for('main.view_providers')),
|
('Providers', url_for('main.view_providers')),
|
||||||
('Email branding', url_for('main.email_branding')),
|
('Email branding', url_for('main.email_branding')),
|
||||||
('Letter jobs', url_for('main.letter_jobs')),
|
('Letter jobs', url_for('main.letter_jobs')),
|
||||||
('Inbound SMS numbers', url_for('main.inbound_sms_admin'))
|
('Inbound SMS numbers', url_for('main.inbound_sms_admin')),
|
||||||
|
('Email Complaints', url_for('main.platform_admin_list_complaints'))
|
||||||
] %}
|
] %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url }}">
|
<a href="{{ url }}">
|
||||||
|
|||||||
36
app/templates/views/platform-admin/complaints.html
Normal file
36
app/templates/views/platform-admin/complaints.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{% extends "views/platform-admin/_base_template.html" %}
|
||||||
|
{% from "components/page-footer.html" import page_footer %}
|
||||||
|
{% from "components/table.html" import list_table, field, text_field, link_field, right_aligned_field_heading, hidden_field_heading %}
|
||||||
|
|
||||||
|
{% block per_page_title %}
|
||||||
|
{{ page_title|capitalize }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block platform_admin_content %}
|
||||||
|
|
||||||
|
<h1 class="heading-large">
|
||||||
|
Email complaints
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
|
{% call(item, row_number) list_table(
|
||||||
|
complaints,
|
||||||
|
caption="Complaints",
|
||||||
|
caption_visible=False,
|
||||||
|
empty_message='No complaints',
|
||||||
|
field_headings=['Notification Id', 'Service', 'Complaint type', 'Complaint Date'],
|
||||||
|
field_headings_visible=True
|
||||||
|
) %}
|
||||||
|
|
||||||
|
{{ link_field(item.notification_id, url_for('main.view_notification', service_id=item.service_id, notification_id=item.notification_id)) }}
|
||||||
|
|
||||||
|
{{ link_field(item.service_name, url_for('main.service_dashboard', service_id=item.service_id)) }}
|
||||||
|
|
||||||
|
{{ text_field(item.complaint_type) }}
|
||||||
|
|
||||||
|
{{ text_field(item.complaint_date|format_datetime_short) }}
|
||||||
|
|
||||||
|
{% endcall %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import uuid
|
||||||
from unittest.mock import ANY
|
from unittest.mock import ANY
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -637,3 +638,32 @@ def test_sum_service_usage_with_zeros(fake_uuid):
|
|||||||
sms_failed=0
|
sms_failed=0
|
||||||
)
|
)
|
||||||
assert sum_service_usage(service) == 0
|
assert sum_service_usage(service) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_platform_admin_list_complaints(
|
||||||
|
client,
|
||||||
|
platform_admin_user,
|
||||||
|
mocker
|
||||||
|
):
|
||||||
|
mock_get_user(mocker, user=platform_admin_user)
|
||||||
|
client.login(platform_admin_user)
|
||||||
|
complaint = {
|
||||||
|
'id': str(uuid.uuid4()),
|
||||||
|
'notification_id': str(uuid.uuid4()),
|
||||||
|
'service_id': str(uuid.uuid4()),
|
||||||
|
'service_name': 'Sample service',
|
||||||
|
'ses_feedback_id': 'Some ses id',
|
||||||
|
'complaint_type': 'abuse',
|
||||||
|
'complaint_date': '2018-06-05T13:50:30.012354',
|
||||||
|
'created_at': '2018-06-05T13:50:30.012354',
|
||||||
|
}
|
||||||
|
mock = mocker.patch('app.complaint_api_client.get_all_complaints',
|
||||||
|
return_value=[complaint])
|
||||||
|
|
||||||
|
client.login(platform_admin_user)
|
||||||
|
response = client.get(url_for('main.platform_admin_list_complaints'))
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
resp_data = response.get_data(as_text=True)
|
||||||
|
assert 'Email complaints' in resp_data
|
||||||
|
assert mock.called
|
||||||
|
|||||||
10
tests/app/notify_client/test_compliant_client.py
Normal file
10
tests/app/notify_client/test_compliant_client.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from app import ComplaintApiClient
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_all_complaints(mocker):
|
||||||
|
client = ComplaintApiClient()
|
||||||
|
|
||||||
|
mock = mocker.patch('app.notify_client.complaint_api_client.ComplaintApiClient.get')
|
||||||
|
|
||||||
|
client.get_all_complaints()
|
||||||
|
mock.assert_called_once_with('/complaint')
|
||||||
Reference in New Issue
Block a user