229 lines
7.2 KiB
JavaScript
229 lines
7.2 KiB
JavaScript
/**
|
|
* Document Handler Module (PDF, DOCX, DOC)
|
|
* UPDATED: Updates workflow progress after document load
|
|
*/
|
|
|
|
function initPdfHandler() {
|
|
const uploadZone = document.getElementById('uploadZone');
|
|
const docInput = document.getElementById('docInput');
|
|
|
|
if (!uploadZone || !docInput) return;
|
|
|
|
uploadZone.addEventListener('click', (e) => {
|
|
if (e.target.closest('button')) return;
|
|
docInput.click();
|
|
});
|
|
|
|
docInput.addEventListener('change', (e) => {
|
|
const file = e.target.files[0];
|
|
if (file) {
|
|
handleDocumentFile(file);
|
|
}
|
|
});
|
|
|
|
uploadZone.addEventListener('dragover', (e) => {
|
|
e.preventDefault();
|
|
uploadZone.classList.add('drag-over');
|
|
});
|
|
|
|
uploadZone.addEventListener('dragleave', () => {
|
|
uploadZone.classList.remove('drag-over');
|
|
});
|
|
|
|
uploadZone.addEventListener('drop', (e) => {
|
|
e.preventDefault();
|
|
uploadZone.classList.remove('drag-over');
|
|
|
|
const files = e.dataTransfer.files;
|
|
if (files.length > 0) {
|
|
const file = files[0];
|
|
const name = file.name.toLowerCase();
|
|
|
|
if (name.endsWith('.pdf') || name.endsWith('.docx') || name.endsWith('.doc')) {
|
|
handleDocumentFile(file);
|
|
} else {
|
|
alert('Please drop a valid PDF, DOCX, or DOC file.');
|
|
}
|
|
}
|
|
});
|
|
|
|
console.log('📄 Document handler initialized (PDF, DOCX, DOC)');
|
|
}
|
|
|
|
function handleDocumentFile(file) {
|
|
const name = file.name.toLowerCase();
|
|
|
|
if (name.endsWith('.pdf')) {
|
|
handlePdfFile(file);
|
|
} else if (name.endsWith('.docx') || name.endsWith('.doc')) {
|
|
handleWordFile(file);
|
|
} else {
|
|
alert('Unsupported file type. Please upload a PDF, DOCX, or DOC file.');
|
|
}
|
|
}
|
|
|
|
async function handlePdfFile(file) {
|
|
if (!file.name.toLowerCase().endsWith('.pdf')) {
|
|
alert('Please select a valid PDF file.');
|
|
return;
|
|
}
|
|
|
|
showLoader('Processing PDF...', `Extracting content from ${file.name}`);
|
|
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
try {
|
|
const response = await fetch('/api/upload-pdf', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
|
|
console.log(`✅ PDF processed: ${data.page_count} pages, ${data.blocks.length} blocks`);
|
|
|
|
const projectName = file.name.replace('.pdf', '');
|
|
document.getElementById('projectName').value = projectName;
|
|
currentProject.name = projectName;
|
|
|
|
renderDocumentBlocks(data.blocks);
|
|
|
|
document.getElementById('uploadSection').style.display = 'none';
|
|
document.getElementById('editorSection').style.display = 'block';
|
|
|
|
hideLoader();
|
|
showNotification(`PDF processed: ${data.blocks.length} blocks extracted`, 'success');
|
|
updateWorkflowProgress('edit');
|
|
|
|
} catch (error) {
|
|
hideLoader();
|
|
console.error('PDF processing error:', error);
|
|
alert('Failed to process PDF: ' + error.message);
|
|
}
|
|
}
|
|
|
|
async function handleWordFile(file) {
|
|
const name = file.name.toLowerCase();
|
|
if (!name.endsWith('.docx') && !name.endsWith('.doc')) {
|
|
alert('Please select a valid DOCX or DOC file.');
|
|
return;
|
|
}
|
|
|
|
const fileType = name.endsWith('.docx') ? 'DOCX' : 'DOC';
|
|
showLoader(`Processing ${fileType}...`, `Extracting content from ${file.name}`);
|
|
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
try {
|
|
const response = await fetch('/api/upload-docx', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
|
|
console.log(`✅ ${fileType} processed: ${data.blocks.length} blocks`);
|
|
|
|
const projectName = file.name.replace(/\.(docx|doc)$/i, '');
|
|
document.getElementById('projectName').value = projectName;
|
|
currentProject.name = projectName;
|
|
|
|
renderDocumentBlocks(data.blocks);
|
|
|
|
document.getElementById('uploadSection').style.display = 'none';
|
|
document.getElementById('editorSection').style.display = 'block';
|
|
|
|
hideLoader();
|
|
showNotification(`${fileType} processed: ${data.blocks.length} blocks extracted`, 'success');
|
|
updateWorkflowProgress('edit');
|
|
|
|
} catch (error) {
|
|
hideLoader();
|
|
console.error(`${fileType} processing error:`, error);
|
|
alert(`Failed to process ${fileType}: ` + error.message);
|
|
}
|
|
}
|
|
|
|
function renderDocumentBlocks(blocks) {
|
|
const editor = document.getElementById('markdownEditor');
|
|
editor.innerHTML = '';
|
|
editorBlocks = [];
|
|
|
|
const emptyMessage = document.getElementById('emptyEditorMessage');
|
|
if (emptyMessage) {
|
|
emptyMessage.style.display = 'none';
|
|
}
|
|
|
|
addChapterMarker(1);
|
|
|
|
for (const block of blocks) {
|
|
let type = 'paragraph';
|
|
let content = block.content || '';
|
|
|
|
if (block.type === 'image') {
|
|
type = 'image';
|
|
} else if (block.type === 'heading1' || content.startsWith('# ')) {
|
|
type = 'heading1';
|
|
} else if (block.type === 'heading2' || content.startsWith('## ')) {
|
|
type = 'heading2';
|
|
} else if (block.type === 'heading3' || content.startsWith('### ')) {
|
|
type = 'heading3';
|
|
} else if (block.type === 'list_item' || content.startsWith('- ')) {
|
|
type = 'bulletList';
|
|
} else if (block.type === 'quote' || content.startsWith('> ')) {
|
|
type = 'quote';
|
|
} else if (block.type === 'table') {
|
|
type = 'table';
|
|
}
|
|
|
|
let images = [];
|
|
if (block.type === 'image' && block.data) {
|
|
images = [{
|
|
data: block.data,
|
|
format: block.format || 'png',
|
|
alt_text: 'Document Image',
|
|
position: 'before'
|
|
}];
|
|
content = ``;
|
|
}
|
|
|
|
const lastChild = editor.lastElementChild;
|
|
const blockId = addBlock(type, content, lastChild, images);
|
|
|
|
if (block.type === 'image' && block.data) {
|
|
const blockEl = document.getElementById(blockId);
|
|
if (blockEl) {
|
|
const contentDiv = blockEl.querySelector('.md-block-content');
|
|
if (contentDiv) {
|
|
contentDiv.innerHTML = `
|
|
<div class="image-block">
|
|
<img src="data:image/${block.format || 'png'};base64,${block.data}" alt="Document Image">
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
}
|
|
|
|
const blockEl = document.getElementById(blockId);
|
|
if (blockEl) {
|
|
ensureNewBlockLineAfter(blockEl);
|
|
}
|
|
}
|
|
|
|
repairAllNewBlockLines();
|
|
}
|
|
|
|
function renderPdfBlocks(blocks) {
|
|
renderDocumentBlocks(blocks);
|
|
}
|