File size: 6,760 Bytes
38a3707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36529d5
 
 
 
 
 
 
38a3707
 
 
 
 
 
 
 
9966b7c
537abbd
9966b7c
 
 
 
 
 
537abbd
9966b7c
 
d537c1b
9966b7c
fa0ef29
d537c1b
 
 
 
 
 
fa0ef29
 
537abbd
 
 
9966b7c
 
 
537abbd
9966b7c
 
 
 
 
d537c1b
 
 
 
9966b7c
537abbd
9966b7c
 
 
d537c1b
 
 
 
537abbd
9966b7c
 
 
 
 
 
537abbd
d537c1b
 
 
 
 
 
 
9966b7c
 
 
 
d537c1b
9966b7c
537abbd
9966b7c
 
 
 
 
207b3fa
 
 
 
 
d537c1b
207b3fa
 
9966b7c
207b3fa
9966b7c
 
 
 
36529d5
 
d537c1b
36529d5
 
 
 
 
 
 
 
 
 
 
 
 
 
9966b7c
 
 
 
d537c1b
9966b7c
38a3707
 
 
fa0ef29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

<!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>