v9.18: restore graph button, add text wrapping in SVG, fix scrolling
This commit is contained in:
+1
-1
@@ -15,7 +15,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: cloud-dashboard
|
||||
image: naeel/cloud-dashboard:v9.17
|
||||
image: naeel/cloud-dashboard:v9.18
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
+59
-53
@@ -39,6 +39,8 @@
|
||||
.btn-graph:hover { background: #2563eb; }
|
||||
.btn-theme { padding: 5px 10px; background: #21262d; border: 1px solid #30363d; border-radius: 6px; color: #e1e4e8; cursor: pointer; font-size: 14px; line-height: 1; }
|
||||
.btn-theme:hover { background: #30363d; }
|
||||
.btn-graph { padding: 5px 12px; background: #21262d; border: 1px solid #30363d; border-radius: 6px; color: #e1e4e8; cursor: pointer; font-size: 12px; }
|
||||
.btn-graph:hover { background: #30363d; }
|
||||
.header-user { display: flex; align-items: center; gap: 10px; }
|
||||
.user-email { font-size: 12px; color: #8b949e; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.btn-exit { padding: 5px 12px; background: #21262d; border: 1px solid #30363d; border-radius: 6px; color: #f85149; cursor: pointer; font-size: 12px; }
|
||||
@@ -133,8 +135,8 @@
|
||||
body.light header { background: #ffffff; border-bottom-color: #cbd5e1; }
|
||||
body.light .header-logo .logo-text { color: #0f172a; }
|
||||
body.light .header-logo .logo-sub, body.light .user-email { color: #475569; }
|
||||
body.light .btn-refresh, body.light .btn-theme, body.light .btn-exit { background: #f8fafc; border-color: #cbd5e1; color: #0f172a; }
|
||||
body.light .btn-refresh:hover, body.light .btn-theme:hover, body.light .btn-exit:hover { background: #e2e8f0; }
|
||||
body.light .btn-refresh, body.light .btn-theme, body.light .btn-exit, body.light .btn-graph { background: #f8fafc; border-color: #cbd5e1; color: #0f172a; }
|
||||
body.light .btn-refresh:hover, body.light .btn-theme:hover, body.light .btn-exit:hover, body.light .btn-graph:hover { background: #e2e8f0; }
|
||||
body.light .main { background: #f3f6fb; }
|
||||
body.light table { background: #ffffff; border-color: #cbd5e1; }
|
||||
body.light thead { background: #e2e8f0; }
|
||||
@@ -205,7 +207,7 @@
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<button class="btn-refresh" id="btn-refresh">↻ Обновить</button>
|
||||
|
||||
<button class="btn-graph" id="btn-running-graph">📊 Граф зависимостей</button>
|
||||
<button class="btn-theme" id="btn-theme" title="Сменить тему">🌙</button>
|
||||
<div class="header-user">
|
||||
<span class="user-email" id="user-email"></span>
|
||||
@@ -540,7 +542,7 @@ function drawGraph(containerId, data, focusUid, forceShowAux){
|
||||
graphDrawing = false;
|
||||
return;
|
||||
}
|
||||
var layoutMeta = buildRowLayout(data, el.clientWidth || 1200, forceShowAux);
|
||||
var layoutMeta = buildRowLayout(data, 1200, forceShowAux);
|
||||
var posMap = layoutMeta.positions;
|
||||
var visibleNodes = data.nodes || [];
|
||||
|
||||
@@ -563,20 +565,25 @@ function drawGraph(containerId, data, focusUid, forceShowAux){
|
||||
var offsetX = -minX + padding;
|
||||
var offsetY = -minY + padding;
|
||||
|
||||
// Create SVG container for scrolling
|
||||
// Create scrollable container
|
||||
var scrollContainer = document.createElement("div");
|
||||
scrollContainer.style.width = "100%";
|
||||
scrollContainer.style.height = "100%";
|
||||
scrollContainer.style.overflow = "auto";
|
||||
scrollContainer.style.backgroundColor = "#0d1117";
|
||||
|
||||
// Create SVG
|
||||
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svg.setAttribute("width", containerW);
|
||||
svg.setAttribute("height", containerH);
|
||||
svg.setAttribute("viewBox", "0 0 " + containerW + " " + containerH);
|
||||
svg.style.display = "block";
|
||||
svg.style.width = "100%";
|
||||
svg.style.height = "100%";
|
||||
svg.style.backgroundColor = "#0d1117";
|
||||
svg.style.cursor = "default";
|
||||
svg.style.minWidth = containerW + "px";
|
||||
svg.style.minHeight = containerH + "px";
|
||||
|
||||
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||||
|
||||
// Draw nodes
|
||||
// Draw nodes with text wrapping via tspan
|
||||
visibleNodes.forEach(function(n){
|
||||
var pos = posMap[n.id];
|
||||
if(!pos) return;
|
||||
@@ -604,60 +611,54 @@ function drawGraph(containerId, data, focusUid, forceShowAux){
|
||||
});
|
||||
g.appendChild(rect);
|
||||
|
||||
// Text: name (bold, underline), svc (italic), age (small)
|
||||
// Text with wrapping: name + svc + age
|
||||
var nameFs = Math.round((n.fontSize || 13) * 1.25);
|
||||
var txtX = x;
|
||||
var txtY = y - h/4;
|
||||
var lineH = nameFs * 1.5;
|
||||
var lines = [];
|
||||
|
||||
// Split name into lines (rough estimate)
|
||||
var charsPerLine = Math.max(8, Math.floor((w - 20) / (nameFs * 0.6)));
|
||||
var nameLines = [];
|
||||
for(var i = 0; i < n.label.length; i += charsPerLine){
|
||||
nameLines.push(n.label.substring(i, i + charsPerLine));
|
||||
}
|
||||
nameLines.forEach(function(line){ lines.push({text: line, size: nameFs, weight: "bold", style: "normal", color: "#dbeafe"}); });
|
||||
|
||||
// Name
|
||||
var nameText = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
nameText.setAttribute("x", txtX);
|
||||
nameText.setAttribute("y", txtY);
|
||||
nameText.setAttribute("text-anchor", "middle");
|
||||
nameText.setAttribute("font-size", nameFs);
|
||||
nameText.setAttribute("font-weight", "bold");
|
||||
nameText.setAttribute("text-decoration", "underline");
|
||||
nameText.setAttribute("fill", "#dbeafe");
|
||||
nameText.setAttribute("font-family", "system-ui, sans-serif");
|
||||
nameText.textContent = n.label || n.id || "";
|
||||
nameText.style.pointerEvents = "none";
|
||||
g.appendChild(nameText);
|
||||
|
||||
// Service
|
||||
if(n.svc){
|
||||
var svcText = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
svcText.setAttribute("x", txtX);
|
||||
svcText.setAttribute("y", txtY + nameFs * 0.8 + 3);
|
||||
svcText.setAttribute("text-anchor", "middle");
|
||||
svcText.setAttribute("font-size", (nameFs - 2));
|
||||
svcText.setAttribute("font-style", "italic");
|
||||
svcText.setAttribute("fill", "#93c5fd");
|
||||
svcText.setAttribute("font-family", "system-ui, sans-serif");
|
||||
svcText.textContent = n.svc;
|
||||
svcText.style.pointerEvents = "none";
|
||||
g.appendChild(svcText);
|
||||
lines.push({text: n.svc, size: nameFs - 2, weight: "normal", style: "italic", color: "#93c5fd"});
|
||||
}
|
||||
|
||||
if(n.age){
|
||||
lines.push({text: "⏱ " + n.age, size: 9, weight: "normal", style: "italic", color: "#9ca3af"});
|
||||
}
|
||||
|
||||
// Age
|
||||
if(n.age){
|
||||
var ageText = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
ageText.setAttribute("x", txtX);
|
||||
ageText.setAttribute("y", y + h/4 + 4);
|
||||
ageText.setAttribute("text-anchor", "middle");
|
||||
ageText.setAttribute("font-size", 9);
|
||||
ageText.setAttribute("font-style", "italic");
|
||||
ageText.setAttribute("fill", "#9ca3af");
|
||||
ageText.setAttribute("font-family", "system-ui, sans-serif");
|
||||
ageText.textContent = "⏱ " + n.age;
|
||||
ageText.style.pointerEvents = "none";
|
||||
g.appendChild(ageText);
|
||||
}
|
||||
// Render text lines
|
||||
var textG = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||||
var currentY = txtY - (lines.length * lineH / 2);
|
||||
lines.forEach(function(line){
|
||||
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
text.setAttribute("x", txtX);
|
||||
text.setAttribute("y", currentY);
|
||||
text.setAttribute("text-anchor", "middle");
|
||||
text.setAttribute("font-size", line.size);
|
||||
text.setAttribute("font-weight", line.weight);
|
||||
text.setAttribute("font-style", line.style);
|
||||
text.setAttribute("fill", line.color);
|
||||
text.setAttribute("font-family", "system-ui, sans-serif");
|
||||
text.textContent = line.text;
|
||||
text.style.pointerEvents = "none";
|
||||
textG.appendChild(text);
|
||||
currentY += lineH;
|
||||
});
|
||||
g.appendChild(textG);
|
||||
});
|
||||
|
||||
svg.appendChild(g);
|
||||
el.appendChild(svg);
|
||||
scrollContainer.appendChild(svg);
|
||||
el.appendChild(scrollContainer);
|
||||
|
||||
// Auto-fit on container size change
|
||||
setTimeout(function(){ graphDrawing = false; }, 50);
|
||||
}
|
||||
|
||||
@@ -1272,9 +1273,14 @@ function initApp(){
|
||||
|
||||
document.getElementById("btn-login").addEventListener("click", doLogin);
|
||||
document.getElementById("btn-refresh").addEventListener("click", loadAllDetails);
|
||||
document.getElementById("btn-running-graph").addEventListener("click", openRunningGraph);
|
||||
document.getElementById("btn-theme").addEventListener("click", toggleTheme);
|
||||
document.getElementById("btn-exit").addEventListener("click", doLogout);
|
||||
|
||||
document.getElementById("graph-modal").addEventListener("click", function(e){
|
||||
if(e.target && e.target.id === "graph-modal") closeRunningGraph();
|
||||
});
|
||||
|
||||
applyTheme(localStorage.getItem("dashboard_theme") || "dark");
|
||||
|
||||
var envSelect = document.getElementById("deck-env");
|
||||
|
||||
Reference in New Issue
Block a user