Files
2026-06-13 19:50:42 +05:30

789 lines
13 KiB
JavaScript

import {
buildNodeExplorer,
locateNode
}
from "./node_explorer.js";
import {
buildArchitectureAnalyzer
}
from "./architecture_analyzer.js";
import {
buildWorkflowStatistics
}
from "./workflow_statistics.js";
import {
buildBranchAnalyzer
}
from "./branch_analyzer.js";
import {
buildDependencyGraph
}
from "./dependency_graph.js";
import {
buildWorkflowAdvisor
}
from "./workflow_advisor.js";
import {
buildWorkflowActions
}
from "./workflow_actions.js";
let dashboardWindow = null;
function createTabButton(
title,
onClick,
container
)
{
const button =
document.createElement(
"button"
);
button.innerText =
title;
button.style.marginRight =
"8px";
button.style.padding =
"8px";
button.style.cursor =
"pointer";
button.style.background =
"#333";
button.style.color =
"#fff";
button.style.border =
"1px solid #555";
button.style.borderRadius =
"6px";
button.onclick =
onClick;
container.appendChild(
button
);
}
function getRiskColor(
risk
)
{
if (
risk === "High"
)
{
return "#ff4444";
}
if (
risk === "Medium"
)
{
return "#ffaa00";
}
return "#00cc66";
}
function buildHealthAnalyzer(
healthData
)
{
const wrapper =
document.createElement(
"div"
);
const score =
healthData?.score ?? 0;
const status =
healthData?.status ??
"Unknown";
let statusColor =
"#ff4444";
if (
score >= 90
)
{
statusColor =
"#00cc66";
}
else if (
score >= 70
)
{
statusColor =
"#ffaa00";
}
wrapper.innerHTML =
`
<h2>
Workflow Health Analyzer
</h2>
<div
style="
padding:20px;
border:1px solid #444;
border-radius:10px;
margin-bottom:20px;
background:#252526;
"
>
<h1
style="
color:${statusColor};
margin:0;
"
>
${score}/100
</h1>
<h3>
Status:
${status}
</h3>
<p>
<b>Orphan Nodes:</b>
${healthData.orphan_nodes || 0}
</p>
<p>
<b>Dead End Nodes:</b>
${healthData.dead_end_nodes || 0}
</p>
<p>
<b>Save Nodes:</b>
${healthData.save_nodes || 0}
</p>
<p>
<b>Exit Nodes:</b>
${healthData.exit_nodes || 0}
</p>
</div>
`;
const warningTitle =
document.createElement(
"h3"
);
warningTitle.innerText =
"Warnings";
wrapper.appendChild(
warningTitle
);
const warningList =
document.createElement(
"ul"
);
const warnings =
healthData.warnings || [];
if (
warnings.length === 0
)
{
const item =
document.createElement(
"li"
);
item.innerText =
"No issues detected";
warningList.appendChild(
item
);
}
else
{
warnings.forEach(
warning =>
{
const item =
document.createElement(
"li"
);
item.innerText =
warning;
warningList.appendChild(
item
);
}
);
}
wrapper.appendChild(
warningList
);
const issueTitle =
document.createElement(
"h3"
);
issueTitle.style.marginTop =
"25px";
issueTitle.innerText =
"Workflow Debugger";
wrapper.appendChild(
issueTitle
);
const issues =
healthData.issues || [];
if (
issues.length === 0
)
{
const successCard =
document.createElement(
"div"
);
successCard.style.padding =
"15px";
successCard.style.marginTop =
"10px";
successCard.style.border =
"1px solid #00cc66";
successCard.style.borderRadius =
"8px";
successCard.style.background =
"#1f2b1f";
successCard.innerHTML =
`
<h3>
No Issues Found
</h3>
<p>
Workflow looks healthy.
</p>
`;
wrapper.appendChild(
successCard
);
return wrapper;
}
issues.forEach(
issue =>
{
const card =
document.createElement(
"div"
);
card.style.border =
"1px solid #444";
card.style.borderRadius =
"10px";
card.style.padding =
"15px";
card.style.marginBottom =
"15px";
card.style.background =
"#252526";
const riskColor =
getRiskColor(
issue.risk
);
card.innerHTML =
`
<h3>
${issue.issue_type}
</h3>
<p>
<b>Node:</b>
${issue.node_type}
</p>
<p>
<b>Node ID:</b>
${issue.node_id ?? "N/A"}
</p>
<p>
<b>Risk:</b>
<span
style="
color:${riskColor};
font-weight:bold;
"
>
${issue.risk}
</span>
</p>
<p>
<b>Reason:</b>
${issue.reason}
</p>
<p>
<b>Recommendation:</b>
${issue.recommendation}
</p>
`;
if (
issue.node_id !== null &&
issue.node_id !== undefined
)
{
const locateButton =
document.createElement(
"button"
);
locateButton.innerText =
"Locate Node";
locateButton.style.marginTop =
"10px";
locateButton.style.padding =
"8px";
locateButton.style.cursor =
"pointer";
locateButton.onclick =
() =>
{
locateNode(
issue.node_id
);
};
card.appendChild(
locateButton
);
}
wrapper.appendChild(
card
);
}
);
return wrapper;
}
export function showDashboard(
data
)
{
if (
dashboardWindow
)
{
dashboardWindow.remove();
}
dashboardWindow =
document.createElement(
"div"
);
dashboardWindow.id =
"comfyflow-dashboard";
dashboardWindow.style.position =
"fixed";
dashboardWindow.style.top =
"80px";
dashboardWindow.style.left =
"120px";
dashboardWindow.style.width =
"1100px";
dashboardWindow.style.height =
"750px";
dashboardWindow.style.background =
"#1e1e1e";
dashboardWindow.style.color =
"#ffffff";
dashboardWindow.style.border =
"1px solid #555";
dashboardWindow.style.zIndex =
"99999";
dashboardWindow.style.resize =
"both";
dashboardWindow.style.overflow =
"hidden";
const header =
document.createElement(
"div"
);
header.style.padding =
"12px";
header.style.cursor =
"move";
header.style.background =
"#252526";
header.style.fontWeight =
"bold";
header.style.fontSize =
"18px";
header.innerHTML =
`
ComfyFlow Insight
<span
id="comfyflow-close"
style="
float:right;
cursor:pointer;
font-size:22px;
"
>
✖
</span>
`;
dashboardWindow.appendChild(
header
);
const tabs =
document.createElement(
"div"
);
tabs.style.padding =
"10px";
tabs.style.borderBottom =
"1px solid #444";
dashboardWindow.appendChild(
tabs
);
const content =
document.createElement(
"div"
);
content.id =
"comfyflow-content";
content.style.padding =
"15px";
content.style.height =
"620px";
content.style.overflow =
"auto";
dashboardWindow.appendChild(
content
);
document.body.appendChild(
dashboardWindow
);
createTabButton(
"Overview",
() =>
{
content.innerHTML =
`
<h2>Workflow Overview</h2>
<p><b>Nodes:</b> ${data.nodes}</p>
<p><b>Links:</b> ${data.links}</p>
<p><b>Complexity:</b> ${data.complexity}</p>
<p><b>Health:</b> ${data.health}</p>
`;
},
tabs
);
createTabButton(
"Architecture",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildArchitectureAnalyzer(
data.architecture_analysis ||
{},
data.diagram ||
""
)
);
},
tabs
);
createTabButton(
"Statistics",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildWorkflowStatistics(
data.workflow_statistics ||
{}
)
);
},
tabs
);
createTabButton(
"Branch Analyzer",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildBranchAnalyzer(
data.branch_analysis ||
{}
)
);
},
tabs
);
createTabButton(
"Dependency Graph",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildDependencyGraph(
data.dependency_graph ||
{}
)
);
},
tabs
);
createTabButton(
"Workflow Advisor",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildWorkflowAdvisor(
data.workflow_advisor ||
{}
)
);
},
tabs
);
createTabButton(
"Workflow Actions",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildWorkflowActions(
data.workflow_actions ||
{}
)
);
},
tabs
);
createTabButton(
"Node Explorer",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildNodeExplorer(
data.node_explorer
)
);
},
tabs
);
createTabButton(
"Health Analyzer",
() =>
{
content.innerHTML =
"";
content.appendChild(
buildHealthAnalyzer(
data.health_analysis
)
);
},
tabs
);
content.innerHTML =
`
<h2>Workflow Overview</h2>
<p><b>Nodes:</b> ${data.nodes}</p>
<p><b>Links:</b> ${data.links}</p>
<p><b>Complexity:</b> ${data.complexity}</p>
<p><b>Health:</b> ${data.health}</p>
`;
document.getElementById(
"comfyflow-close"
).onclick =
() =>
{
dashboardWindow.remove();
dashboardWindow = null;
};
let dragging =
false;
let offsetX =
0;
let offsetY =
0;
header.addEventListener(
"mousedown",
function(e)
{
dragging =
true;
offsetX =
e.clientX -
dashboardWindow.offsetLeft;
offsetY =
e.clientY -
dashboardWindow.offsetTop;
}
);
document.addEventListener(
"mouseup",
function()
{
dragging =
false;
}
);
document.addEventListener(
"mousemove",
function(e)
{
if (
!dragging
)
{
return;
}
dashboardWindow.style.left =
(
e.clientX -
offsetX
) + "px";
dashboardWindow.style.top =
(
e.clientY -
offsetY
) + "px";
}
);
}