Auto-commit local changes before build (2026-03-20 11:04:11)
This commit is contained in:
parent
af84039daf
commit
44214cc2c6
@ -184,6 +184,54 @@ def inbox_message_detail(message_id: int):
|
||||
for obj in MailObject.query.filter_by(mail_message_id=msg.id).order_by(MailObject.object_name.asc()).all()
|
||||
]
|
||||
|
||||
# Optional run_id: if provided and the run is a Cloud Connect run, return
|
||||
# per-run objects (from run_object_links) and a structured CC summary instead
|
||||
# of the raw MailObject list which contains all tenants from the shared report email.
|
||||
cloud_connect_summary = None
|
||||
run_id_param = request.args.get("run_id", type=int)
|
||||
if run_id_param:
|
||||
try:
|
||||
from ..models import JobRun, CloudConnectAccount
|
||||
from ..database import db
|
||||
from sqlalchemy import text as _sql_text
|
||||
_run = JobRun.query.get(run_id_param)
|
||||
if _run and getattr(_run, "source_type", None) == "cloud_connect" and _run.job_id:
|
||||
_cc_acc = CloudConnectAccount.query.filter_by(job_id=_run.job_id).first()
|
||||
if _cc_acc:
|
||||
cloud_connect_summary = {
|
||||
"user": _cc_acc.user or "",
|
||||
"section": _cc_acc.section or "",
|
||||
"repo_name": _cc_acc.repo_name or "",
|
||||
"repo_type": _cc_acc.repo_type or "",
|
||||
"used_space": _cc_acc.used_space or "",
|
||||
"total_quota": _cc_acc.total_quota or "",
|
||||
"free_space": _cc_acc.free_space or "",
|
||||
"last_active": _cc_acc.last_active_raw or "",
|
||||
"status": _cc_acc.last_status or "",
|
||||
}
|
||||
# Replace MailObject list with per-run objects from run_object_links
|
||||
cc_rows = db.session.execute(
|
||||
_sql_text("""
|
||||
SELECT co.object_name AS name, rol.status, rol.error_message
|
||||
FROM run_object_links rol
|
||||
JOIN customer_objects co ON co.id = rol.customer_object_id
|
||||
WHERE rol.run_id = :run_id
|
||||
ORDER BY co.object_name ASC
|
||||
"""),
|
||||
{"run_id": run_id_param},
|
||||
).mappings().all()
|
||||
objects = [
|
||||
{
|
||||
"name": r["name"] or "",
|
||||
"type": "",
|
||||
"status": r["status"] or "",
|
||||
"error_message": r["error_message"] or "",
|
||||
}
|
||||
for r in cc_rows
|
||||
]
|
||||
except Exception:
|
||||
pass # keep MailObject objects as fallback
|
||||
|
||||
# VSPC multi-company emails (e.g. "Active alarms summary") may not store parsed objects yet.
|
||||
# Extract company names from the stored body so the UI can offer a dedicated mapping workflow.
|
||||
vspc_companies: list[str] = []
|
||||
@ -227,6 +275,7 @@ def inbox_message_detail(message_id: int):
|
||||
"meta": meta,
|
||||
"body_html": body_html,
|
||||
"objects": objects,
|
||||
"cloud_connect_summary": cloud_connect_summary,
|
||||
"vspc_companies": vspc_companies,
|
||||
"vspc_company_defaults": vspc_company_defaults,
|
||||
})
|
||||
|
||||
@ -258,8 +258,36 @@
|
||||
<h6 class="mb-1">Details</h6>
|
||||
<div id="run_msg_overall_message" class="border rounded p-2" style="white-space: pre-wrap; max-height: 20vh; overflow: auto;"></div>
|
||||
</div>
|
||||
<div class="border rounded p-2 p-0" style="overflow:hidden;">
|
||||
<iframe id="run_msg_body_container_iframe" class="w-100" style="height:55vh; border:0; background:transparent;" sandbox="allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"></iframe>
|
||||
|
||||
<!-- Cloud Connect summary panel (shown instead of raw email for CC runs) -->
|
||||
<div id="jdm_cc_summary_panel" class="mb-3" style="display:none;">
|
||||
<h6>Cloud Connect</h6>
|
||||
<dl class="row mb-0 dl-compact">
|
||||
<dt class="col-4">User</dt> <dd class="col-8" id="jdm_cc_user"></dd>
|
||||
<dt class="col-4">Section</dt> <dd class="col-8" id="jdm_cc_section"></dd>
|
||||
<dt class="col-4">Repository</dt> <dd class="col-8" id="jdm_cc_repo"></dd>
|
||||
<dt class="col-4">Used / Quota</dt><dd class="col-8" id="jdm_cc_used"></dd>
|
||||
<dt class="col-4">Free</dt> <dd class="col-8" id="jdm_cc_free"></dd>
|
||||
<dt class="col-4">Last active</dt> <dd class="col-8" id="jdm_cc_last_active"></dd>
|
||||
<dt class="col-4">Status</dt> <dd class="col-8" id="jdm_cc_status"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center gap-2 mb-1">
|
||||
<h6 class="mb-0" id="jdm_mail_heading">Mail</h6>
|
||||
<a href="#" class="small text-muted" id="jdm_mail_toggle" style="display:none;"
|
||||
onclick="(function(){
|
||||
var b=document.getElementById('jdm_mail_iframe_body');
|
||||
var lnk=document.getElementById('jdm_mail_toggle');
|
||||
var collapsed=b.style.display==='none';
|
||||
b.style.display=collapsed?'':'none';
|
||||
lnk.textContent=collapsed?'hide':'show';
|
||||
})();return false;">show</a>
|
||||
</div>
|
||||
<div id="jdm_mail_iframe_body" class="border rounded p-0" style="overflow:hidden;">
|
||||
<iframe id="run_msg_body_container_iframe" class="w-100" style="height:55vh; border:0; background:transparent;" sandbox="allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
@ -665,7 +693,9 @@ function renderObjects(objects) {
|
||||
if (!messageId) return;
|
||||
currentRunId = runId ? parseInt(runId, 10) : null;
|
||||
|
||||
fetch("{{ url_for('main.inbox_message_detail', message_id=0) }}".replace("0", messageId))
|
||||
var detailUrl = "{{ url_for('main.inbox_message_detail', message_id=0) }}".replace("0", messageId);
|
||||
if (runId) detailUrl += "?run_id=" + encodeURIComponent(runId);
|
||||
fetch(detailUrl)
|
||||
.then(function (resp) {
|
||||
if (!resp.ok) throw new Error("Failed to load message details");
|
||||
return resp.json();
|
||||
@ -727,8 +757,33 @@ function renderObjects(objects) {
|
||||
}
|
||||
}
|
||||
|
||||
var bodyFrame = document.getElementById("run_msg_body_container_iframe");
|
||||
if (bodyFrame) bodyFrame.srcdoc = wrapMailHtml(data.body_html || "");
|
||||
var ccPanel = document.getElementById("jdm_cc_summary_panel");
|
||||
var mailHeading = document.getElementById("jdm_mail_heading");
|
||||
var mailToggle = document.getElementById("jdm_mail_toggle");
|
||||
var mailBody = document.getElementById("jdm_mail_iframe_body");
|
||||
var bodyFrame = document.getElementById("run_msg_body_container_iframe");
|
||||
|
||||
if (data.cloud_connect_summary) {
|
||||
var s = data.cloud_connect_summary;
|
||||
document.getElementById("jdm_cc_user").textContent = s.user || "";
|
||||
document.getElementById("jdm_cc_section").textContent = s.section || "";
|
||||
document.getElementById("jdm_cc_repo").textContent = s.repo_name + (s.repo_type ? " (" + s.repo_type + ")" : "");
|
||||
document.getElementById("jdm_cc_used").textContent = (s.used_space || "—") + " / " + (s.total_quota || "—");
|
||||
document.getElementById("jdm_cc_free").textContent = s.free_space || "—";
|
||||
document.getElementById("jdm_cc_last_active").textContent = s.last_active || "—";
|
||||
document.getElementById("jdm_cc_status").textContent = s.status || "—";
|
||||
if (ccPanel) ccPanel.style.display = "";
|
||||
if (mailHeading) mailHeading.textContent = "Source report email";
|
||||
if (mailToggle) { mailToggle.style.display = ""; mailToggle.textContent = "show"; }
|
||||
if (mailBody) mailBody.style.display = "none";
|
||||
if (bodyFrame) bodyFrame.srcdoc = wrapMailHtml(data.body_html || "");
|
||||
} else {
|
||||
if (ccPanel) ccPanel.style.display = "none";
|
||||
if (mailHeading) mailHeading.textContent = "Mail";
|
||||
if (mailToggle) mailToggle.style.display = "none";
|
||||
if (mailBody) mailBody.style.display = "";
|
||||
if (bodyFrame) bodyFrame.srcdoc = wrapMailHtml(data.body_html || "");
|
||||
}
|
||||
|
||||
renderObjects(data.objects || []);
|
||||
|
||||
|
||||
@ -5,6 +5,10 @@ This file documents all changes made to this project via Claude Code.
|
||||
## [2026-03-20]
|
||||
|
||||
### Fixed
|
||||
- Cloud Connect runs in job detail page popup now show a structured CC summary instead of the raw report email with all tenants:
|
||||
- `routes_inbox.py` (`inbox_message_detail`): accepts optional `?run_id=` parameter; when the run has `source_type = "cloud_connect"`, returns `cloud_connect_summary` dict and per-run objects from `run_object_links` instead of MailObjects
|
||||
- `job_detail.html`: passes `run_id` to the detail API; if `cloud_connect_summary` is returned, shows the CC summary panel, collapses the raw email (accessible via "show" toggle), and shows only the single per-run repository object
|
||||
|
||||
- "Delete all jobs" in Settings → Maintenance no longer times out on large datasets:
|
||||
- Replaced ORM-based deletion (loaded all jobs/runs into Python memory, deleted object by object) with direct SQL `DELETE FROM` statements in FK order — handles 650K+ rows in seconds
|
||||
- Added `job_run_review_events` to the FK cleanup sequence (was causing a FK violation)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user