SanyamV's picture
undefined - Initial Deployment
6d16687 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQL Query Agent</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>
.chat-container {
height: calc(100vh - 200px);
}
.file-dropzone {
border: 2px dashed #cbd5e0;
transition: all 0.3s ease;
}
.file-dropzone.active {
border-color: #4f46e5;
background-color: #eef2ff;
}
.result-table {
max-height: 300px;
overflow-y: auto;
}
.typing-indicator span {
animation: bounce 1.5s infinite ease-in-out;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.sql-editor {
font-family: 'Courier New', monospace;
min-height: 100px;
}
</style>
</head>
<body class="bg-gray-50">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="mb-8">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-3">
<i class="fas fa-database text-3xl text-indigo-600"></i>
<h1 class="text-2xl font-bold text-gray-800">SQL Query Agent</h1>
</div>
<div class="flex space-x-4">
<button id="darkModeToggle" class="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700">
<i class="fas fa-moon text-gray-600"></i>
</button>
<button class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition">
<i class="fas fa-question-circle mr-2"></i>Help
</button>
</div>
</div>
<p class="text-gray-600 mt-2">Upload your Excel file or connect to a database to start querying</p>
</header>
<!-- Main Content -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Left Panel - Data Source Selection -->
<div class="lg:col-span-1 bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Data Sources</h2>
<!-- Tabs -->
<div class="flex border-b mb-6">
<button id="excelTab" class="tab-btn active px-4 py-2 font-medium text-indigo-600 border-b-2 border-indigo-600">
<i class="fas fa-file-excel mr-2"></i>Excel File
</button>
<button id="sqlTab" class="tab-btn px-4 py-2 font-medium text-gray-500 hover:text-gray-700">
<i class="fas fa-database mr-2"></i>SQL Database
</button>
</div>
<!-- Excel Upload Section -->
<div id="excelSection" class="data-source-section">
<div id="fileDropzone" class="file-dropzone rounded-lg p-8 text-center mb-4 cursor-pointer">
<i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
<p class="text-gray-600">Drag & drop your Excel file here</p>
<p class="text-sm text-gray-500 mt-1">or click to browse files</p>
<input type="file" id="fileInput" class="hidden" accept=".xlsx, .xls, .csv">
</div>
<div id="fileInfo" class="hidden p-4 bg-gray-50 rounded-lg mb-4">
<div class="flex justify-between items-center">
<div>
<p class="font-medium text-gray-800" id="fileName">sample_data.xlsx</p>
<p class="text-sm text-gray-500" id="fileSize">2.4 MB</p>
</div>
<button id="removeFile" class="text-red-500 hover:text-red-700">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Sheet Selection</label>
<select id="sheetSelect" class="w-full p-2 border border-gray-300 rounded-lg" disabled>
<option value="">Select a sheet</option>
</select>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Preview</label>
<div class="bg-gray-50 p-2 rounded-lg border border-gray-200 overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead id="previewHeader" class="bg-gray-100">
<!-- Headers will be populated here -->
</thead>
<tbody id="previewBody" class="divide-y divide-gray-200">
<!-- Preview rows will be populated here -->
</tbody>
</table>
</div>
</div>
</div>
<!-- SQL Connection Section -->
<div id="sqlSection" class="data-source-section hidden">
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Database Type</label>
<select class="w-full p-2 border border-gray-300 rounded-lg">
<option>MySQL</option>
<option>PostgreSQL</option>
<option>SQL Server</option>
<option>SQLite</option>
<option>Oracle</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Host</label>
<input type="text" class="w-full p-2 border border-gray-300 rounded-lg" placeholder="localhost">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Port</label>
<input type="text" class="w-full p-2 border border-gray-300 rounded-lg" placeholder="3306">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Database Name</label>
<input type="text" class="w-full p-2 border border-gray-300 rounded-lg" placeholder="my_database">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Username</label>
<input type="text" class="w-full p-2 border border-gray-300 rounded-lg" placeholder="username">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<input type="password" class="w-full p-2 border border-gray-300 rounded-lg" placeholder="••••••••">
</div>
<button class="w-full py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition">
<i class="fas fa-plug mr-2"></i>Connect
</button>
</div>
</div>
<div class="mt-6 pt-4 border-t border-gray-200">
<h3 class="text-sm font-medium text-gray-700 mb-2">Recent Connections</h3>
<div class="space-y-2">
<div class="flex items-center p-2 hover:bg-gray-50 rounded-lg cursor-pointer">
<i class="fas fa-file-excel text-green-500 mr-3"></i>
<div>
<p class="text-sm font-medium">sales_data.xlsx</p>
<p class="text-xs text-gray-500">Yesterday</p>
</div>
</div>
<div class="flex items-center p-2 hover:bg-gray-50 rounded-lg cursor-pointer">
<i class="fas fa-database text-blue-500 mr-3"></i>
<div>
<p class="text-sm font-medium">Production DB</p>
<p class="text-xs text-gray-500">2 days ago</p>
</div>
</div>
</div>
</div>
</div>
<!-- Right Panel - Chat Interface -->
<div class="lg:col-span-2 bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-800">Query Assistant</h2>
<p class="text-sm text-gray-600">Ask questions about your data in natural language or write SQL queries</p>
</div>
<!-- Chat Container -->
<div class="chat-container overflow-y-auto p-4 space-y-4">
<!-- Welcome Message -->
<div class="flex justify-start">
<div class="max-w-[80%] bg-indigo-50 rounded-lg p-4">
<div class="flex items-start">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-indigo-100 flex items-center justify-center">
<i class="fas fa-robot text-indigo-600"></i>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-indigo-800">SQL Assistant</h3>
<div class="mt-1 text-sm text-gray-700">
<p>Hello! I can help you analyze your data. Please upload an Excel file or connect to a database to get started.</p>
<p class="mt-2">You can ask questions like:</p>
<ul class="list-disc pl-5 mt-1 space-y-1">
<li>"Show me the top 5 customers by sales"</li>
<li>"What's the average order value?"</li>
<li>"Find all orders from last month"</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Sample User Message -->
<div class="flex justify-end">
<div class="max-w-[80%] bg-indigo-600 rounded-lg p-4 text-white">
<p>Show me the top 5 products by revenue</p>
</div>
</div>
<!-- Sample Assistant Response -->
<div class="flex justify-start">
<div class="max-w-[80%] bg-gray-50 rounded-lg p-4">
<div class="flex items-start">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-gray-100 flex items-center justify-center">
<i class="fas fa-robot text-gray-600"></i>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-gray-800">SQL Assistant</h3>
<div class="mt-1 text-sm text-gray-700">
<p>Here are the top 5 products by revenue:</p>
<div class="result-table mt-2 border border-gray-200 rounded-lg overflow-hidden">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Product</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Revenue</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr>
<td class="px-4 py-2">Premium Widget</td>
<td class="px-4 py-2">$12,450</td>
</tr>
<tr>
<td class="px-4 py-2">Basic Widget</td>
<td class="px-4 py-2">$8,720</td>
</tr>
<tr>
<td class="px-4 py-2">Deluxe Package</td>
<td class="px-4 py-2">$7,890</td>
</tr>
<tr>
<td class="px-4 py-2">Standard Package</td>
<td class="px-4 py-2">$5,430</td>
</tr>
<tr>
<td class="px-4 py-2">Add-on Service</td>
<td class="px-4 py-2">$3,210</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-3 text-xs text-gray-500">
<p>Generated SQL: <code class="bg-gray-200 px-1 rounded">SELECT product_name, SUM(revenue) as revenue FROM sales GROUP BY product_name ORDER BY revenue DESC LIMIT 5</code></p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Typing Indicator (hidden by default) -->
<div id="typingIndicator" class="flex justify-start hidden">
<div class="max-w-[80%] bg-gray-50 rounded-lg p-4">
<div class="flex items-center">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-gray-100 flex items-center justify-center">
<i class="fas fa-robot text-gray-600"></i>
</div>
<div class="ml-3 typing-indicator">
<span class="inline-block h-2 w-2 rounded-full bg-gray-400 mx-1"></span>
<span class="inline-block h-2 w-2 rounded-full bg-gray-400 mx-1"></span>
<span class="inline-block h-2 w-2 rounded-full bg-gray-400 mx-1"></span>
</div>
</div>
</div>
</div>
</div>
<!-- Input Area -->
<div class="border-t border-gray-200 p-4 bg-gray-50">
<div class="flex items-start space-x-2">
<div class="flex-grow">
<div class="relative">
<div id="sqlEditor" class="sql-editor w-full p-3 border border-gray-300 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" contenteditable="true" placeholder="Type your question or SQL query here..."></div>
<div class="absolute right-2 bottom-2 flex space-x-1">
<button class="p-1 text-gray-500 hover:text-indigo-600">
<i class="fas fa-magic"></i>
</button>
<button class="p-1 text-gray-500 hover:text-indigo-600">
<i class="fas fa-history"></i>
</button>
</div>
</div>
<div class="flex items-center justify-between mt-2">
<div class="flex space-x-2">
<button class="p-1 text-gray-500 hover:text-indigo-600">
<i class="fas fa-paperclip"></i>
</button>
<button class="p-1 text-gray-500 hover:text-indigo-600">
<i class="fas fa-code"></i>
</button>
</div>
<div class="text-xs text-gray-500">
<span id="charCount">0</span>/1000
</div>
</div>
</div>
<button id="sendButton" class="flex-shrink-0 h-12 w-12 rounded-full bg-indigo-600 text-white flex items-center justify-center hover:bg-indigo-700 transition">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Tab switching functionality
const excelTab = document.getElementById('excelTab');
const sqlTab = document.getElementById('sqlTab');
const excelSection = document.getElementById('excelSection');
const sqlSection = document.getElementById('sqlSection');
excelTab.addEventListener('click', () => {
excelTab.classList.add('active', 'text-indigo-600', 'border-indigo-600');
excelTab.classList.remove('text-gray-500');
sqlTab.classList.remove('active', 'text-indigo-600', 'border-indigo-600');
sqlTab.classList.add('text-gray-500');
excelSection.classList.remove('hidden');
sqlSection.classList.add('hidden');
});
sqlTab.addEventListener('click', () => {
sqlTab.classList.add('active', 'text-indigo-600', 'border-indigo-600');
sqlTab.classList.remove('text-gray-500');
excelTab.classList.remove('active', 'text-indigo-600', 'border-indigo-600');
excelTab.classList.add('text-gray-500');
sqlSection.classList.remove('hidden');
excelSection.classList.add('hidden');
});
// File upload functionality
const fileDropzone = document.getElementById('fileDropzone');
const fileInput = document.getElementById('fileInput');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const removeFile = document.getElementById('removeFile');
const sheetSelect = document.getElementById('sheetSelect');
fileDropzone.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
const file = e.target.files[0];
fileName.textContent = file.name;
fileSize.textContent = `${(file.size / (1024 * 1024)).toFixed(1)} MB`;
fileInfo.classList.remove('hidden');
fileDropzone.classList.add('hidden');
// Simulate sheet selection (in a real app, you'd parse the Excel file)
sheetSelect.innerHTML = `
<option value="">Select a sheet</option>
<option value="Sheet1">Sheet1</option>
<option value="Sheet2">Sheet2</option>
<option value="Orders">Orders</option>
`;
sheetSelect.disabled = false;
}
});
removeFile.addEventListener('click', () => {
fileInput.value = '';
fileInfo.classList.add('hidden');
fileDropzone.classList.remove('hidden');
sheetSelect.innerHTML = '<option value="">Select a sheet</option>';
sheetSelect.disabled = true;
// Clear preview
document.getElementById('previewHeader').innerHTML = '';
document.getElementById('previewBody').innerHTML = '';
});
// Drag and drop functionality
fileDropzone.addEventListener('dragover', (e) => {
e.preventDefault();
fileDropzone.classList.add('active');
});
fileDropzone.addEventListener('dragleave', () => {
fileDropzone.classList.remove('active');
});
fileDropzone.addEventListener('drop', (e) => {
e.preventDefault();
fileDropzone.classList.remove('active');
if (e.dataTransfer.files.length > 0) {
fileInput.files = e.dataTransfer.files;
const event = new Event('change');
fileInput.dispatchEvent(event);
}
});
// Sheet selection change
sheetSelect.addEventListener('change', (e) => {
if (e.target.value) {
// Simulate loading data for the selected sheet
const headers = ['ID', 'Product', 'Category', 'Price', 'Quantity'];
const data = [
[1, 'Premium Widget', 'Widgets', 49.99, 120],
[2, 'Basic Widget', 'Widgets', 19.99, 350],
[3, 'Deluxe Package', 'Packages', 199.99, 45],
[4, 'Standard Package', 'Packages', 99.99, 80],
[5, 'Add-on Service', 'Services', 29.99, 210]
];
const previewHeader = document.getElementById('previewHeader');
const previewBody = document.getElementById('previewBody');
// Build header
previewHeader.innerHTML = '';
const headerRow = document.createElement('tr');
headers.forEach(header => {
const th = document.createElement('th');
th.className = 'px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase';
th.textContent = header;
headerRow.appendChild(th);
});
previewHeader.appendChild(headerRow);
// Build body
previewBody.innerHTML = '';
data.forEach(row => {
const tr = document.createElement('tr');
row.forEach(cell => {
const td = document.createElement('td');
td.className = 'px-4 py-2 text-sm text-gray-700';
td.textContent = cell;
tr.appendChild(td);
});
previewBody.appendChild(tr);
});
}
});
// Chat functionality
const sqlEditor = document.getElementById('sqlEditor');
const sendButton = document.getElementById('sendButton');
const typingIndicator = document.getElementById('typingIndicator');
const charCount = document.getElementById('charCount');
// Character count
sqlEditor.addEventListener('input', () => {
charCount.textContent = sqlEditor.textContent.length;
});
// Send message
sendButton.addEventListener('click', () => {
const message = sqlEditor.textContent.trim();
if (message) {
// Add user message to chat
const chatContainer = document.querySelector('.chat-container');
const userMessage = document.createElement('div');
userMessage.className = 'flex justify-end';
userMessage.innerHTML = `
<div class="max-w-[80%] bg-indigo-600 rounded-lg p-4 text-white">
<p>${message}</p>
</div>
`;
chatContainer.appendChild(userMessage);
// Clear input
sqlEditor.textContent = '';
charCount.textContent = '0';
// Show typing indicator
typingIndicator.classList.remove('hidden');
// Scroll to bottom
chatContainer.scrollTop = chatContainer.scrollHeight;
// Simulate assistant response after delay
setTimeout(() => {
typingIndicator.classList.add('hidden');
// Create assistant response
const assistantResponse = document.createElement('div');
assistantResponse.className = 'flex justify-start';
assistantResponse.innerHTML = `
<div class="max-w-[80%] bg-gray-50 rounded-lg p-4">
<div class="flex items-start">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-gray-100 flex items-center justify-center">
<i class="fas fa-robot text-gray-600"></i>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-gray-800">SQL Assistant</h3>
<div class="mt-1 text-sm text-gray-700">
<p>Here are the results for your query:</p>
<div class="result-table mt-2 border border-gray-200 rounded-lg overflow-hidden">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Column 1</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Column 2</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Column 3</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr>
<td class="px-4 py-2">Value 1</td>
<td class="px-4 py-2">Value 2</td>
<td class="px-4 py-2">Value 3</td>
</tr>
<tr>
<td class="px-4 py-2">Value 4</td>
<td class="px-4 py-2">Value 5</td>
<td class="px-4 py-2">Value 6</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-3 text-xs text-gray-500">
<p>Generated SQL: <code class="bg-gray-200 px-1 rounded">SELECT * FROM ${sheetSelect.value || 'your_data'} WHERE condition</code></p>
</div>
</div>
</div>
</div>
</div>
`;
chatContainer.appendChild(assistantResponse);
// Scroll to bottom
chatContainer.scrollTop = chatContainer.scrollHeight;
}, 1500);
}
});
// Dark mode toggle
const darkModeToggle = document.getElementById('darkModeToggle');
darkModeToggle.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
const icon = darkModeToggle.querySelector('i');
if (document.documentElement.classList.contains('dark')) {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
icon.classList.remove('text-gray-600');
icon.classList.add('text-yellow-300');
} else {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
icon.classList.remove('text-yellow-300');
icon.classList.add('text-gray-600');
}
});
</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=SanyamV/sql-query-agent-project" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>