ux: plan mode moved

This commit is contained in:
2026-05-08 00:37:09 -04:00
parent 97c751c585
commit 7b65b62f58
3 changed files with 301 additions and 56 deletions
+57 -6
View File
@@ -50,9 +50,11 @@ const updateModalClose = document.getElementById("update-modal-close");
const updateModalInstall = document.getElementById("update-modal-install");
const updateModalReleases = document.getElementById("update-modal-releases");
const plansRefreshButton = document.getElementById("plans-refresh");
const plansCloseButton = document.getElementById("plans-close");
const planForm = document.getElementById("plan-form");
const plansStatusEl = document.getElementById("plans-status");
const plansDashboardEl = document.getElementById("plans-dashboard");
const plansRailListEl = document.getElementById("plans-rail-list");
let ollamaOnline = true;
let latestUpdate = null;
@@ -742,7 +744,6 @@ function toggleSidebarPanel(panelName) {
const panels = {
settings: { panel: settingsPanel, button: settingsToggle },
memory: { panel: memoryPanel, button: memoryToggle },
plans: { panel: plansPanel, button: plansToggle },
ollama: { panel: ollamaPanel, button: ollamaToggle },
};
const target = panels[panelName];
@@ -763,7 +764,6 @@ function toggleSidebarPanel(panelName) {
checkForUpdate();
}
if (panelName === "memory") refreshMemory();
if (panelName === "plans") refreshPlans();
if (panelName === "ollama") {
refreshConfig();
refreshOllamaStatus();
@@ -971,6 +971,19 @@ function closeNegotiationPanel() {
negotiationStatusEl.textContent = "";
}
function openPlansPanel(openPlanId = null) {
if (!plansPanel) return;
plansPanel.hidden = false;
plansToggle?.setAttribute("aria-expanded", "true");
refreshPlans(openPlanId);
}
function closePlansPanel() {
if (!plansPanel) return;
plansPanel.hidden = true;
plansToggle?.setAttribute("aria-expanded", "false");
}
function renderNegotiationMessages(data) {
negotiationMessagesEl.innerHTML = "";
const items = Array.isArray(data) ? data : [data].filter(Boolean);
@@ -1062,13 +1075,47 @@ async function createPlan(event) {
}
async function refreshPlans(openPlanId = null) {
if (!plansDashboardEl) return;
if (!plansDashboardEl && !plansRailListEl) return;
try {
const response = await fetch("/api/plans");
const result = await response.json();
await renderPlans(result.plans || [], openPlanId);
const plans = result.plans || [];
renderPlansRail(plans);
if (plansDashboardEl) await renderPlans(plans, openPlanId);
} catch (error) {
plansDashboardEl.textContent = `Plans failed: ${fetchErrorMessage(error)}`;
if (plansDashboardEl) plansDashboardEl.textContent = `Plans failed: ${fetchErrorMessage(error)}`;
if (plansRailListEl) plansRailListEl.textContent = `Plans failed: ${fetchErrorMessage(error)}`;
}
}
function renderPlansRail(plans) {
if (!plansRailListEl) return;
plansRailListEl.innerHTML = "";
if (!plans.length) {
plansRailListEl.innerHTML = '<div class="pending-empty">No plans</div>';
return;
}
for (const plan of plans.slice(0, 5)) {
const row = document.createElement("button");
row.type = "button";
row.className = "plan-rail-item";
const title = document.createElement("span");
title.className = "plan-rail-title";
title.textContent = plan.title || "Untitled plan";
const status = document.createElement("span");
status.className = "plan-rail-status";
status.textContent = plan.status || "plan";
row.append(title, status);
row.addEventListener("click", () => openPlansPanel(plan.id));
plansRailListEl.appendChild(row);
}
if (plans.length > 5) {
const more = document.createElement("button");
more.type = "button";
more.className = "plan-rail-item";
more.textContent = `${plans.length - 5} more`;
more.addEventListener("click", () => openPlansPanel());
plansRailListEl.appendChild(more);
}
}
@@ -1385,9 +1432,13 @@ configRefreshButton?.addEventListener("click", refreshConfig);
configForm?.addEventListener("submit", saveConfig);
settingsToggle?.addEventListener("click", () => toggleSidebarPanel("settings"));
memoryToggle?.addEventListener("click", () => toggleSidebarPanel("memory"));
plansToggle?.addEventListener("click", () => toggleSidebarPanel("plans"));
plansToggle?.addEventListener("click", () => {
if (plansPanel?.hidden) openPlansPanel();
else closePlansPanel();
});
ollamaToggle?.addEventListener("click", () => toggleSidebarPanel("ollama"));
plansRefreshButton?.addEventListener("click", () => refreshPlans());
plansCloseButton?.addEventListener("click", closePlansPanel);
planForm?.addEventListener("submit", createPlan);
ollamaForm?.addEventListener("submit", saveOllamaConfig);
ollamaRefreshButton?.addEventListener("click", refreshOllamaStatus);