Files
bDS/src/main/engine/mcp-views/review-post.html

125 lines
5.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Review Post</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; padding: 16px; color: #1a1a1a; background: #fff; line-height: 1.5; }
h1 { font-size: 1.25rem; margin-bottom: 12px; }
h2 { font-size: 1rem; margin: 12px 0 8px; color: #555; }
.meta { color: #666; font-size: 0.875rem; margin-bottom: 8px; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: 600; }
.badge-draft { background: #fef3cd; color: #856404; }
.badge-kind { background: #d1ecf1; color: #0c5460; }
.content-preview { background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 6px; padding: 12px; margin: 8px 0; overflow-x: auto; white-space: pre-wrap; font-family: monospace; font-size: 0.85rem; max-height: 400px; overflow-y: auto; }
.actions { display: flex; gap: 8px; margin-top: 16px; }
.btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem; font-weight: 500; }
.btn-accept { background: #28a745; color: #fff; }
.btn-accept:hover { background: #218838; }
.btn-discard { background: #dc3545; color: #fff; }
.btn-discard:hover { background: #c82333; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.status { margin-top: 12px; padding: 8px 12px; border-radius: 6px; font-size: 0.875rem; }
.status-success { background: #d4edda; color: #155724; }
.status-error { background: #f8d7da; color: #721c24; }
.word-count { color: #888; font-size: 0.8rem; }
</style>
</head>
<body>
<div id="review">
<p class="meta">Waiting for post data...</p>
</div>
<div id="status" class="status" style="display:none"></div>
<script type="module">
import { App } from "@modelcontextprotocol/ext-apps/app-with-deps";
const app = new App({ name: "bDS Review", version: "1.0.0" });
let currentData = null;
app.ontoolresult = (result) => {
try {
const textContent = result.content?.find(c => c.type === "text");
if (textContent?.text) {
currentData = JSON.parse(textContent.text);
renderReview(currentData);
}
} catch (e) {
showStatus("Failed to parse tool result: " + e.message, "error");
}
};
window.acceptProposal = async () => {
if (!currentData?.proposalId) return;
setButtonsDisabled(true);
try {
const result = await app.callServerTool({
name: "accept_proposal",
arguments: { proposalId: currentData.proposalId }
});
const text = result.content?.find(c => c.type === "text")?.text;
const parsed = text ? JSON.parse(text) : {};
showStatus(parsed.success ? "Accepted!" : (parsed.message || "Failed"), parsed.success ? "success" : "error");
} catch (e) {
showStatus("Error: " + e.message, "error");
}
};
window.discardProposal = async () => {
if (!currentData?.proposalId) return;
setButtonsDisabled(true);
try {
const result = await app.callServerTool({
name: "discard_proposal",
arguments: { proposalId: currentData.proposalId }
});
const text = result.content?.find(c => c.type === "text")?.text;
const parsed = text ? JSON.parse(text) : {};
showStatus(parsed.success ? "Discarded." : (parsed.message || "Failed"), parsed.success ? "success" : "error");
} catch (e) {
showStatus("Error: " + e.message, "error");
}
};
function setButtonsDisabled(disabled) {
document.querySelectorAll(".btn").forEach(b => b.disabled = disabled);
}
function showStatus(message, type) {
const el = document.getElementById("status");
if (el) {
el.textContent = message;
el.className = "status status-" + type;
el.style.display = "block";
}
}
window.showStatus = showStatus;
window.renderReview = window.renderReview || (() => {});
window.renderReview = (data) => {
const post = data.post || {};
const wc = (post.content || "").split(/\s+/).filter(Boolean).length;
document.getElementById("review").innerHTML = `
<h1>${esc(post.title || "Untitled")}</h1>
<p class="meta">
<span class="badge badge-draft">Draft</span>
<span class="word-count">${wc} words</span>
</p>
${post.categories?.length ? '<p class="meta">Categories: ' + post.categories.map(c => esc(c)).join(", ") + '</p>' : ''}
${post.tags?.length ? '<p class="meta">Tags: ' + post.tags.map(t => esc(t)).join(", ") + '</p>' : ''}
${post.excerpt ? '<h2>Excerpt</h2><p>' + esc(post.excerpt) + '</p>' : ''}
<h2>Content</h2>
<div class="content-preview">${esc(post.content || "")}</div>
<div class="actions">
<button class="btn btn-accept" onclick="acceptProposal()">Publish</button>
<button class="btn btn-discard" onclick="discardProposal()">Discard Draft</button>
</div>
`;
};
function esc(s) { const d = document.createElement("div"); d.textContent = s; return d.innerHTML; }
app.connect().catch(e => console.error("App connect failed:", e));
</script>
</body>
</html>