smart-summarizer / webapp /templates /single_summary.html
Rajak13's picture
Make Smart Summarizer fully responsive for all devices - mobile, tablet, desktop (#3)
3293ecf verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Single Summary - Smart Summarizer</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<!-- Top Navigation Bar -->
<nav class="top-navbar">
<a href="/" class="navbar-logo">
<div class="logo-circle">S</div>
<span>Smart Summarizer</span>
</a>
<!-- Mobile Menu Toggle -->
<button class="mobile-menu-toggle" onclick="toggleMobileMenu()">
<i class="fas fa-bars"></i>
</button>
<div class="navbar-links" id="navbarLinks">
<a href="/" class="nav-item">
<i class="fas fa-home"></i> Home
</a>
<a href="/single-summary" class="nav-item active">
<i class="fas fa-file-alt"></i> Single Summary
</a>
<a href="/comparison" class="nav-item">
<i class="fas fa-balance-scale"></i> Comparison
</a>
<a href="/batch" class="nav-item">
<i class="fas fa-layer-group"></i> Batch
</a>
<a href="/evaluation" class="nav-item">
<i class="fas fa-chart-bar"></i> Evaluation
</a>
</div>
</nav>
<i class="fas fa-chart-bar"></i> Evaluation
</a>
</div>
</nav>
<!-- Page Content -->
<div class="page-container">
<h1 class="page-title">Single Model Summary</h1>
<p class="page-subtitle">Input your text and select a specialized model to begin.</p>
<div class="content-grid">
<!-- Input Section -->
<div class="input-section">
<div class="section-label">Input Text</div>
<!-- Input Method Tabs -->
<div class="input-tabs">
<button class="tab-btn active" onclick="switchTab('paste')">Paste Text</button>
<button class="tab-btn" onclick="switchTab('upload')">Upload File</button>
</div>
<!-- Paste Text Tab -->
<div id="paste-tab" class="tab-content active">
<textarea
class="text-input"
id="inputText"
placeholder="Paste your source text here..."
></textarea>
<div class="char-count">
<span id="charCount">0 characters</span>
<span id="wordCount">0 words</span>
</div>
</div>
<!-- Upload File Tab -->
<div id="upload-tab" class="tab-content">
<div class="upload-area" id="uploadArea">
<div class="upload-icon">📄</div>
<p>Drag and drop a file here or click to browse</p>
<p class="upload-hint">Supported formats: .txt, .md, .pdf, .docx, .doc (Max 16MB)</p>
<input type="file" id="fileInput" accept=".txt,.md,.pdf,.docx,.doc" style="display: none;">
</div>
<div id="fileInfo" class="file-info" style="display: none;">
<span id="fileName"></span>
<button class="btn-remove" onclick="removeFile()">Remove</button>
</div>
</div>
</div>
<!-- Output Section -->
<div class="output-section">
<div class="section-label">Output Preview</div>
<div class="output-preview" id="outputPreview">
<div class="icon"></div>
<div>Summary will appear here</div>
</div>
</div>
</div>
<!-- Controls -->
<div class="controls-section">
<select class="model-select" id="modelSelect">
<option value="bart">BART</option>
<option value="textrank">TextRank</option>
<option value="pegasus">PEGASUS</option>
</select>
<button class="btn-generate" id="generateBtn">
Generate Summary
</button>
</div>
</div>
<!-- Footer -->
<footer class="footer">
<div class="footer-left">
<div class="logo-circle" style="width: 24px; height: 24px; font-size: 0.9rem;">S</div>
<span>Smart Summarizer</span>
</div>
<div class="footer-right">
<span>© 2025 Smart Summarizer. Abdul Razzaq Ansari</span>
<a href="https://github.com/Rajak13/Smart-Summarizer" target="_blank" class="footer-link">
<i class="fab fa-github"></i> GitHub Repository
</a>
</div>
</footer>
<script>
const inputText = document.getElementById('inputText');
const charCount = document.getElementById('charCount');
const wordCount = document.getElementById('wordCount');
const generateBtn = document.getElementById('generateBtn');
const modelSelect = document.getElementById('modelSelect');
const outputPreview = document.getElementById('outputPreview');
const fileInput = document.getElementById('fileInput');
const uploadArea = document.getElementById('uploadArea');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
// Tab switching
function switchTab(tab) {
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
if (tab === 'paste') {
document.querySelector('.tab-btn:first-child').classList.add('active');
document.getElementById('paste-tab').classList.add('active');
} else {
document.querySelector('.tab-btn:last-child').classList.add('active');
document.getElementById('upload-tab').classList.add('active');
}
}
// Update character and word count
inputText.addEventListener('input', () => {
const text = inputText.value;
const chars = text.length;
const words = text.trim().split(/\s+/).filter(word => word.length > 0).length;
charCount.textContent = `${chars} characters`;
wordCount.textContent = `${words} words`;
});
// File upload handling
uploadArea.addEventListener('click', () => fileInput.click());
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.style.borderColor = 'var(--slate-blue)';
uploadArea.style.background = 'rgba(109, 129, 150, 0.05)';
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.style.borderColor = 'var(--cool-gray)';
uploadArea.style.background = 'transparent';
});
uploadArea.addEventListener('drop', async (e) => {
e.preventDefault();
uploadArea.style.borderColor = 'var(--cool-gray)';
uploadArea.style.background = 'transparent';
const file = e.dataTransfer.files[0];
if (file) {
await handleFileUpload(file);
}
});
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
if (file) {
await handleFileUpload(file);
}
});
async function handleFileUpload(file) {
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
inputText.value = data.text;
inputText.dispatchEvent(new Event('input'));
fileName.textContent = `${data.filename} (${data.word_count} words)`;
fileInfo.style.display = 'flex';
uploadArea.style.display = 'none';
// Switch to paste tab to show the text
switchTab('paste');
} else {
alert('Error: ' + data.error);
}
} catch (error) {
alert('Failed to upload file. Please try again.');
console.error(error);
}
}
function removeFile() {
fileInput.value = '';
fileInfo.style.display = 'none';
uploadArea.style.display = 'flex';
inputText.value = '';
inputText.dispatchEvent(new Event('input'));
}
// Generate summary
generateBtn.addEventListener('click', async () => {
const text = inputText.value.trim();
const model = modelSelect.value;
if (!text || text.split(/\s+/).length < 10) {
alert('Please enter at least 10 words of text');
return;
}
// Show loading state
generateBtn.disabled = true;
generateBtn.textContent = 'Generating...';
outputPreview.innerHTML = '<div class="spinner"></div><div>Processing your text...</div>';
try {
const response = await fetch('/api/summarize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: text,
model: model
})
});
const data = await response.json();
if (data.success) {
// Display summary
outputPreview.innerHTML = `
<div class="output-text">
<strong>Summary (${model.toUpperCase()}):</strong><br><br>
${data.summary}
<br><br>
<small style="color: var(--slate-blue);">
Processing time: ${data.metadata.processing_time.toFixed(2)}s |
Compression: ${(data.metadata.compression_ratio * 100).toFixed(1)}%
</small>
</div>
`;
} else {
outputPreview.innerHTML = `
<div style="color: #ef4444;">
<strong>Error:</strong> ${data.error}
</div>
`;
}
} catch (error) {
outputPreview.innerHTML = `
<div style="color: #ef4444;">
<strong>Error:</strong> Failed to generate summary. Please try again.
</div>
`;
} finally {
generateBtn.disabled = false;
generateBtn.textContent = 'Generate Summary';
}
});
</script>
<!-- Mobile Menu JavaScript -->
<script src="{{ url_for('static', filename='js/mobile-menu.js') }}"></script>
</body>
</html>