Add JSON export actions for topology and diff.
Provide UI buttons to export latest topology and diff payloads into downloadable JSON files. Made-with: Cursor
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<select id="scanSelect" style="min-width: 360px;"></select>
|
||||
<button id="loadBtn">Загрузить</button>
|
||||
<button id="latestBtn">Последний scan</button>
|
||||
<button id="exportTopologyBtn">Экспорт topology JSON</button>
|
||||
<button id="fitBtn">По центру</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -29,6 +30,7 @@
|
||||
<select id="fromScanSelect" style="min-width: 240px;"></select>
|
||||
<select id="toScanSelect" style="min-width: 240px;"></select>
|
||||
<button id="diffBtn">Сравнить</button>
|
||||
<button id="exportDiffBtn">Экспорт diff JSON</button>
|
||||
</div>
|
||||
<div id="status">Ожидание данных...</div>
|
||||
<div style="margin: 6px 0 10px 0; font-size: 13px;">
|
||||
@@ -56,6 +58,8 @@
|
||||
const loadBtn = document.getElementById("loadBtn");
|
||||
const latestBtn = document.getElementById("latestBtn");
|
||||
const diffBtn = document.getElementById("diffBtn");
|
||||
const exportTopologyBtn = document.getElementById("exportTopologyBtn");
|
||||
const exportDiffBtn = document.getElementById("exportDiffBtn");
|
||||
const fitBtn = document.getElementById("fitBtn");
|
||||
const nodeFilter = document.getElementById("nodeFilter");
|
||||
const statusEl = document.getElementById("status");
|
||||
@@ -64,9 +68,21 @@
|
||||
const NS = "http://www.w3.org/2000/svg";
|
||||
let lastTopology = null;
|
||||
let lastHighlight = null;
|
||||
let lastDiff = null;
|
||||
|
||||
function setStatus(text) { statusEl.textContent = text; }
|
||||
function setDiff(text) { diffBox.textContent = text; }
|
||||
function downloadJSON(filename, data) {
|
||||
const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
function clearSVG() {
|
||||
while (svg.firstChild) svg.removeChild(svg.firstChild);
|
||||
@@ -240,6 +256,7 @@
|
||||
return;
|
||||
}
|
||||
const d = await res.json();
|
||||
lastDiff = d;
|
||||
setDiff(JSON.stringify(d, null, 2));
|
||||
const topoRes = await fetch(`/api/scans/${encodeURIComponent(toId)}/topology?limit=5000`);
|
||||
if (topoRes.ok) {
|
||||
@@ -272,6 +289,25 @@
|
||||
});
|
||||
latestBtn.addEventListener("click", loadLatestScan);
|
||||
diffBtn.addEventListener("click", loadDiff);
|
||||
exportTopologyBtn.addEventListener("click", () => {
|
||||
const scanId = scanIdInput.value.trim() || "unknown";
|
||||
if (!lastTopology) {
|
||||
setStatus("Сначала загрузите topology");
|
||||
return;
|
||||
}
|
||||
downloadJSON(`topology_${scanId}.json`, lastTopology);
|
||||
setStatus("Topology JSON экспортирован");
|
||||
});
|
||||
exportDiffBtn.addEventListener("click", () => {
|
||||
const fromId = fromScanIdInput.value.trim() || "from";
|
||||
const toId = toScanIdInput.value.trim() || "to";
|
||||
if (!lastDiff) {
|
||||
setStatus("Сначала выполните diff");
|
||||
return;
|
||||
}
|
||||
downloadJSON(`diff_${fromId}_to_${toId}.json`, lastDiff);
|
||||
setStatus("Diff JSON экспортирован");
|
||||
});
|
||||
fitBtn.addEventListener("click", () => {
|
||||
svg.setAttribute("viewBox", "0 0 1200 620");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user