Merge remote-tracking branch 'origin/main' into 1169-display-confirmation-summary-on-the-preview-page

This commit is contained in:
Beverly Nguyen
2024-02-23 10:05:53 -08:00
9 changed files with 279 additions and 237 deletions

View File

@@ -381,28 +381,29 @@ td.table-empty-message {
}
.job-table {
.usa-table {
thead th.file-name {
width: 25%;
}
thead th.template {
width: 20%;
}
thead th.time-sent {
width: 30%;
}
thead th.sender {
width: 15%;
}
thead th.\#-of-recipients {
width: 5%;
}
thead th.report {
width: 5%;
}
th {
padding: 0.5rem 0.5rem;
}
width: 100%;
border-collapse: collapse;
td.file-name {
width: 25%;
overflow-wrap: anywhere;
}
td.template {
width: 20%;
}
td.time-sent {
width: 20%;
}
td.sender {
width: 15%;
}
td.count-of-recipients {
width: 5%;
}
td.report {
width: 5%;
}
th {
padding: 0.5rem 0.5rem;
}
}

View File

@@ -1,4 +1,5 @@
import calendar
from collections import defaultdict
from datetime import datetime
from functools import partial
from itertools import groupby
@@ -47,31 +48,40 @@ def service_dashboard(service_id):
if not current_user.has_permissions("view_activity"):
return redirect(url_for("main.choose_template", service_id=service_id))
notifications = notification_api_client.get_notifications_for_service(
service_id=service_id,
job_response = job_api_client.get_jobs(service_id)["data"]
notifications_response = notification_api_client.get_notifications_for_service(
service_id
)["notifications"]
job_response = job_api_client.get_jobs(service_id)
service_data_retention_days = 7
jobs = [
aggregate_notifications_by_job = defaultdict(list)
for notification in notifications_response:
job_id = notification.get("job", {}).get("id", None)
if job_id:
aggregate_notifications_by_job[job_id].append(notification)
job_and_notifications = [
{
"job_id": job["id"],
"time_left": get_time_left(job["created_at"]),
"download_link": url_for(
".view_job_csv", service_id=current_service.id, job_id=job["id"]
),
"view_job_link": url_for(
".view_job", service_id=current_service.id, job_id=job["id"]
),
"created_at": job["created_at"],
"notification_count": job["notification_count"],
"created_by": job["created_by"],
"notifications": aggregate_notifications_by_job.get(job["id"], []),
}
for job in job_response["data"]
for job in job_response
]
return render_template(
"views/dashboard/dashboard.html",
updates_url=url_for(".service_dashboard_updates", service_id=service_id),
partials=get_dashboard_partials(service_id),
notifications=notifications,
jobs=jobs,
job_and_notifications=job_and_notifications,
service_data_retention_days=service_data_retention_days,
)

View File

@@ -28,66 +28,70 @@
{{ ajax_block(partials, updates_url, 'totals') }}
{{ ajax_block(partials, updates_url, 'template-statistics') }}
<h2 class="margin-top-4 margin-bottom-1">Recent Batches</h2>
<div class='job-table'>
<table class="usa-table usa-table--borderless width-full">
<div>
<table class="usa-table usa-table--borderless job-table">
<thead class="table-field-headings">
<tr>
<th scope="col" class="table-field-heading-first file-name">
<th scope="col" class="table-field-heading-first">
<span>File name</span>
</th>
<th scope="col" class="table-field-heading template">
<th scope="col" class="table-field-heading">
<span>Template</span>
</th>
<th scope="col" class="table-field-heading time-sent">
<th scope="col" class="table-field-heading">
<span>Time sent</span>
</th>
<th scope="col" class="table-field-heading sender">
<th scope="col" class="table-field-heading">
<span>Sender</span>
</th>
<th scope="col" class="table-field-heading #-of-recipients">
<th scope="col" class="table-field-heading">
<span># of Recipients</span>
</th>
<th scope="col" class="table-field-heading report">
<th scope="col" class="table-field-heading">
<span>Report</span>
</th>
</tr>
</thead>
<tbody>
{% for notification in notifications[:5] %}
{% if notification %}
<tr class="table-row" id="{{ notification.job.id }}">
<th class="table-field">
{{ notification.job.original_file_name if notification.job.original_file_name else 'Manually entered number'}}
<br>
<a class="usa-link file-list-filename" href="/services/{{ notification.service }}/jobs/{{ notification.job.id }}">View Batch</a>
</th>
<th class="table-field">
{{ notification.template.name }}
</th>
<th class="table-field">
{{ notification.created_at | format_datetime_short_america }}
</th>
<th class="table-field">
{{ notification.created_by.name }}
</th>
{% set job_available = jobs|selectattr('job_id', 'equalto', notification.job.id)|first %}
<th class="table-field">
{{ job_available.notification_count if job_available else ''}}
</th>
<th class="table-field">
{% if job_available and job_available.time_left != "Data no longer available" %}
<a class="usa-link file-list-filename" href="{{ job_available.download_link }}">
{{ "Download" if job_available.job_id else '' }}</a>
<span class="usa-hint">{{ job_available.time_left }}</span>
{% elif job_available %}
<span>{{ job_available.time_left }}</span>
{% endif %}
</th>
</tr>
{% endif %}
{% endfor %}
{% if job_and_notifications %}
{% for job in job_and_notifications[:5] %}
{% if job.job_id and job.notifications %}
{% set notification = job.notifications[0] %}
<tr class="table-row" id="{{ job.job_id }}">
<td class="table-field file-name">
{{ notification.job.original_file_name if notification.job.original_file_name else 'Manually entered number'}}
<br>
<a class="usa-link file-list-filename" href="{{ job.view_job_link }}">View Batch</a>
</td>
<td class="table-field template">
{{ notification.template.name }}
</td>
<td class="table-field time-sent">
{{ job.created_at | format_datetime_short_america }}
</td>
<td class="table-field sender">
{{ notification.created_by.name }}
</td>
<td class="table-field count-of-recipients">
{{ job.notification_count}}
</td>
<td class="table-field report">
{% if notification and job.time_left != "Data no longer available" %}
<a class="usa-link file-list-filename" href="{{ job.download_link }}">Download</a>
<span class="usa-hint">{{ job.time_left }}</span>
{% elif job %}
<span>{{ job.time_left }}</span>
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
{% else %}
<tr class="table-row">
<td class="table-empty-message" colspan="10">No batched job messages found &thinsp;(messages are kept for {{ service_data_retention_days }} days).</td>
</tr>
{% endif %}
</tbody>
</table>
</div>

View File

@@ -29,10 +29,9 @@
{% else %}
<h1 class="font-body-2xl margin-bottom-3">Sign in</h1>
{% if login_gov_enabled %}
<p>
Test login.gov authentication:
<a class="usa-link" href="{{ initial_signin_url }}">Login.gov</a>.
<a class="usa-link" href="{{ initial_signin_url }}">Sign in with Login.gov</a>
</p>
<h4 class="margin-bottom-3">Or:</h4>
{% endif %}
{% endif %}

View File

@@ -71,6 +71,7 @@ def generate_notifications_csv(**kwargs):
if "page" not in kwargs:
kwargs["page"] = 1
# This generates the "batch" csv report
if kwargs.get("job_id"):
original_file_contents = s3download(kwargs["service_id"], kwargs["job_id"])
original_upload = RecipientCSV(
@@ -79,6 +80,7 @@ def generate_notifications_csv(**kwargs):
)
original_column_headers = original_upload.column_headers
fieldnames = [
"Phone Number",
"Template",
"Sent by",
"Batch File",
@@ -87,12 +89,13 @@ def generate_notifications_csv(**kwargs):
"Time",
]
for header in original_column_headers:
fieldnames.append(header)
if header.lower() != "phone number":
fieldnames.append(header)
else:
# TODO This is deprecated because everything should be a job now, is it ever invoked?
# This generates the "full" csv report
fieldnames = [
"Recipient",
"Phone Number",
"Template",
"Sent by",
"Batch File",
@@ -100,7 +103,6 @@ def generate_notifications_csv(**kwargs):
"Status",
"Time",
]
current_app.logger.warning("Invoking deprecated report format")
yield ",".join(fieldnames) + "\n"
@@ -113,9 +115,9 @@ def generate_notifications_csv(**kwargs):
notification["created_at"]
)
current_app.logger.info(f"\n\n{notification}")
if kwargs.get("job_id"):
values = [
notification["recipient"],
notification["template_name"],
notification["created_by_name"],
notification["job_name"],
@@ -124,12 +126,14 @@ def generate_notifications_csv(**kwargs):
preferred_tz_created_at,
]
for header in original_column_headers:
values.append(
original_upload[notification["row_number"] - 1].get(header).data
)
if header.lower() != "phone number":
values.append(
original_upload[notification["row_number"] - 1]
.get(header)
.data
)
else:
# TODO This is deprecated, should not be invoked. See above
values = [
notification["recipient"],
notification["template_name"],