Merge pull request #2712 from GSA/2709-bug-sorting-error-on-activity-page

Improved job/activity list ordering and display
This commit is contained in:
ccostino
2025-06-27 15:55:55 -04:00
committed by GitHub
5 changed files with 48 additions and 52 deletions

View File

@@ -34,6 +34,7 @@ from app.config import configs
from app.extensions import redis_client
from app.formatters import (
convert_markdown_template,
convert_time_unixtimestamp,
convert_to_boolean,
format_auth_type,
format_billions,
@@ -672,6 +673,7 @@ def add_template_filters(application):
format_thousands,
id_safe,
convert_to_boolean,
convert_time_unixtimestamp,
format_list_items,
iteration_count,
recipient_count,

View File

@@ -1,7 +1,7 @@
from flask import abort, render_template, request, url_for
from app import current_service, job_api_client
from app.formatters import convert_time_unixtimestamp, get_time_left
from app.formatters import get_time_left
from app.main import main
from app.utils.pagination import (
generate_next_dict,
@@ -78,47 +78,43 @@ def handle_pagination(jobs, service_id, page):
return prev_page, next_page, pagination
JOB_STATUS_DELIVERED = "delivered"
JOB_STATUS_FAILED = "failed"
def get_job_statistics(job, status):
statistics = job.get("statistics", [])
for stat in statistics:
if stat.get("status") == status:
return stat.get("count")
return None
def create_job_dict_entry(job):
job_id = job.get("id")
can_download = get_time_left(job.get("created_at")) != "Data no longer available"
activity_time = job.get("processing_started") or job.get("created_at")
return {
"job_id": job_id,
"can_download": can_download,
"download_link": (
url_for(".view_job_csv", service_id=current_service.id, job_id=job_id)
if can_download
else None
),
"view_job_link": url_for(
".view_job", service_id=current_service.id, job_id=job_id
),
"activity_time": activity_time,
"created_by": job.get("created_by"),
"template_name": job.get("template_name"),
"delivered_count": get_job_statistics(job, JOB_STATUS_DELIVERED),
"failed_count": get_job_statistics(job, JOB_STATUS_FAILED),
}
def generate_job_dict(jobs):
return [
{
"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"],
"time_sent_data_value": convert_time_unixtimestamp(
job["processing_finished"]
if job["processing_finished"]
else (
job["processing_started"]
if job["processing_started"]
else job["created_at"]
)
),
"processing_finished": job["processing_finished"],
"processing_started": job["processing_started"],
"created_by": job["created_by"],
"template_name": job["template_name"],
"delivered_count": next(
(
stat["count"]
for stat in job.get("statistics", [])
if stat["status"] == "delivered"
),
None,
),
"failed_count": next(
(
stat["count"]
for stat in job.get("statistics", [])
if stat["status"] == "failed"
),
None,
),
}
for job in jobs["data"]
]
if not jobs or not jobs.get("data"):
return []
return [create_job_dict_entry(job) for job in jobs["data"]]

View File

@@ -43,10 +43,9 @@ def service_dashboard(service_id):
service_data_retention_days = 7
active_jobs = [job for job in job_response if job["job_status"] != "cancelled"]
sorted_jobs = sorted(active_jobs, key=lambda job: job["created_at"], reverse=True)
job_lists = [
{**job_dict, "finished_processing": job_is_finished(job_dict)}
for job_dict in sorted_jobs
for job_dict in active_jobs
]
total_messages = service_api_client.get_service_message_ratio(service_id)

View File

@@ -70,7 +70,7 @@
<span>Template</span>
</th>
<th data-sortable scope="col" role="columnheader" class="table-field-heading">
<span>Time sent</span>
<span>Started</span>
</th>
<th data-sortable scope="col" role="columnheader" class="table-field-heading">
<span>Sender</span>
@@ -96,13 +96,12 @@
</a>
</td>
<td class="table-field template">{{ job.template_name }}</td>
<td data-sort-value="{{job.time_sent_data_value}}" class="table-field time-sent">
{{ (job.processing_finished if job.processing_finished else job.processing_started
if job.processing_started else job.created_at)|format_datetime_table }}
<td data-sort-value="{{ job.activity_time | convert_time_unixtimestamp }}" class="table-field time-sent">
{{ job.activity_time|format_datetime_table }}
</td>
<td class="table-field sender">{{ job.created_by.name }}</td>
<td class="table-field report">
{% if job.time_left != "Data no longer available" %}
{% if job.can_download %}
<a href="{{ job.download_link }}">
<img src="{{ url_for('static', filename='img/material-icons/file_download.svg') }}" alt="">
<span class="usa-sr-only">Download report link</span>

View File

@@ -69,7 +69,7 @@ def test_all_activity(
expected_headers = [
"Job ID#",
"Template",
"Time sent",
"Started",
"Sender",
"Report",
"Delivered",