textclarity / static /index.html
ganna217's picture
update
80ec3ce
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TexClarity</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Griffy&display=swap" rel="stylesheet">
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #000, #1a1a2e);
color: #fff;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
min-height: 100vh;
}
.container {
max-width: 1000px;
width: 100%;
}
h1 {
font-family: 'Griffy', cursive;
font-size: 2em;
margin-bottom: 0;
margin-top: 10px;
position: absolute;
top: 20px;
left: 20px;
color: #fff;
text-align: left;
box-shadow: 0 0 5px rgba(78, 121, 230, 0.2);
padding: 5px 10px;
border-radius: 5px;
animation: glow 2s infinite;
}
@keyframes glow {
0% { box-shadow: 0 0 5px rgba(78, 121, 230, 0.2); }
50% { box-shadow: 0 0 8px rgba(78, 121, 230, 0.4); }
100% { box-shadow: 0 0 5px rgba(78, 121, 230, 0.2); }
}
h2 {
font-family: 'Verdana', sans-serif;
font-size: 1.8em;
font-weight: normal;
margin-top: 30px;
}
h1, h2 {
color: #fff;
text-align: left;
}
.input-section {
margin-top: 60px;
margin-bottom: 20px;
}
textarea {
width: 100%;
height: 250px;
padding: 15px;
margin-bottom: 10px;
border: none;
border-radius: 8px;
background: #e0e0e0;
color: #333;
font-size: 1.2em;
box-sizing: border-box;
box-shadow: 0 0 10px rgba(78, 121, 230, 0.3);
transition: box-shadow 0.3s;
}
textarea:focus {
box-shadow: 0 0 15px rgba(78, 121, 230, 0.6);
}
.labels-section {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
}
.labels-section label {
font-size: 1.2em;
}
input {
flex: 2;
padding: 15px;
border: 2px solid #4e79e6;
border-radius: 8px;
background: #e0e0e0;
color: #333;
font-size: 1.2em;
box-shadow: 0 0 8px rgba(78, 121, 230, 0.3);
transition: box-shadow 0.3s;
}
input:focus {
box-shadow: 0 0 8px rgba(78, 121, 230, 0.5);
}
button {
background: linear-gradient(135deg, #2c5aa0, #4e79e6);
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1.1em;
box-shadow: 0 0 15px rgba(78, 121, 230, 0.5);
animation: pulse 2s infinite;
transition: transform 0.2s;
}
button:hover {
transform: scale(1.05);
box-shadow: 0 0 20px rgba(78, 121, 230, 0.8);
}
@keyframes pulse {
0% { box-shadow: 0 0 15px rgba(78, 121, 230, 0.5); }
50% { box-shadow: 0 0 25px rgba(78, 121, 230, 0.8); }
100% { box-shadow: 0 0 15px rgba(78, 121, 230, 0.5); }
}
.results {
display: flex;
flex-direction: column;
gap: 20px;
}
table {
width: 100%;
border-collapse: collapse;
background: linear-gradient(135deg, #000, #1a1a2e);
border-radius: 8px;
overflow: hidden;
}
th, td {
padding: 12px;
text-align: left;
color: #fff;
}
th {
font-weight: bold;
}
.chart-container {
display: none;
position: relative;
height: 300px;
background: linear-gradient(135deg, #000, #1a1a2e);
border-radius: 8px;
padding: 10px;
}
.loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #4e79e6;
font-size: 3.5em;
display: none;
}
.loading::after {
content: '...';
animation: dots 1.5s infinite;
}
@keyframes dots {
0% { content: '.'; }
33% { content: '..'; }
66% { content: '...'; }
}
@media (max-width: 768px) {
.container {
padding: 10px;
}
textarea, input, button {
font-size: 1em;
}
.labels-section {
flex-direction: column;
align-items: flex-start;
}
button {
width: 100%;
}
h1 {
font-size: 1.5em;
top: 10px;
left: 10px;
}
h2 {
margin-top: 20px;
font-size: 1.4em;
}
.input-section {
margin-top: 40px;
}
.loading {
font-size: 2.5em;
}
}
</style>
</head>
<body>
<div class="container">
<h1>TexClarity</h1>
<h2>Make your text analysis clearer</h2>
<div class="input-section">
<textarea id="document" placeholder="Enter your text here..."></textarea>
<div class="labels-section">
<label>Labels:</label>
<input type="text" id="labels" placeholder="Enter labels (comma-separated)">
<button id="classifyBtn">Classify</button>
</div>
</div>
<div class="results">
<table id="results-table">
<thead>
<tr>
<th>Label</th>
<th>Score</th>
</tr>
</thead>
<tbody></tbody>
</table>
<div class="chart-container">
<canvas id="resultsChart"></canvas>
</div>
</div>
</div>
<div id="loading" class="loading"></div>
<script>
let chartInstance = null;
const textarea = document.getElementById('document');
textarea.addEventListener('focus', function() {
if (this.value === this.getAttribute('placeholder')) {
this.value = '';
}
});
textarea.addEventListener('blur', function() {
if (!this.value) {
this.value = this.getAttribute('placeholder');
}
});
document.getElementById("classifyBtn").addEventListener("click", classifyText);
async function classifyText() {
const textInput = document.getElementById('document').value;
const labelsInput = document.getElementById('labels').value;
const loadingElement = document.getElementById('loading');
const chartContainer = document.querySelector('.chart-container');
// Validate inputs
if (!textInput || textInput === textarea.getAttribute('placeholder')) {
alert('Please enter some text to classify.');
return;
}
if (!labelsInput) {
alert('Please enter at least one label.');
return;
}
// Keep labels as a comma-separated string (as expected by the backend)
const labels = labelsInput.trim();
console.log("Sending request with text:", textInput.substring(0, 50) + "...");
console.log("Labels:", labels);
loadingElement.style.display = 'block';
chartContainer.style.display = 'none';
try {
const response = await fetch('/classify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ document: textInput, labels: labels }),
});
console.log("Response status:", response.status);
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Classification failed with status ${response.status}: ${errorText}`);
}
const rawResults = await response.json();
console.log("Raw response:", JSON.stringify(rawResults, null, 2)); // Formatted JSON
// Handle both array and object responses
let results;
if (Array.isArray(rawResults)) {
results = rawResults[0];
} else {
results = rawResults;
}
console.log("Processed results:", JSON.stringify(results, null, 2)); // Formatted JSON
if (results.error) {
throw new Error(results.error);
}
if (!results.labels || !results.scores) {
throw new Error("Invalid response format: 'labels' or 'scores' missing");
}
updateTable(results);
updateChart(results);
chartContainer.style.display = 'block';
} catch (error) {
console.error("Error during classification:", error);
alert('Error: ' + error.message);
} finally {
loadingElement.style.display = 'none';
}
}
function updateTable(results) {
const tbody = document.querySelector('#results-table tbody');
tbody.innerHTML = '';
// If labels is a single string, split it manually based on the input
let labelsArray = [];
if (typeof results.labels === 'string') {
labelsArray = results.labels.split(',').map(label => label.trim());
} else if (Array.isArray(results.labels)) {
labelsArray = results.labels; // Use the original array if it's already split
} else {
console.warn("Unexpected labels format:", results.labels);
labelsArray = [results.labels.toString()]; // Fallback
}
// Use the first score (since the model might return one score for all labels)
const score = results.scores.length > 0 ? results.scores[0].toFixed(3) : '0.000';
// Create a row for each label with the same score
if (labelsArray.length === 0) {
console.warn("No labels to display");
return;
}
labelsArray.forEach((label) => {
const row = document.createElement('tr');
row.innerHTML = `<td>${label}</td><td>${score}</td>`;
tbody.appendChild(row);
});
}
function updateChart(results) {
const ctx = document.getElementById('resultsChart').getContext('2d');
if (chartInstance) chartInstance.destroy();
// If labels is a single string, split it manually for the chart
let labelsArray = [];
if (typeof results.labels === 'string') {
labelsArray = results.labels.split(',').map(label => label.trim());
} else if (Array.isArray(results.labels)) {
labelsArray = results.labels;
} else {
labelsArray = [results.labels.toString()];
}
// Create scores array with the same length as labelsArray
const score = results.scores.length > 0 ? results.scores[0] : 0;
const scoresArray = Array(labelsArray.length).fill(score);
chartInstance = new Chart(ctx, {
type: 'bar',
data: {
labels: labelsArray,
datasets: [{
label: 'Scores',
data: scoresArray,
backgroundColor: '#4e79e6',
borderColor: '#6a8de9',
borderWidth: 1
}]
},
options: {
scales: { y: { beginAtZero: true, max: 1 } },
plugins: { legend: { display: false } }
}
});
}
</script>
</body>
</html>