Auto-commit local changes before build (2026-01-04 12:17:21)
This commit is contained in:
parent
985397afa1
commit
843e01e1e6
@ -1 +1 @@
|
||||
v20260104-03-reports-html-view-selection-fix
|
||||
v20260104-04-reports-html-jobs-table-fix
|
||||
|
||||
@ -1096,18 +1096,117 @@ def _export_html_response(report: ReportDefinition, report_id: int, view: str):
|
||||
# - when html_content is not set, pick a sensible default based on scope + view
|
||||
scope = (getattr(report, "customer_scope", None) or "all").strip().lower()
|
||||
if not html_content:
|
||||
if scope == "single" and (view or "summary").strip().lower() == "summary":
|
||||
html_content = "customers"
|
||||
else:
|
||||
# For a single-customer report, the most useful summary is a job list.
|
||||
# For all-customer reports, the summary defaults to performance by customer.
|
||||
html_content = "jobs" if scope == "single" else "customers"
|
||||
|
||||
include_customers = html_content in ("customers", "both")
|
||||
include_jobs = html_content in ("jobs", "both")
|
||||
|
||||
# Snapshot preview table can be requested either explicitly via view=snapshot
|
||||
# or via the report config (include_jobs).
|
||||
# Snapshot preview table can be requested explicitly via view=snapshot.
|
||||
want_snapshot_table = (view or "summary").strip().lower() == "snapshot"
|
||||
|
||||
jobs_table_html = ""
|
||||
if include_jobs and not want_snapshot_table:
|
||||
# Job table (latest snapshot per job/object) for a single-customer report.
|
||||
jobs_rows = []
|
||||
with db.engine.connect() as conn:
|
||||
rows = conn.execute(
|
||||
text(
|
||||
"""
|
||||
SELECT DISTINCT ON (COALESCE(object_name,''), COALESCE(job_name,''), COALESCE(backup_software,''), COALESCE(backup_type,''))
|
||||
COALESCE(object_name,'') AS object_name,
|
||||
COALESCE(customer_name,'') AS customer_name,
|
||||
COALESCE(job_name,'') AS job_name,
|
||||
COALESCE(backup_software,'') AS backup_software,
|
||||
COALESCE(backup_type,'') AS backup_type,
|
||||
run_at,
|
||||
COALESCE(status,'') AS status,
|
||||
missed,
|
||||
override_applied,
|
||||
COALESCE(ticket_number,'') AS ticket_number,
|
||||
COALESCE(remark,'') AS remark
|
||||
FROM report_object_snapshots
|
||||
WHERE report_id = :rid
|
||||
ORDER BY
|
||||
COALESCE(object_name,''),
|
||||
COALESCE(job_name,''),
|
||||
COALESCE(backup_software,''),
|
||||
COALESCE(backup_type,''),
|
||||
run_at DESC NULLS LAST
|
||||
LIMIT 1000
|
||||
"""
|
||||
),
|
||||
{"rid": report_id},
|
||||
).fetchall()
|
||||
|
||||
for r in rows or []:
|
||||
jobs_rows.append(
|
||||
{
|
||||
"object_name": r.object_name or "",
|
||||
"customer_name": r.customer_name or "",
|
||||
"job_name": r.job_name or "",
|
||||
"backup_software": r.backup_software or "",
|
||||
"backup_type": r.backup_type or "",
|
||||
"run_at": r.run_at.isoformat() if r.run_at else "",
|
||||
"status": r.status or "",
|
||||
"missed": bool(r.missed),
|
||||
"override_applied": bool(r.override_applied),
|
||||
"ticket_number": r.ticket_number or "",
|
||||
"remark": (r.remark or "").replace("\r", " ").replace("\n", " ").strip(),
|
||||
}
|
||||
)
|
||||
|
||||
job_row_html = []
|
||||
for j in jobs_rows:
|
||||
job_row_html.append(
|
||||
"<tr>"
|
||||
f"<td>{_esc(j['object_name'])}</td>"
|
||||
f"<td>{_esc(j['job_name'])}</td>"
|
||||
f"<td>{_esc(j['backup_software'])}</td>"
|
||||
f"<td>{_esc(j['backup_type'])}</td>"
|
||||
f"<td class='text-muted small'>{_esc(j['run_at'])}</td>"
|
||||
f"<td>{_esc(j['status'])}</td>"
|
||||
f"<td class='text-end'>{'1' if j['missed'] else '0'}</td>"
|
||||
f"<td class='text-end'>{'1' if j['override_applied'] else '0'}</td>"
|
||||
f"<td>{_esc(j['ticket_number'])}</td>"
|
||||
f"<td>{_esc(j['remark'])}</td>"
|
||||
"</tr>"
|
||||
)
|
||||
|
||||
jobs_table_html = """<div class="row g-3 mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-white">
|
||||
<div class="fw-semibold">Jobs</div>
|
||||
<div class="small-muted">Latest snapshot per job</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Object</th>
|
||||
<th>Job</th>
|
||||
<th>Software</th>
|
||||
<th>Type</th>
|
||||
<th>Last run</th>
|
||||
<th>Status</th>
|
||||
<th class="text-end">Missed</th>
|
||||
<th class="text-end">Override</th>
|
||||
<th>Ticket</th>
|
||||
<th>Remark</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
""" + "\n".join(job_row_html) + """</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>"""
|
||||
|
||||
snapshot_table_html = ""
|
||||
if want_snapshot_table:
|
||||
snap_rows = []
|
||||
@ -1343,6 +1442,8 @@ def _export_html_response(report: ReportDefinition, report_id: int, view: str):
|
||||
|
||||
{perf_table_html}
|
||||
|
||||
{jobs_table_html}
|
||||
|
||||
{snapshot_table_html}
|
||||
|
||||
</div>
|
||||
|
||||
@ -209,6 +209,14 @@
|
||||
- Prevented unintended fallback to Snapshot view when generating HTML reports.
|
||||
- Improved default behavior for single-customer summary reports to ensure a meaningful summary is displayed.
|
||||
|
||||
---
|
||||
|
||||
## v20260104-04-reports-html-jobs-table-fix
|
||||
|
||||
- Fixed HTML report rendering where only charts were shown and no data rows appeared.
|
||||
- Restored the jobs table below the charts in HTML reports for single-customer selections.
|
||||
- Ensured the latest snapshot per job is displayed correctly in the HTML output.
|
||||
|
||||
================================================================================================================================================
|
||||
|
||||
## v0.1.15
|
||||
|
||||
Loading…
Reference in New Issue
Block a user