Fix manifest update: always rebuild tree, add debug logs, fix status handling
- Always rebuild progress tree HTML instead of incremental updates (simpler, more reliable) - Add console.log for debugging manifest updates - Fix status normalization (backend sends 'Running', 'Completed' etc) - Fix updateStatusSection to handle different manifest structures - Log section and child details for debugging
This commit is contained in:
parent
f5ece0d410
commit
4f05af4d04
1 changed files with 107 additions and 35 deletions
|
|
@ -441,15 +441,32 @@ function handleWebSocketMessage(data) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "manifest_update":
|
case "manifest_update":
|
||||||
console.log("[Tasks WS] MANIFEST_UPDATE for task:", data.task_id);
|
console.log(
|
||||||
|
"[Tasks WS] MANIFEST_UPDATE for task:",
|
||||||
|
data.task_id,
|
||||||
|
"selected:",
|
||||||
|
TasksState.selectedTaskId,
|
||||||
|
);
|
||||||
// Update the progress log section with manifest data
|
// Update the progress log section with manifest data
|
||||||
if (data.details) {
|
if (data.details) {
|
||||||
try {
|
try {
|
||||||
const manifestData = JSON.parse(data.details);
|
const manifestData = JSON.parse(data.details);
|
||||||
|
console.log(
|
||||||
|
"[Tasks WS] Manifest parsed, sections:",
|
||||||
|
manifestData.sections?.length,
|
||||||
|
"status:",
|
||||||
|
manifestData.status,
|
||||||
|
);
|
||||||
renderManifestProgress(data.task_id, manifestData);
|
renderManifestProgress(data.task_id, manifestData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("[Tasks WS] Failed to parse manifest:", e);
|
console.error(
|
||||||
|
"[Tasks WS] Failed to parse manifest:",
|
||||||
|
e,
|
||||||
|
data.details?.substring(0, 200),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("[Tasks WS] manifest_update received but no details");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -459,8 +476,16 @@ function handleWebSocketMessage(data) {
|
||||||
const pendingManifestUpdates = new Map();
|
const pendingManifestUpdates = new Map();
|
||||||
|
|
||||||
function renderManifestProgress(taskId, manifest, retryCount = 0) {
|
function renderManifestProgress(taskId, manifest, retryCount = 0) {
|
||||||
|
console.log(
|
||||||
|
"[Manifest] renderManifestProgress called for task:",
|
||||||
|
taskId,
|
||||||
|
"selected:",
|
||||||
|
TasksState.selectedTaskId,
|
||||||
|
);
|
||||||
|
|
||||||
// Only update if this is the selected task
|
// Only update if this is the selected task
|
||||||
if (TasksState.selectedTaskId !== taskId) {
|
if (TasksState.selectedTaskId !== taskId) {
|
||||||
|
console.log("[Manifest] Skipping - not selected task");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,6 +496,7 @@ function renderManifestProgress(taskId, manifest, retryCount = 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!progressLog) {
|
if (!progressLog) {
|
||||||
|
console.log("[Manifest] No progress log element found, retry:", retryCount);
|
||||||
// If task is selected but element not yet loaded, retry after a delay
|
// If task is selected but element not yet loaded, retry after a delay
|
||||||
if (retryCount < 5) {
|
if (retryCount < 5) {
|
||||||
pendingManifestUpdates.set(taskId, manifest);
|
pendingManifestUpdates.set(taskId, manifest);
|
||||||
|
|
@ -491,29 +517,28 @@ function renderManifestProgress(taskId, manifest, retryCount = 0) {
|
||||||
pendingManifestUpdates.delete(taskId);
|
pendingManifestUpdates.delete(taskId);
|
||||||
|
|
||||||
if (!manifest || !manifest.sections) {
|
if (!manifest || !manifest.sections) {
|
||||||
|
console.log("[Manifest] No sections in manifest");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("[Manifest] Rendering", manifest.sections.length, "sections");
|
||||||
|
|
||||||
const totalSteps = manifest.progress?.total || 60;
|
const totalSteps = manifest.progress?.total || 60;
|
||||||
|
|
||||||
// Update STATUS section if exists
|
// Update STATUS section if exists
|
||||||
updateStatusSection(manifest);
|
updateStatusSection(manifest);
|
||||||
|
|
||||||
// Update or create progress tree
|
// Always rebuild the tree to ensure children are shown
|
||||||
let tree = progressLog.querySelector(".taskmd-tree");
|
// This is simpler and more reliable than incremental updates
|
||||||
if (!tree) {
|
const html = buildProgressTreeHTML(manifest, totalSteps);
|
||||||
// First render - create full HTML
|
progressLog.innerHTML = html;
|
||||||
progressLog.innerHTML = buildProgressTreeHTML(manifest, totalSteps);
|
|
||||||
// Auto-expand running sections
|
// Auto-expand running sections
|
||||||
progressLog
|
progressLog
|
||||||
.querySelectorAll(".tree-section.running, .tree-child.running")
|
.querySelectorAll(".tree-section.running, .tree-child.running")
|
||||||
.forEach((el) => {
|
.forEach((el) => {
|
||||||
el.classList.add("expanded");
|
el.classList.add("expanded");
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
// Incremental update - only update changed elements
|
|
||||||
updateProgressTree(tree, manifest, totalSteps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update terminal stats
|
// Update terminal stats
|
||||||
updateTerminalStats(taskId, manifest);
|
updateTerminalStats(taskId, manifest);
|
||||||
|
|
@ -521,69 +546,116 @@ function renderManifestProgress(taskId, manifest, retryCount = 0) {
|
||||||
|
|
||||||
function updateStatusSection(manifest) {
|
function updateStatusSection(manifest) {
|
||||||
const statusContent = document.querySelector(".taskmd-status-content");
|
const statusContent = document.querySelector(".taskmd-status-content");
|
||||||
if (!statusContent) return;
|
if (!statusContent) {
|
||||||
|
console.log("[Manifest] No status content element found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Update current action
|
// Update current action
|
||||||
const actionText = statusContent.querySelector(
|
const actionText = statusContent.querySelector(
|
||||||
".status-current .status-text",
|
".status-current .status-text",
|
||||||
);
|
);
|
||||||
if (actionText && manifest.status?.current_action) {
|
const currentAction =
|
||||||
actionText.textContent = manifest.status.current_action;
|
manifest.status?.current_action ||
|
||||||
|
manifest.current_status?.current_action ||
|
||||||
|
"Processing...";
|
||||||
|
if (actionText) {
|
||||||
|
actionText.textContent = currentAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update runtime
|
// Update runtime
|
||||||
const runtimeEl = statusContent.querySelector(".status-main .status-time");
|
const runtimeEl = statusContent.querySelector(".status-main .status-time");
|
||||||
if (runtimeEl && manifest.status?.runtime_display) {
|
const runtime =
|
||||||
runtimeEl.innerHTML = `Runtime: ${manifest.status.runtime_display} <span class="status-indicator"></span>`;
|
manifest.status?.runtime_display || manifest.runtime || "Not started";
|
||||||
|
if (runtimeEl) {
|
||||||
|
runtimeEl.innerHTML = `Runtime: ${runtime} <span class="status-indicator"></span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update estimated
|
// Update estimated
|
||||||
const estimatedEl = statusContent.querySelector(
|
const estimatedEl = statusContent.querySelector(
|
||||||
".status-current .status-time",
|
".status-current .status-time",
|
||||||
);
|
);
|
||||||
if (estimatedEl && manifest.status?.estimated_display) {
|
const estimated =
|
||||||
estimatedEl.innerHTML = `Estimated: ${manifest.status.estimated_display} <span class="status-gear">⚙</span>`;
|
manifest.status?.estimated_display ||
|
||||||
|
(manifest.estimated_seconds
|
||||||
|
? `${manifest.estimated_seconds} sec`
|
||||||
|
: "calculating...");
|
||||||
|
if (estimatedEl) {
|
||||||
|
estimatedEl.innerHTML = `Estimated: ${estimated} <span class="status-gear">⚙</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"[Manifest] Status updated - action:",
|
||||||
|
currentAction,
|
||||||
|
"runtime:",
|
||||||
|
runtime,
|
||||||
|
"estimated:",
|
||||||
|
estimated,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildProgressTreeHTML(manifest, totalSteps) {
|
function buildProgressTreeHTML(manifest, totalSteps) {
|
||||||
let html = '<div class="taskmd-tree">';
|
let html = '<div class="taskmd-tree">';
|
||||||
|
|
||||||
for (const section of manifest.sections) {
|
for (const section of manifest.sections) {
|
||||||
const statusClass = section.status?.toLowerCase() || "pending";
|
// Normalize status - backend sends "Running", "Completed", etc.
|
||||||
|
const rawStatus = section.status || "Pending";
|
||||||
|
const statusClass = rawStatus.toLowerCase();
|
||||||
const isRunning = statusClass === "running";
|
const isRunning = statusClass === "running";
|
||||||
const globalCurrent =
|
const globalCurrent =
|
||||||
section.progress?.global_current || section.progress?.current || 0;
|
section.progress?.global_current || section.progress?.current || 0;
|
||||||
const statusText = section.status || "Pending";
|
|
||||||
|
console.log(
|
||||||
|
"[Manifest] Section:",
|
||||||
|
section.name,
|
||||||
|
"status:",
|
||||||
|
rawStatus,
|
||||||
|
"children:",
|
||||||
|
section.children?.length,
|
||||||
|
);
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="tree-section ${statusClass}${isRunning ? " expanded" : ""}" data-section-id="${section.id}">
|
<div class="tree-section ${statusClass}${isRunning ? " expanded" : ""}" data-section-id="${section.id}">
|
||||||
<div class="tree-row tree-level-0" onclick="this.parentElement.classList.toggle('expanded')">
|
<div class="tree-row tree-level-0" onclick="this.parentElement.classList.toggle('expanded')">
|
||||||
<span class="tree-name">${escapeHtml(section.name)}</span>
|
<span class="tree-name">${escapeHtml(section.name)}</span>
|
||||||
<span class="tree-step-badge">Step ${globalCurrent}/${totalSteps}</span>
|
<span class="tree-step-badge">Step ${globalCurrent}/${totalSteps}</span>
|
||||||
<span class="tree-status ${statusClass}">${statusText}</span>
|
<span class="tree-status ${statusClass}">${rawStatus}</span>
|
||||||
<span class="tree-section-dot ${statusClass}"></span>
|
<span class="tree-section-dot ${statusClass}"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tree-children">`;
|
<div class="tree-children">`;
|
||||||
|
|
||||||
// Children
|
// Children (e.g., "Database Schema Design" under "Database & Models")
|
||||||
if (section.children?.length > 0) {
|
if (section.children && section.children.length > 0) {
|
||||||
for (const child of section.children) {
|
for (const child of section.children) {
|
||||||
const childStatus = child.status?.toLowerCase() || "pending";
|
const childRawStatus = child.status || "Pending";
|
||||||
|
const childStatus = childRawStatus.toLowerCase();
|
||||||
const childIsRunning = childStatus === "running";
|
const childIsRunning = childStatus === "running";
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"[Manifest] Child:",
|
||||||
|
child.name,
|
||||||
|
"status:",
|
||||||
|
childRawStatus,
|
||||||
|
"items:",
|
||||||
|
(child.item_groups?.length || 0) + (child.items?.length || 0),
|
||||||
|
);
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="tree-child ${childStatus}${childIsRunning ? " expanded" : ""}" data-child-id="${child.id}">
|
<div class="tree-child ${childStatus}${childIsRunning ? " expanded" : ""}" data-child-id="${child.id}">
|
||||||
<div class="tree-row tree-level-1" onclick="this.parentElement.classList.toggle('expanded')">
|
<div class="tree-row tree-level-1" onclick="this.parentElement.classList.toggle('expanded')">
|
||||||
<span class="tree-item-dot ${childStatus}"></span>
|
<span class="tree-item-dot ${childStatus}"></span>
|
||||||
<span class="tree-name">${escapeHtml(child.name)}</span>
|
<span class="tree-name">${escapeHtml(child.name)}</span>
|
||||||
<span class="tree-step-badge">Step ${child.progress?.current || 0}/${child.progress?.total || 1}</span>
|
<span class="tree-step-badge">Step ${child.progress?.current || 0}/${child.progress?.total || 1}</span>
|
||||||
<span class="tree-status ${childStatus}">${child.status || "Pending"}</span>
|
<span class="tree-status ${childStatus}">${childRawStatus}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tree-items">`;
|
<div class="tree-items">`;
|
||||||
|
|
||||||
// Items
|
// Items within child (e.g., "email, password_hash, email_verified")
|
||||||
const items = [...(child.item_groups || []), ...(child.items || [])];
|
const childItems = [
|
||||||
for (const item of items) {
|
...(child.item_groups || []),
|
||||||
|
...(child.items || []),
|
||||||
|
];
|
||||||
|
for (const item of childItems) {
|
||||||
html += buildItemHTML(item);
|
html += buildItemHTML(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -591,7 +663,7 @@ function buildProgressTreeHTML(manifest, totalSteps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section-level items
|
// Section-level items (items directly under section, not in children)
|
||||||
const sectionItems = [
|
const sectionItems = [
|
||||||
...(section.item_groups || []),
|
...(section.item_groups || []),
|
||||||
...(section.items || []),
|
...(section.items || []),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue