chunker / index.html
prashantmatlani's picture
updated changes in phase0102 and in main
207b3fa
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jung Chunker UI</title>
<style>
:root { --bg: #fdf6e3; --text: #586e75; --accent: #268bd2; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; height: 100vh; }
/* Sidebar for the Tree */
#sidebar { width: 350px; border-right: 1px solid #ddd; overflow-y: auto; padding: 20px; background: #eee8d5; }
#viewer { flex-grow: 1; padding: 40px; overflow-y: auto; line-height: 1.6; }
.tree-node { margin-left: 15px; border-left: 2px solid #ccc; padding-left: 10px; margin-bottom: 10px; }
.summary-block { font-weight: bold; color: var(--accent); cursor: pointer; display: block; margin-top: 15px; }
.leaf-node { font-size: 0.9em; cursor: pointer; color: #657b83; display: block; margin: 5px 0; }
.leaf-node:hover { text-decoration: underline; }
h1 { font-size: 1.2em; border-bottom: 1px solid #ccc; padding-bottom: 10px; }
.chunk-content { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.upload-section { margin-bottom: 20px; padding: 15px; background: #fff; border-radius: 5px; }
/* Styling for different levels */
.summary_l1 { color: #268bd2; font-weight: bold; margin-left: 10px; border-left: 2px solid #268bd2; }
.summary_l2 { color: #d33682; font-weight: 800; margin-left: 5px; border-left: 4px solid #d33682; font-size: 1.1em; }
.summary_l3 { color: #b58900; font-weight: 900; text-transform: uppercase; border: 2px solid #b58900; padding: 5px; text-align: center; }
.leaf-node { color: #657b83; margin-left: 20px; font-size: 0.9em; }
</style>
</head>
<body>
<div id="sidebar">
<h1>Jungian Chunker</h1>
<div class="upload-section">
<input type="file" id="pdfUpload" accept=".pdf"><br><br>
<label><input type="radio" name="mode" value="range" checked onclick="toggleRange(true)"> Page Range</label>
<label><input type="radio" name="mode" value="whole" onclick="toggleRange(false)"> Whole Book</label>
<div id="range-inputs" style="margin-top:10px;">
<input type="number" id="startP" placeholder="Start" style="width:50px">
<input type="number" id="endP" placeholder="End" style="width:50px">
</div>
<button onclick="uploadFile()" style="margin-top:10px; width:100%;">Process Jungian Tree</button>
<div id="status" style="font-size: 0.8em; margin-top: 10px; color: var(--accent);">Status: Idle</div>
<!-- Download Button -->
<button id="downloadBtn" style="display:none; margin-top:10px; background:#2aa198; color:white; border:none; padding:10px; cursor:pointer; width:100%;">
πŸ“₯ Download Knowledge Tree
</button>
</div>
<div id="tree-container"></div>
</div>
<script>
function toggleRange(show) {
document.getElementById('range-inputs').style.display = show ? 'block' : 'none';
}
async function uploadFile() {
const fileInput = document.getElementById('pdfUpload');
const isWhole = document.querySelector('input[name="mode"]:checked').value === 'whole';
const status = document.getElementById('status');
// Explicitly grab the values from the inputs
const startVal = document.getElementById('startP').value;
const endVal = document.getElementById('endP').value;
if (fileInput.files.length === 0) return alert("Please select a PDF");
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('whole', isWhole);
formData.append('start', startVal || 20); // Fallback to 20 if empty
formData.append('end', endVal || 30); // Fallback to 30 if empty
console.log("Sending Range:", startVal, "to", endVal); // Check browser console
status.innerText = "Status: Uploading...";
await fetch('/upload', { method: 'POST', body: formData });
status.innerText = "Status: Processing (Waiting for first chunk...)";
listenToStream();
}
// --- VIEW function ---
function view(title, text) {
const display = document.getElementById('content-display');
display.innerHTML = `<h2>${title}</h2><div style="white-space: pre-wrap;">${text}</div>`;
}
// --- listenToStream Function --
function listenToStream() {
const eventSource = new EventSource('/stream');
const container = document.getElementById('tree-container');
const status = document.getElementById('status');
const dlBtn = document.getElementById('downloadBtn');
container.innerHTML = "";
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'done') {
status.innerText = "βœ… EXTRACTION FINISHED!";
//dlBtn.style.display = "block"; // Show the button
//dlBtn.onclick = () => window.location.href = '/download-latest';
//eventSource.close();
//return;
const dlBtn = document.getElementById('downloadBtn');
dlBtn.style.display = "block"; // Show the button
dlBtn.innerHTML = "πŸ“₯ Download All Files (.zip)";
dlBtn.onclick = () => window.location.href = '/download-all'; // Points to the ZIP endpoint
eventSource.close();
}
// Add Leaf or Summary to the UI
const node = document.createElement('div');
//node.className = data.type === 'summary' ? "tree-node summary-block" : "tree-node leaf-node";
//node.innerHTML = (data.type === 'summary' ? "⭐ " : "∟ ") + (data.name || data.filename);
// Pass the content to the view function when clicked
//node.onclick = () => view(data.name || data.filename, data.content);
node.className = `tree-node ${data.type}`; // Uses summary_l1, summary_l2, etc.
let prefix = "∟ ";
if (data.type === 'summary_l1') prefix = "⭐ ";
if (data.type === 'summary_l2') prefix = "πŸ’Ž ";
if (data.type === 'summary_l3') prefix = "πŸ‘‘ ";
//node.innerHTML = prefix + data.name;
// innerHTML with "OR" check
node.innerHTML = prefix + (data.name || data.filename || "Untitled Chunk");
node.onclick = () => view(data.name, data.content);
container.appendChild(node);
status.innerText = `Status: Created ${data.type}...`;
};
}
</script>
</body>
</html>