Convert-it/Areas/DocumentConverters/Views/PdfToText/Index.cshtml

351 lines
18 KiB
Plaintext

@{
ViewData["Title"] = ViewBag.PageTitle;
Layout = "_Layout";
}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="text-center mb-4">
<h1 class="display-5">@ViewBag.PageTitle</h1>
<p class="lead text-muted">@ViewBag.PageDescription</p>
</div>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-10 col-xl-8">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="bi bi-file-earmark-text me-2"></i>@ViewBag.DocumentMenuTitle
</h5>
</div>
<div class="card-body">
@if (ViewBag.ConversionError != null)
{
<div class="alert alert-danger" role="alert">
<i class="bi bi-exclamation-triangle-fill me-2"></i>
@ViewBag.ConversionError
</div>
}
<ul class="nav nav-tabs mb-4" id="pdfTextTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="plain-text-tab" data-bs-toggle="tab" data-bs-target="#plain-text" type="button" role="tab" aria-controls="plain-text" aria-selected="true">
<i class="bi bi-file-text me-2"></i>@ViewBag.PdfPlainTextTabTitle
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="markdown-tab" data-bs-toggle="tab" data-bs-target="#markdown" type="button" role="tab" aria-controls="markdown" aria-selected="false">
<i class="bi bi-markdown me-2"></i>@ViewBag.PdfMarkdownTabTitle
</button>
</li>
</ul>
<div class="tab-content" id="pdfTextTabContent">
<div class="tab-pane fade show active" id="plain-text" role="tabpanel" aria-labelledby="plain-text-tab">
<form id="plainTextForm" action="/pt-BR/DocumentConverters/PdfToText/ExtractPlainText" method="post" enctype="multipart/form-data" class="needs-validation" novalidate>
<div asp-validation-summary="ModelOnly" class="alert alert-danger" role="alert"></div>
<div class="mb-4">
<label for="plainTextPdfFile" class="form-label fw-semibold">@ViewBag.PdfFileInputLabel</label>
<input class="form-control" type="file" id="plainTextPdfFile" name="pdfFile" accept=".pdf" required>
<div class="invalid-feedback">
@ViewBag.SelectFileError
</div>
</div>
<div class="mb-4">
<label for="plainTextPassword" class="form-label fw-semibold">@ViewBag.PdfPasswordLabel</label>
<input class="form-control" type="password" id="plainTextPassword" name="password" placeholder="@ViewBag.PdfPasswordPlaceholder">
<div class="form-text">
<i class="bi bi-shield-lock me-1"></i>@ViewBag.PdfPasswordHint
</div>
</div>
<div class="d-grid gap-2">
<button type="button" id="previewPlainTextBtn" class="btn btn-primary">
<i class="bi bi-eye me-2"></i>@ViewBag.ExtractPlainTextButton
</button>
<button type="submit" class="btn btn-outline-secondary">
<i class="bi bi-download me-2"></i>@ViewBag.DownloadPlainTextButton
</button>
</div>
</form>
</div>
<div class="tab-pane fade" id="markdown" role="tabpanel" aria-labelledby="markdown-tab">
<form id="markdownForm" action="/pt-BR/DocumentConverters/PdfToText/ExtractMarkdown" method="post" enctype="multipart/form-data" class="needs-validation" novalidate>
<div asp-validation-summary="ModelOnly" class="alert alert-danger" role="alert"></div>
<div class="mb-4">
<label for="markdownPdfFile" class="form-label fw-semibold">@ViewBag.PdfFileInputLabel</label>
<input class="form-control" type="file" id="markdownPdfFile" name="pdfFile" accept=".pdf" required>
<div class="invalid-feedback">
@ViewBag.SelectFileError
</div>
</div>
<div class="mb-4">
<label for="markdownPassword" class="form-label fw-semibold">@ViewBag.PdfPasswordLabel</label>
<input class="form-control" type="password" id="markdownPassword" name="password" placeholder="@ViewBag.PdfPasswordPlaceholder">
<div class="form-text">
<i class="bi bi-shield-lock me-1"></i>@ViewBag.PdfPasswordHint
</div>
</div>
<div class="d-grid gap-2">
<button type="button" id="previewMarkdownBtn" class="btn btn-primary">
<i class="bi bi-eye me-2"></i>@ViewBag.ExtractMarkdownButton
</button>
<button type="submit" class="btn btn-outline-secondary">
<i class="bi bi-download me-2"></i>@ViewBag.DownloadMarkdownButton
</button>
</div>
</form>
</div>
</div>
<div id="loadingSpinner" class="text-center my-4" style="display: none;">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Carregando...</span>
</div>
</div>
<div id="previewArea" class="mt-4" style="display: none;">
<h5 class="mb-3">@ViewBag.PdfTextPreviewTitle</h5>
<textarea id="previewTextArea" class="form-control" rows="12" readonly></textarea>
<div class="text-end mt-3">
<button id="downloadPreviewBtn" class="btn btn-success btn-sm">
<i class="bi bi-box-arrow-down me-2"></i>@ViewBag.DownloadPlainTextButton
</button>
</div>
</div>
<div id="errorArea" class="mt-4" style="display: none;">
<div class="alert alert-warning" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i>
<span id="errorMessage"></span>
<button id="fallbackDownloadBtn" class="btn btn-outline-primary btn-sm ms-2">
@ViewBag.DownloadPlainTextButton
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-5">
<div class="col-lg-10 mx-auto">
<div class="converter-faq">
<h3 class="h4 mb-3 text-center">Perguntas Frequentes</h3>
<div class="accordion" id="pdfTextFaqAccordion">
<div class="accordion-item">
<h2 class="accordion-header" id="faqWhat">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWhat" aria-expanded="false" aria-controls="collapseWhat">
<i class="bi bi-question-circle me-2"></i>@ViewBag.FaqWhatTitle
</button>
</h2>
<div id="collapseWhat" class="accordion-collapse collapse" aria-labelledby="faqWhat" data-bs-parent="#pdfTextFaqAccordion">
<div class="accordion-body">
@ViewBag.FaqWhatContent
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="faqHow">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseHow" aria-expanded="false" aria-controls="collapseHow">
<i class="bi bi-gear me-2"></i>@ViewBag.FaqHowTitle
</button>
</h2>
<div id="collapseHow" class="accordion-collapse collapse" aria-labelledby="faqHow" data-bs-parent="#pdfTextFaqAccordion">
<div class="accordion-body">
@ViewBag.FaqHowContent
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="faqWhy">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWhy" aria-expanded="false" aria-controls="collapseWhy">
<i class="bi bi-lightbulb me-2"></i>@ViewBag.FaqWhyTitle
</button>
</h2>
<div id="collapseWhy" class="accordion-collapse collapse" aria-labelledby="faqWhy" data-bs-parent="#pdfTextFaqAccordion">
<div class="accordion-body">
@ViewBag.FaqWhyContent
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="faqSecurity">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSecurity" aria-expanded="false" aria-controls="collapseSecurity">
<i class="bi bi-shield-check me-2"></i>@ViewBag.FaqSecurityTitle
</button>
</h2>
<div id="collapseSecurity" class="accordion-collapse collapse" aria-labelledby="faqSecurity" data-bs-parent="#pdfTextFaqAccordion">
<div class="accordion-body">
@ViewBag.FaqSecurityContent
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="faqLimits">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseLimits" aria-expanded="false" aria-controls="collapseLimits">
<i class="bi bi-exclamation-triangle me-2"></i>@ViewBag.FaqLimitsTitle
</button>
</h2>
<div id="collapseLimits" class="accordion-collapse collapse" aria-labelledby="faqLimits" data-bs-parent="#pdfTextFaqAccordion">
<div class="accordion-body">
@ViewBag.FaqLimitsContent
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
#previewTextArea {
font-family: monospace;
background-color: #f8f9fa;
}
.spinner-border {
width: 3rem;
height: 3rem;
}
</style>
@section Scripts {
<script>
(function () {
const plainForm = document.getElementById('plainTextForm');
const markdownForm = document.getElementById('markdownForm');
const previewPlainBtn = document.getElementById('previewPlainTextBtn');
const previewMarkdownBtn = document.getElementById('previewMarkdownBtn');
const downloadPreviewBtn = document.getElementById('downloadPreviewBtn');
const fallbackDownloadBtn = document.getElementById('fallbackDownloadBtn');
const loadingSpinner = document.getElementById('loadingSpinner');
const previewArea = document.getElementById('previewArea');
const errorArea = document.getElementById('errorArea');
const previewTextArea = document.getElementById('previewTextArea');
const errorMessage = document.getElementById('errorMessage');
const previewTitleButton = document.getElementById('downloadPreviewBtn');
let previewContent = '';
let previewFileName = 'resultado.txt';
let previewMime = 'text/plain';
const forms = document.querySelectorAll('.needs-validation');
Array.from(forms).forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
});
});
previewPlainBtn.addEventListener('click', function () {
handlePreview(plainForm, 'text/plain');
});
previewMarkdownBtn.addEventListener('click', function () {
handlePreview(markdownForm, 'text/markdown');
});
downloadPreviewBtn.addEventListener('click', function () {
if (!previewContent) {
return;
}
const blob = new Blob([previewContent], { type: previewMime + ';charset=utf-8' });
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = previewFileName;
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
window.URL.revokeObjectURL(url);
});
fallbackDownloadBtn.addEventListener('click', function () {
const activeTab = document.querySelector('.nav-link.active');
const currentForm = activeTab.id === 'plain-text-tab' ? plainForm : markdownForm;
currentForm.submit();
});
function handlePreview(form, mimeType) {
if (!form.checkValidity()) {
form.classList.add('was-validated');
return;
}
showLoading();
const formData = new FormData(form);
const requestUrl = form.action + '?preview=true';
console.log('DEBUG: Requesting URL:', requestUrl);
console.log('DEBUG: Form action:', form.action);
fetch(requestUrl, {
method: 'POST',
body: formData
}).then(async response => {
console.log('DEBUG: Response status:', response.status);
console.log('DEBUG: Response headers:', response.headers.get('content-type'));
const responseText = await response.text();
console.log('DEBUG: Response text (first 200 chars):', responseText.substring(0, 200));
if (!response.ok) {
throw new Error(responseText || response.statusText);
}
const result = JSON.parse(responseText);
if (!result.success) {
throw new Error(result.message || 'Erro na conversão');
}
previewContent = result.content;
previewFileName = result.filename;
previewMime = mimeType;
previewTextArea.value = result.content;
previewTitleButton.innerHTML = `<i class="bi bi-box-arrow-down me-2"></i>${result.format === 'markdown' ? '@ViewBag.DownloadMarkdownButton' : '@ViewBag.DownloadPlainTextButton'}`;
showPreview();
}).catch(error => {
showError(error.message || 'Erro inesperado.');
});
}
function showLoading() {
loadingSpinner.style.display = 'block';
previewArea.style.display = 'none';
errorArea.style.display = 'none';
}
function showPreview() {
loadingSpinner.style.display = 'none';
errorArea.style.display = 'none';
previewArea.style.display = 'block';
}
function showError(message) {
loadingSpinner.style.display = 'none';
previewArea.style.display = 'none';
errorMessage.textContent = message;
errorArea.style.display = 'block';
}
})();
</script>
}