Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions app/main/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1564,20 +1564,20 @@ class SearchUsersForm(StripWhitespaceForm):
search = UsaSearchField("Search by name or email address")


class SearchNotificationsForm(StripWhitespaceForm):
to = UsaSearchField()

labels = {
"email": "Search by email address",
"sms": "Search by phone number",
}

def __init__(self, message_type, *args, **kwargs):
super().__init__(*args, **kwargs)
self.to.label.text = self.labels.get(
message_type,
"Search by phone number or email address",
)
# class SearchNotificationsForm(StripWhitespaceForm):
# to = UsaSearchField()
#
# labels = {
# "email": "Search by email address",
# "sms": "Search by phone number",
# }
#
# def __init__(self, message_type, *args, **kwargs):
# super().__init__(*args, **kwargs)
# self.to.label.text = self.labels.get(
# message_type,
# "Search by phone number or email address",
# )


class SearchTemplatesForm(StripWhitespaceForm):
Expand Down
255 changes: 2 additions & 253 deletions app/main/views/jobs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from functools import partial

from flask import (
Response,
Expand All @@ -12,27 +11,15 @@
stream_with_context,
url_for,
)
from flask_login import current_user
from markupsafe import Markup

from app import (
current_service,
format_datetime_table,
notification_api_client,
service_api_client,
)
from app.enums import NotificationStatus, NotificationType, ServicePermission
from app import current_service, format_datetime_table
from app.enums import ServicePermission
from app.formatters import get_time_left, message_count_noun
from app.main import main
from app.main.forms import SearchNotificationsForm
from app.models.job import Job
from app.utils import parse_filter_args, set_status_filters
from app.utils.csv import generate_notifications_csv
from app.utils.pagination import (
generate_next_dict,
generate_previous_dict,
get_page_from_request,
)
from app.utils.user import user_has_permissions
from notifications_python_client.errors import HTTPError
from notifications_utils.template import EmailPreviewTemplate, SMSBodyPreviewTemplate
Expand Down Expand Up @@ -197,244 +184,6 @@ def view_job_notifications_table(service_id, job_id):
)


@main.route("/services/<uuid:service_id>/notifications", methods=["GET", "POST"])
@main.route(
"/services/<uuid:service_id>/notifications/<template_type:message_type>",
methods=["GET", "POST"],
)
@user_has_permissions()
def view_notifications(service_id, message_type=None):
return render_template(
"views/notifications.html",
partials=get_notifications(service_id, message_type),
message_type=message_type,
status=request.args.get("status") or "sending,delivered,failed",
page=request.args.get("page", 1),
search_form=SearchNotificationsForm(
message_type=message_type,
to=request.form.get("to"),
),
things_you_can_search_by={
"email": ["email address"],
"sms": ["phone number"],
None: ["recipient"],
}.get(message_type)
+ {
True: ["reference"],
False: [],
}.get(bool(current_service.api_keys)),
download_link_one_day=url_for(
".download_notifications_csv",
service_id=current_service.id,
message_type=message_type,
status=request.args.get("status"),
number_of_days="one_day",
),
download_link_today=url_for(
".download_notifications_csv",
service_id=current_service.id,
message_type=message_type,
status=request.args.get("status"),
number_of_days="today",
),
download_link_three_day=url_for(
".download_notifications_csv",
service_id=current_service.id,
message_type=message_type,
status=request.args.get("status"),
number_of_days="three_day",
),
download_link_five_day=url_for(
".download_notifications_csv",
service_id=current_service.id,
message_type=message_type,
status=request.args.get("status"),
number_of_days="five_day",
),
download_link_seven_day=url_for(
".download_notifications_csv",
service_id=current_service.id,
message_type=message_type,
status=request.args.get("status"),
number_of_days="seven_day",
),
)


@main.route("/services/<uuid:service_id>/notifications.json", methods=["GET", "POST"])
@main.route(
"/services/<uuid:service_id>/notifications/<template_type:message_type>.json",
methods=["GET", "POST"],
)
@user_has_permissions()
def get_notifications_as_json(service_id, message_type=None):
return jsonify(
get_notifications(
service_id, message_type, status_override=request.args.get("status")
)
)


@main.route(
"/services/<uuid:service_id>/notifications.csv", endpoint="view_notifications_csv"
)
@main.route(
"/services/<uuid:service_id>/notifications/<template_type:message_type>.csv",
endpoint="view_notifications_csv",
)
@user_has_permissions()
def get_notifications(service_id, message_type, status_override=None): # noqa
# TODO get the api to return count of pages as well.
page = get_page_from_request()
if page is None:
abort(404, "Invalid page argument ({}).".format(request.args.get("page")))
filter_args = parse_filter_args(request.args)
filter_args["status"] = set_status_filters(filter_args)
service_data_retention_days = None
search_term = request.form.get("to", "")
if message_type is not None:
service_data_retention_days = current_service.get_days_of_retention(
message_type, number_of_days="seven_day"
)

if request.path.endswith("csv") and current_user.has_permissions(
ServicePermission.VIEW_ACTIVITY
):
return Response(
generate_notifications_csv(
service_id=service_id,
page=page,
page_size=5000,
template_type=[message_type],
status=filter_args.get("status"),
limit_days=service_data_retention_days,
),
mimetype="text/csv",
headers={"Content-Disposition": 'inline; filename="notifications.csv"'},
)
notifications = notification_api_client.get_notifications_for_service(
service_id=service_id,
page=page,
template_type=[message_type] if message_type else [],
status=filter_args.get("status"),
limit_days=service_data_retention_days,
to=search_term,
)

notifications_list = notifications.get("notifications", [])

url_args = {"message_type": message_type, "status": request.args.get("status")}
prev_page = None
if "links" in notifications and notifications["links"].get("prev", None):
prev_page = generate_previous_dict(
"main.view_notifications", service_id, page, url_args=url_args
)
next_page = None

total_items = notifications.get("total", 0)
page_size = notifications.get("page_size", 50)
total_pages = (total_items + page_size - 1) // page_size
if (
"links" in notifications
and notifications["links"].get("next", None)
and total_items > 50
and page < total_pages
):
next_page = generate_next_dict(
"main.view_notifications", service_id, page, url_args
)

if message_type:
download_link = url_for(
".view_notifications_csv",
service_id=current_service.id,
message_type=message_type,
status=request.args.get("status"),
)
else:
download_link = None
return {
"service_data_retention_days": service_data_retention_days,
"counts": render_template(
"views/activity/counts.html",
status=request.args.get("status"),
status_filters=get_status_filters(
current_service,
message_type,
service_api_client.get_service_statistics(
service_id, limit_days=service_data_retention_days
),
),
),
"notifications": render_template(
"views/activity/notifications.html",
notifications=list(
add_preview_of_content_to_notifications(notifications_list)
),
page=page,
limit_days=service_data_retention_days,
prev_page=prev_page,
next_page=next_page,
show_pagination=(not search_term),
status=request.args.get("status"),
message_type=message_type,
download_link=download_link,
single_notification_url=partial(
url_for,
".view_notification",
service_id=current_service.id,
),
),
}


def get_status_filters(service, message_type, statistics):
message_types = (
[message_type]
if message_type
else [NotificationType.EMAIL, NotificationType.SMS]
)

stats = {
NotificationStatus.REQUESTED: sum(
statistics[mt].get(NotificationStatus.REQUESTED, 0) for mt in message_types
),
NotificationStatus.DELIVERED: sum(
statistics[mt].get(NotificationStatus.DELIVERED, 0) for mt in message_types
),
NotificationStatus.FAILED: sum(
statistics[mt].get(NotificationStatus.FAILED, 0) for mt in message_types
),
}

stats[NotificationStatus.PENDING] = (
stats[NotificationStatus.REQUESTED]
- stats[NotificationStatus.DELIVERED]
- stats[NotificationStatus.FAILED]
)

filters = [
(NotificationStatus.REQUESTED, "total", "sending,delivered,failed"),
(NotificationStatus.PENDING, "pending", "sending,pending"),
(NotificationStatus.DELIVERED, "delivered", "delivered"),
(NotificationStatus.FAILED, "failed", "failed"),
]
return [
(
label,
option,
url_for(
".view_notifications",
service_id=service.id,
message_type=message_type,
status=option,
),
stats.get(key),
)
for key, label, option in filters
]


def _get_job_counts(job):
job_type = job.template_type
return [
Expand Down
14 changes: 5 additions & 9 deletions app/main/views/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ def view_notification(service_id, notification_id, error_message=None):
job = None

if get_help_argument() or request.args.get("help") == "0":
# help=0 is set when youve just sent a notification. We
# only want to show the back link when youve navigated to a
# notification, not when youve just sent it.
# help=0 is set when you've just sent a notification. We
# only want to show the back link when you've navigated to a
# notification, not when you've just sent it.
back_link = None
elif request.args.get("from_job"):
back_link = url_for(
Expand All @@ -74,10 +74,8 @@ def view_notification(service_id, notification_id, error_message=None):
)
else:
back_link = url_for(
"main.view_notifications",
"main.all_jobs_activity",
service_id=current_service.id,
message_type=template.template_type,
status="sending,delivered,failed",
)

return render_template(
Expand Down Expand Up @@ -198,10 +196,8 @@ def download_notifications_csv(service_id):
)
return redirect(
url_for(
"main.view_notifications",
"main.all_jobs_activity",
service_id=service_id,
message_type=filter_args["message_type"][0],
status="sending,delivered,failed",
)
)
return Response(
Expand Down
3 changes: 0 additions & 3 deletions app/navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ class HeaderNavigation(Navigation):
"service_dashboard",
"template_usage",
"view_notification",
"view_notifications",
"action_blocked",
"add_service_template",
"check_messages",
Expand Down Expand Up @@ -160,7 +159,6 @@ class MainNavigation(Navigation):
"service_dashboard",
"template_usage",
"view_notification",
"view_notifications",
},
"templates": {
"action_blocked",
Expand Down Expand Up @@ -268,7 +266,6 @@ class CaseworkNavigation(Navigation):
"send_one_off_to_myself",
},
"sent-messages": {
"view_notifications",
"view_notification",
},
"uploads": {
Expand Down
3 changes: 0 additions & 3 deletions app/templates/components/main_nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('dashboard') }}" href="{{ url_for('.service_dashboard', service_id=current_service.id) }}">Dashboard</a></li>
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('activity') }}" href="{{ url_for('.all_jobs_activity', service_id=current_service.id) }}">Activity</a></li>
{% endif %}
{% if not current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) %}
<li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li>
{% endif %}
{% elif current_user.has_permissions(allow_org_user=True) %}
<li class="usa-sidenav__item"><a class="usa-link{{ main_navigation.is_selected('usage') }}" href="{{ url_for('.usage', service_id=current_service.id) }}">Usage</a></li>
<li class="usa-sidenav__item"><a class="usa-link{{ main_navigation.is_selected('team-members') }}" href="{{ url_for('.manage_users', service_id=current_service.id) }}">Team members</a></li>
Expand Down
Loading