"use strict";
function byId(id) {
return document.getElementById(id);
}
function escapeHtml(value) {
if (!value) return "";
const div = document.createElement("div");
div.textContent = String(value);
return div.innerHTML;
}
/**
* Owns structural proposal rendering and approval actions.
*/
export class StructuralProposalPanel {
constructor({ api, logger, onChanged = async () => {} }) {
this.api = api;
this.logger = logger;
this.onChanged = onChanged;
this.commandInFlight = false;
this.proposals = [];
this.handleApprove = this.handleApprove.bind(this);
this.handleReject = this.handleReject.bind(this);
}
async load() {
try {
const data = await this.api.getProposals();
this.proposals = data.proposals || [];
this.render(this.proposals);
} catch (error) {
this.logger.log(`⚠️ Failed to load proposals: ${error.message}`, "warning");
}
}
render(proposals) {
const container = byId("b5d-proposals");
if (!container) return;
if (!proposals || proposals.length === 0) {
container.innerHTML = '
No pending proposals
';
return;
}
container.innerHTML = proposals.map((proposal) => {
const confidence = (proposal.confidence || 0) * 100;
const id = escapeHtml(proposal.proposal_id);
return `
${escapeHtml(proposal.kind || "unknown")}
Neuron ${proposal.neuron_id || "?"} → ${proposal.target_id || "?"}
${confidence.toFixed(0)}%
${escapeHtml(proposal.reason || "")}
`;
}).join("");
container.querySelectorAll(".btn-approve").forEach((button) => {
button.addEventListener("click", () => this.handleApprove(button.dataset.id));
});
container.querySelectorAll(".btn-reject").forEach((button) => {
button.addEventListener("click", () => this.handleReject(button.dataset.id));
});
}
async handleApprove(proposalId) {
await this.execute(proposalId, "approve", () => this.api.approveProposal(proposalId));
}
async handleReject(proposalId) {
await this.execute(proposalId, "reject", () => this.api.rejectProposal(proposalId));
}
async execute(proposalId, action, request) {
if (this.commandInFlight) {
this.logger.log("⏳ Command in progress...", "warning");
return;
}
this.commandInFlight = true;
this.logger.log(`${action === "approve" ? "✓ Approving" : "✗ Rejecting"} proposal ${proposalId}...`, "info");
try {
const result = await request();
if (result.ok) {
this.logger.log(`✅ Proposal ${proposalId} ${action}d`, "success");
await this.load();
await this.onChanged();
} else {
this.logger.log(`❌ Failed to ${action}: ${result.message || "Unknown error"}`, "error");
}
} catch (error) {
this.logger.log(`❌ Failed to ${action}: ${error.message}`, "error");
} finally {
this.commandInFlight = false;
}
}
}