conv / index.html
Ultronprime's picture
Add 3 files
16ef808 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Conversation Analysis Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.fade-in {
animation: fadeIn 0.3s ease-out forwards;
}
.sidebar {
transition: transform 0.3s ease-in-out;
}
.sidebar-open {
transform: translateX(0);
}
@media (max-width: 768px) {
.sidebar {
transform: translateX(-100%);
position: fixed;
top: 0;
left: 0;
z-index: 40;
height: 100vh;
}
.sidebar-open {
transform: translateX(0);
}
}
.conversation-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.progress-bar {
transition: width 0.5s ease;
}
.modal-overlay {
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
max-height: 90vh;
}
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>
</head>
<body class="bg-gray-50 font-sans antialiased">
<!-- Mobile menu button -->
<div class="md:hidden fixed top-4 left-4 z-50">
<button id="mobileMenuBtn" class="p-2 rounded-md bg-white shadow-md text-gray-700">
<i class="fas fa-bars"></i>
</button>
</div>
<!-- Sidebar -->
<div id="sidebar" class="sidebar w-64 bg-white border-r border-gray-200 fixed h-full overflow-y-auto">
<div class="p-4 border-b border-gray-200">
<div class="flex items-center space-x-2">
<div class="bg-purple-600 text-white p-2 rounded-lg">
<i class="fas fa-comments text-xl"></i>
</div>
<h1 class="text-xl font-bold text-gray-800">ConvoAnalyzer</h1>
</div>
<p class="text-xs text-gray-500 mt-1">Conversation Analysis Dashboard</p>
</div>
<div class="p-4 space-y-6">
<div>
<h3 class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">Configuration</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Worker Count</label>
<div class="flex items-center space-x-2">
<input id="workerCount" type="range" min="1" max="8" value="4" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
<span id="workerCountDisplay" class="text-sm font-medium text-gray-700 w-8 text-center">4</span>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Analysis Model</label>
<select id="modelSelect" class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md">
<option value="default">Default Model</option>
<option value="advanced">Advanced Model</option>
<option value="custom">Custom Model</option>
</select>
</div>
</div>
</div>
<div>
<h3 class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">Actions</h3>
<div class="space-y-2">
<button id="uploadBtn" class="w-full flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500">
<i class="fas fa-upload mr-2"></i> Upload Conversations
</button>
<button id="startAnalysisBtn" class="w-full flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-purple-700 bg-white hover:bg-purple-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500">
<i class="fas fa-play mr-2"></i> Start Analysis
</button>
<div class="flex space-x-2">
<button id="pauseBtn" disabled class="flex-1 flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-gray-700 bg-gray-200 opacity-50 cursor-not-allowed">
<i class="fas fa-pause mr-2"></i> Pause
</button>
<button id="stopBtn" disabled class="flex-1 flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 opacity-50 cursor-not-allowed hover:bg-red-700">
<i class="fas fa-stop mr-2"></i> Stop
</button>
</div>
<button id="downloadBtn" class="w-full flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
<i class="fas fa-download mr-2"></i> Download Results
</button>
</div>
</div>
<div>
<h3 class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">Agent Status</h3>
<div class="space-y-2">
<div class="flex items-center justify-between p-2 bg-gray-50 rounded-md">
<div class="flex items-center space-x-2">
<i class="fas fa-smile text-blue-500"></i>
<span class="text-sm font-medium text-gray-700">Sentiment</span>
</div>
<span id="sentimentStatus" class="text-sm font-medium text-gray-600">Idle</span>
</div>
<div class="flex items-center justify-between p-2 bg-gray-50 rounded-md">
<div class="flex items-center space-x-2">
<i class="fas fa-tags text-blue-500"></i>
<span class="text-sm font-medium text-gray-700">Topic</span>
</div>
<span id="topicStatus" class="text-sm font-medium text-gray-600">Idle</span>
</div>
<div class="flex items-center justify-between p-2 bg-gray-50 rounded-md">
<div class="flex items-center space-x-2">
<i class="fas fa-tasks text-blue-500"></i>
<span class="text-sm font-medium text-gray-700">Progress</span>
</div>
<span id="progressStatus" class="text-sm font-medium text-gray-600">Idle</span>
</div>
<div class="flex items-center justify-between p-2 bg-gray-50 rounded-md">
<div class="flex items-center space-x-2">
<i class="fas fa-file-alt text-blue-500"></i>
<span class="text-sm font-medium text-gray-700">Summary</span>
</div>
<span id="summaryStatus" class="text-sm font-medium text-gray-600">Idle</span>
</div>
</div>
</div>
</div>
</div>
<!-- Main content -->
<div class="md:ml-64">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Header -->
<div class="pt-6 pb-4">
<div class="flex flex-col md:flex-row md:items-center md:justify-between">
<h2 class="text-2xl font-bold leading-tight text-gray-900">Conversation Analysis Dashboard</h2>
<div class="mt-2 md:mt-0 flex items-center space-x-2">
<span class="text-sm text-gray-500">Last run:</span>
<span id="lastRunTime" class="text-sm font-medium text-gray-700">Never</span>
</div>
</div>
</div>
<!-- Stats -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-green-500 rounded-md p-3">
<i class="fas fa-check-circle text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Completed</dt>
<dd class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">
<span id="completedCount">0</span>
</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-red-500 rounded-md p-3">
<i class="fas fa-exclamation-circle text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Errors</dt>
<dd class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">
<span id="errorCount">0</span>
</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-blue-500 rounded-md p-3">
<i class="fas fa-spinner text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Processing</dt>
<dd class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">
<span id="processingCount">0</span>
</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-purple-500 rounded-md p-3">
<i class="fas fa-chart-line text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Progress</dt>
<dd class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">
<span id="progressPercent">0</span>%
</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
<!-- Progress bar -->
<div class="mb-6">
<div class="flex justify-between mb-1">
<span class="text-sm font-medium text-gray-700">Analysis Progress</span>
<span class="text-sm font-medium text-gray-700"><span id="progressPercent2">0</span>%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="progressBar" class="progress-bar bg-purple-600 h-2.5 rounded-full" style="width: 0%"></div>
</div>
</div>
<!-- Agent Counts -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div class="bg-white p-4 rounded-lg shadow">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-md bg-blue-100 text-blue-600">
<i class="fas fa-smile"></i>
</div>
<span class="text-sm font-medium text-gray-700">Sentiment</span>
</div>
<span id="sentimentCount" class="text-lg font-bold text-gray-900">0</span>
</div>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-md bg-green-100 text-green-600">
<i class="fas fa-tags"></i>
</div>
<span class="text-sm font-medium text-gray-700">Topics</span>
</div>
<span id="topicCount" class="text-lg font-bold text-gray-900">0</span>
</div>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-md bg-purple-100 text-purple-600">
<i class="fas fa-tasks"></i>
</div>
<span class="text-sm font-medium text-gray-700">Progress</span>
</div>
<span id="progressCount" class="text-lg font-bold text-gray-900">0</span>
</div>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-md bg-yellow-100 text-yellow-600">
<i class="fas fa-file-alt"></i>
</div>
<span class="text-sm font-medium text-gray-700">Summaries</span>
</div>
<span id="summaryCount" class="text-lg font-bold text-gray-900">0</span>
</div>
</div>
</div>
<!-- Visualizations -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div class="bg-white p-4 rounded-lg shadow">
<div id="sentimentChart">
<h4 class="font-medium text-gray-900 mb-3">Sentiment Distribution</h4>
<div class="text-center py-10 text-gray-400">
<i class="fas fa-chart-pie text-2xl mb-2"></i>
<p class="text-sm">No sentiment data available yet</p>
</div>
</div>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<div id="topicChart">
<h4 class="font-medium text-gray-900 mb-3">Top Topics</h4>
<div class="text-center py-10 text-gray-400">
<i class="fas fa-chart-bar text-2xl mb-2"></i>
<p class="text-sm">No topic data available yet</p>
</div>
</div>
</div>
</div>
<!-- Results section -->
<div class="bg-white shadow rounded-lg overflow-hidden mb-6">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<div class="flex flex-col md:flex-row md:items-center md:justify-between">
<h3 class="text-lg font-medium leading-6 text-gray-900">Conversation Results</h3>
<p class="mt-1 text-sm text-gray-500 md:mt-0">
Showing <span id="showingCount" class="font-medium">0</span> of <span id="totalCount" class="font-medium">0</span> conversations
</p>
</div>
</div>
<div id="conversationResults" class="divide-y divide-gray-200">
<div class="text-center py-10 text-gray-400">
<i class="fas fa-comments text-4xl mb-2"></i>
<p>No analysis results yet. Start the analysis to see results here.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Upload Modal -->
<div id="uploadModal" class="fixed z-50 inset-0 overflow-y-auto hidden">
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity modal-overlay" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-purple-100 sm:mx-0 sm:h-10 sm:w-10">
<i class="fas fa-file-upload text-purple-600"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<h3 class="text-lg leading-6 font-medium text-gray-900">Upload Conversations</h3>
<div class="mt-4">
<div class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-md">
<div class="space-y-1 text-center">
<div class="flex text-sm text-gray-600">
<label for="fileUpload" class="relative cursor-pointer bg-white rounded-md font-medium text-purple-600 hover:text-purple-500 focus-within:outline-none">
<span>Upload a file</span>
<input id="fileUpload" name="fileUpload" type="file" class="sr-only">
</label>
<p class="pl-1">or drag and drop</p>
</div>
<p class="text-xs text-gray-500">CSV, JSON, or TXT files up to 10MB</p>
</div>
</div>
<div class="mt-4">
<p class="text-sm text-gray-500">Selected file: <span id="fileNameDisplay" class="font-medium">None</span></p>
</div>
<div class="mt-4">
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="uploadProgress" class="bg-purple-600 h-2.5 rounded-full" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button id="confirmUpload" type="button" disabled class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-purple-600 text-base font-medium text-white hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 sm:ml-3 sm:w-auto sm:text-sm">
Upload and Extract
</button>
<button id="closeUploadModal" type="button" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
<!-- Analysis Details Modal -->
<div id="analysisModal" class="fixed z-50 inset-0 overflow-y-auto hidden">
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity modal-overlay" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<i class="fas fa-chart-bar text-blue-600"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<h3 class="text-lg leading-6 font-medium text-gray-900">Conversation Analysis Details</h3>
<div class="mt-4">
<div class="bg-gray-50 p-4 rounded-lg mb-4">
<h4 class="font-medium text-gray-900 mb-2">Summary</h4>
<p id="modalSummary" class="text-sm text-gray-700">Loading summary...</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<h4 class="font-medium text-gray-900 mb-2">Success Indicators</h4>
<div id="successIndicators" class="space-y-2">
<div class="bg-green-50 border border-green-100 p-3 rounded-lg">
<p class="text-sm text-green-800">Positive engagement throughout the conversation</p>
</div>
<div class="bg-green-50 border border-green-100 p-3 rounded-lg">
<p class="text-sm text-green-800">Clear communication of key points</p>
</div>
</div>
</div>
<div>
<h4 class="font-medium text-gray-900 mb-2">Struggle Indicators</h4>
<div id="struggleIndicators" class="space-y-2">
<div class="bg-red-50 border border-red-100 p-3 rounded-lg">
<p class="text-sm text-red-800">Some confusion around technical terms</p>
</div>
</div>
</div>
</div>
<div class="mb-4">
<h4 class="font-medium text-gray-900 mb-2">Main Topics</h4>
<div id="mainTopics" class="flex flex-wrap gap-1">
<span class="inline-block bg-white px-2 py-1 rounded-md text-xs mr-1 mb-1">Product Features</span>
<span class="inline-block bg-white px-2 py-1 rounded-md text-xs mr-1 mb-1">Pricing</span>
<span class="inline-block bg-white px-2 py-1 rounded-md text-xs mr-1 mb-1">Implementation</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-gray-50 p-3 rounded-lg">
<h4 class="font-medium text-gray-900 mb-2">Sentiment Trend</h4>
<div class="flex items-center">
<i class="fas fa-smile text-green-600 text-sm mr-2"></i>
<span id="sentimentTrend" class="text-sm font-medium text-green-600">Mostly Positive</span>
</div>
</div>
<div class="bg-gray-50 p-3 rounded-lg">
<h4 class="font-medium text-gray-900 mb-2">Key Learning</h4>
<p id="keyLearning" class="text-sm text-gray-700">The customer was particularly interested in integration capabilities with their existing systems.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button id="closeModal" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
Close
</button>
</div>
</div>
</div>
</div>
<script>
// DOM Elements
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const sidebar = document.getElementById('sidebar');
const workerCountInput = document.getElementById('workerCount');
const workerCountDisplay = document.getElementById('workerCountDisplay');
const uploadBtn = document.getElementById('uploadBtn');
const uploadModal = document.getElementById('uploadModal');
const closeUploadModalBtn = document.getElementById('closeUploadModal');
const fileUploadInput = document.getElementById('fileUpload');
const fileNameDisplay = document.getElementById('fileNameDisplay');
const confirmUploadBtn = document.getElementById('confirmUpload');
const uploadProgress = document.getElementById('uploadProgress');
const startAnalysisBtn = document.getElementById('startAnalysisBtn');
const lastRunTimeSpan = document.getElementById('lastRunTime');
const completedCountSpan = document.getElementById('completedCount');
const errorCountSpan = document.getElementById('errorCount');
const processingCountSpan = document.getElementById('processingCount');
const progressPercentSpan = document.getElementById('progressPercent');
const progressPercentSpan2 = document.getElementById('progressPercent2');
const progressBarDiv = document.getElementById('progressBar');
const sentimentCountSpan = document.getElementById('sentimentCount');
const topicCountSpan = document.getElementById('topicCount');
const progressCountSpan = document.getElementById('progressCount');
const summaryCountSpan = document.getElementById('summaryCount');
const sentimentStatusSpan = document.getElementById('sentimentStatus');
const topicStatusSpan = document.getElementById('topicStatus');
const progressStatusSpan = document.getElementById('progressStatus');
const summaryStatusSpan = document.getElementById('summaryStatus');
const resultsContainer = document.getElementById('conversationResults');
const showingCountSpan = document.getElementById('showingCount');
const totalCountSpan = document.getElementById('totalCount');
const analysisModal = document.getElementById('analysisModal');
const closeModalBtn = document.getElementById('closeModal');
const modalSummary = document.getElementById('modalSummary');
const successIndicatorsDiv = document.getElementById('successIndicators');
const struggleIndicatorsDiv = document.getElementById('struggleIndicators');
const mainTopicsDiv = document.getElementById('mainTopics');
const sentimentTrendSpan = document.getElementById('sentimentTrend');
const sentimentTrendIcon = document.querySelector('#sentimentTrend').previousElementSibling;
const keyLearningPara = document.getElementById('keyLearning');
const downloadBtn = document.getElementById('downloadBtn');
const pauseBtn = document.getElementById('pauseBtn');
const stopBtn = document.getElementById('stopBtn');
const modelSelect = document.getElementById('modelSelect');
const sentimentChartDiv = document.getElementById('sentimentChart');
const topicChartDiv = document.getElementById('topicChart');
// Sample data for demonstration
const sampleResults = [
{
filename: "Customer Support Call - 2023-05-15",
date: "May 15, 2023",
sentiment: "Positive",
summary_snippet: "The customer was satisfied with the resolution provided and appreciated the quick response time.",
topics: ["Support", "Resolution", "Response Time"],
exchanges: 12,
has_details: true
},
{
filename: "Sales Demo - Acme Corp",
date: "May 10, 2023",
sentiment: "Neutral",
summary_snippet: "The prospect showed interest in the product but had concerns about pricing and implementation timeline.",
topics: ["Pricing", "Implementation", "Features"],
exchanges: 24,
has_details: true
},
{
filename: "Team Meeting - Project Kickoff",
date: "May 5, 2023",
sentiment: "Positive",
summary_snippet: "The team aligned on project goals and timelines with clear action items assigned.",
topics: ["Goals", "Timelines", "Action Items"],
exchanges: 18,
has_details: true
}
];
// Event Listeners
mobileMenuBtn.addEventListener('click', function() {
sidebar.classList.toggle('sidebar-open');
});
// Close sidebar when clicking outside on mobile
document.addEventListener('click', function(event) {
if (!sidebar.contains(event.target) && !mobileMenuBtn.contains(event.target) && sidebar.classList.contains('sidebar-open') && window.innerWidth <= 768) {
sidebar.classList.remove('sidebar-open');
}
});
// Worker count display
workerCountInput.addEventListener('input', function() {
workerCountDisplay.textContent = this.value;
});
// File upload modal
uploadBtn.addEventListener('click', function() {
uploadModal.classList.remove('hidden');
});
closeUploadModalBtn.addEventListener('click', function() {
uploadModal.classList.add('hidden');
resetUploadModal();
});
// Reset upload modal UI
function resetUploadModal() {
fileUploadInput.value = '';
fileNameDisplay.textContent = 'None';
confirmUploadBtn.disabled = true;
uploadProgress.style.width = '0%';
}
// File selection handler
fileUploadInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
fileNameDisplay.textContent = file.name;
confirmUploadBtn.disabled = false;
} else {
resetUploadModal();
}
});
// Confirm upload button
confirmUploadBtn.addEventListener('click', function() {
const file = fileUploadInput.files[0];
if (!file) return;
// Simulate upload progress
let progress = 0;
const interval = setInterval(() => {
progress += 10;
uploadProgress.style.width = `${progress}%`;
if (progress >= 100) {
clearInterval(interval);
setTimeout(() => {
// Update UI with sample data
totalCountSpan.textContent = sampleResults.length;
showingCountSpan.textContent = 0;
// Reset analysis progress
completedCountSpan.textContent = '0';
errorCountSpan.textContent = '0';
processingCountSpan.textContent = '0';
progressPercentSpan.textContent = '0';
progressPercentSpan2.textContent = '0';
progressBarDiv.style.width = '0%';
// Update agent statuses
updateAgentStatuses("Ready");
// Close modal after upload
uploadModal.classList.add('hidden');
resetUploadModal();
// Show success message
alert('File uploaded successfully! 3 conversations extracted.');
}, 500);
}
}, 200);
});
// Update agent statuses
function updateAgentStatuses(status) {
const statusInfo = {
"Idle": { text: "Idle", color: "gray" },
"Ready": { text: "Ready", color: "blue" },
"Active": { text: "Active", color: "blue" },
"Completed": { text: "Completed", color: "green" },
"Error": { text: "Error", color: "red" }
};
const currentStatus = statusInfo[status] || statusInfo["Idle"];
sentimentStatusSpan.textContent = currentStatus.text;
sentimentStatusSpan.className = `text-sm font-medium text-${currentStatus.color}-600`;
topicStatusSpan.textContent = currentStatus.text;
topicStatusSpan.className = `text-sm font-medium text-${currentStatus.color}-600`;
progressStatusSpan.textContent = currentStatus.text;
progressStatusSpan.className = `text-sm font-medium text-${currentStatus.color}-600`;
summaryStatusSpan.textContent = currentStatus.text;
summaryStatusSpan.className = `text-sm font-medium text-${currentStatus.color}-600`;
}
// Start analysis button
startAnalysisBtn.addEventListener('click', function() {
const model = modelSelect.value;
// Disable button and show loading
startAnalysisBtn.disabled = true;
startAnalysisBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Starting...';
startAnalysisBtn.classList.add('opacity-50', 'cursor-not-allowed');
// Simulate analysis progress
setTimeout(() => {
// Update last run time
lastRunTimeSpan.textContent = new Date().toLocaleString();
// Update agent statuses
updateAgentStatuses("Active");
// Enable pause/stop buttons
pauseBtn.disabled = false;
stopBtn.disabled = false;
// Simulate analysis progress
let progress = 0;
const analysisInterval = setInterval(() => {
progress += 5;
// Update progress
progressPercentSpan.textContent = progress;
progressPercentSpan2.textContent = progress;
progressBarDiv.style.width = `${progress}%`;
// Update counts
completedCountSpan.textContent = Math.floor(progress / 100 * sampleResults.length);
processingCountSpan.textContent = sampleResults.length - Math.floor(progress / 100 * sampleResults.length);
// Update agent counts
sentimentCountSpan.textContent = Math.floor(progress / 30);
topicCountSpan.textContent = Math.floor(progress / 25);
progressCountSpan.textContent = Math.floor(progress / 20);
summaryCountSpan.textContent = Math.floor(progress / 35);
// When analysis completes
if (progress >= 100) {
clearInterval(analysisInterval);
// Update UI for completion
updateAgentStatuses("Completed");
startAnalysisBtn.disabled = false;
startAnalysisBtn.innerHTML = '<i class="fas fa-check mr-2"></i> Analysis Complete';
startAnalysisBtn.classList.remove('opacity-50', 'cursor-not-allowed');
startAnalysisBtn.classList.add('bg-green-100', 'text-green-700', 'hover:bg-green-200');
// Disable pause/stop buttons
pauseBtn.disabled = true;
stopBtn.disabled = true;
// Show results
updateResultsList();
updateVisualizations();
}
}, 300);
}, 1000);
});
// Update results list
function updateResultsList() {
resultsContainer.innerHTML = '';
sampleResults.forEach((result, index) => {
const card = document.createElement('div');
card.className = 'conversation-card bg-white border border-gray-200 rounded-lg overflow-hidden shadow-sm transition cursor-pointer mb-4 fade-in';
card.style.animationDelay = `${index * 0.1}s`;
// Determine sentiment color
let sentimentClass = 'bg-gray-100 text-gray-800';
if (result.sentiment.toLowerCase() === 'positive') {
sentimentClass = 'bg-green-100 text-green-800';
} else if (result.sentiment.toLowerCase() === 'negative') {
sentimentClass = 'bg-red-100 text-red-800';
}
card.innerHTML = `
<div class="p-4 border-b border-gray-200">
<div class="flex justify-between items-start">
<div>
<h4 class="font-medium text-gray-900 truncate">${result.filename}</h4>
<p class="text-xs text-gray-500 mt-1">${result.date}</p>
</div>
<span class="px-2 py-1 rounded-full text-xs font-medium ${sentimentClass}">
${result.sentiment}
</span>
</div>
</div>
<div class="p-4">
<p class="text-sm text-gray-600 line-clamp-2">${result.summary_snippet}</p>
<div class="mt-3 flex flex-wrap gap-1">
${result.topics.map(topic =>
`<span class="inline-block bg-gray-100 px-2 py-1 rounded-md text-xs">${topic}</span>`
).join('')}
</div>
</div>
<div class="px-4 py-2 bg-gray-50 border-t border-gray-200 flex justify-between items-center">
<span class="text-xs text-gray-500">${result.exchanges} exchanges</span>
<button class="text-blue-600 hover:text-blue-800 text-sm font-medium" data-filename="${result.filename}">
View Details
</button>
</div>
`;
// Add click handler to show modal
const detailButton = card.querySelector('button');
detailButton.addEventListener('click', function(e) {
e.stopPropagation();
showAnalysisModal(result.filename);
});
card.addEventListener('click', function() {
showAnalysisModal(result.filename);
});
resultsContainer.appendChild(card);
});
showingCountSpan.textContent = sampleResults.length;
totalCountSpan.textContent = sampleResults.length;
}
// Show analysis modal with details
function showAnalysisModal(filename) {
// Find the selected conversation
const conversation = sampleResults.find(r => r.filename === filename);
if (!conversation) return;
// Update modal content
modalSummary.textContent = conversation.summary_snippet;
// Update success indicators
successIndicatorsDiv.innerHTML = `
<div class="bg-green-50 border border-green-100 p-3 rounded-lg">
<p class="text-sm text-green-800">Positive engagement throughout the conversation</p>
</div>
<div class="bg-green-50 border border-green-100 p-3 rounded-lg">
<p class="text-sm text-green-800">Clear communication of key points</p>
</div>
`;
// Update struggle indicators
struggleIndicatorsDiv.innerHTML = `
<div class="bg-red-50 border border-red-100 p-3 rounded-lg">
<p class="text-sm text-red-800">Some confusion around technical terms</p>
</div>
`;
// Update main topics
mainTopicsDiv.innerHTML = conversation.topics.map(topic =>
`<span class="inline-block bg-white px-2 py-1 rounded-md text-xs mr-1 mb-1">${topic}</span>`
).join('');
// Update sentiment trend
let sentimentIcon, sentimentColor, sentimentText;
if (conversation.sentiment.toLowerCase() === 'positive') {
sentimentIcon = 'fa-smile text-green-600';
sentimentColor = 'text-green-600';
sentimentText = 'Mostly Positive';
} else if (conversation.sentiment.toLowerCase() === 'negative') {
sentimentIcon = 'fa-frown text-red-600';
sentimentColor = 'text-red-600';
sentimentText = 'Mostly Negative';
} else {
sentimentIcon = 'fa-meh text-gray-500';
sentimentColor = 'text-gray-600';
sentimentText = 'Neutral';
}
sentimentTrendIcon.className = `fas ${sentimentIcon} text-sm mr-2`;
sentimentTrendSpan.textContent = sentimentText;
sentimentTrendSpan.className = `text-sm font-medium ${sentimentColor}`;
// Update key learning
keyLearningPara.textContent = "The customer was particularly interested in integration capabilities with their existing systems.";
// Show modal
analysisModal.classList.remove('hidden');
}
// Close modal
closeModalBtn.addEventListener('click', function() {
analysisModal.classList.add('hidden');
});
// Download results
downloadBtn.addEventListener('click', function() {
alert('Downloading analysis results...');
});
// Pause analysis
pauseBtn.addEventListener('click', function() {
alert('Analysis paused. Click Start to resume.');
updateAgentStatuses("Ready");
});
// Stop analysis
stopBtn.addEventListener('click', function() {
if (confirm('Are you sure you want to stop the analysis? Progress will be saved.')) {
alert('Analysis stopped.');
updateAgentStatuses("Ready");
}
});
// Update visualizations
function updateVisualizations() {
// Sentiment distribution
const sentimentCounts = sampleResults.reduce((acc, res) => {
const sentiment = res.sentiment || 'N/A';
acc[sentiment] = (acc[sentiment] || 0) + 1;
return acc;
}, {});
let sentimentHtml = '<h4 class="font-medium text-gray-900 mb-3">Sentiment Distribution</h4>';
sentimentHtml += '<ul class="list-disc list-inside text-sm text-gray-700">';
for (const [sentiment, count] of Object.entries(sentimentCounts)) {
let colorClass = 'text-gray-600';
if (sentiment.toLowerCase() === 'positive') colorClass = 'text-green-600';
else if (sentiment.toLowerCase() === 'negative') colorClass = 'text-red-600';
sentimentHtml += `<li class="${colorClass}">${sentiment}: ${count}</li>`;
}
sentimentHtml += '</ul>';
sentimentChartDiv.innerHTML = sentimentHtml;
// Top topics
const allTopics = sampleResults.flatMap(res => res.topics || []);
const topicCounts = allTopics.reduce((acc, topic) => {
acc[topic] = (acc[topic] || 0) + 1;
return acc;
}, {});
const sortedTopics = Object.entries(topicCounts).sort(([, a], [, b]) => b - a);
let topicHtml = '<h4 class="font-medium text-gray-900 mb-3">Top Topics</h4>';
topicHtml += '<ul class="list-disc list-inside text-sm text-gray-700">';
sortedTopics.slice(0, 5).forEach(([topic, count]) => {
topicHtml += `<li>${topic}: ${count}</li>`;
});
topicHtml += '</ul>';
topicChartDiv.innerHTML = topicHtml;
}
// Initialize
document.addEventListener('DOMContentLoaded', function() {
// Set initial values
workerCountDisplay.textContent = workerCountInput.value;
lastRunTimeSpan.textContent = 'Never';
// Add fade-in class to cards when they're added
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.classList && node.classList.contains('conversation-card')) {
node.classList.add('fade-in');
}
});
});
});
observer.observe(resultsContainer, {
childList: true,
subtree: true
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Ultronprime/conv" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>