Spaces:
Running
Running
Upload src/app/giao_dien/text_to_sql_dashboard/code.html with huggingface_hub
Browse files
src/app/giao_dien/text_to_sql_dashboard/code.html
CHANGED
|
@@ -234,10 +234,31 @@
|
|
| 234 |
</div>
|
| 235 |
<!-- Sample Mode Content -->
|
| 236 |
<div class="space-y-4" id="source-sample">
|
|
|
|
| 237 |
<h3 class="font-label-caps text-label-caps text-secondary uppercase" id="schema-title">Active Schema: ...</h3>
|
| 238 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
<pre id="schema-block">Loading schema...</pre>
|
| 240 |
</div>
|
|
|
|
| 241 |
</div>
|
| 242 |
<!-- Upload Mode Content (Hidden by default) -->
|
| 243 |
<div class="hidden space-y-4" id="source-upload">
|
|
@@ -455,6 +476,7 @@
|
|
| 455 |
}
|
| 456 |
|
| 457 |
toggleDataSource(meta.mode === 'uploaded' ? 'upload' : 'sample');
|
|
|
|
| 458 |
loadModels();
|
| 459 |
}
|
| 460 |
|
|
@@ -572,6 +594,62 @@
|
|
| 572 |
}
|
| 573 |
});
|
| 574 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 575 |
// ---- Banners (validator block / execution error) ----
|
| 576 |
function renderBanners(data) {
|
| 577 |
const container = document.getElementById('banners');
|
|
|
|
| 234 |
</div>
|
| 235 |
<!-- Sample Mode Content -->
|
| 236 |
<div class="space-y-4" id="source-sample">
|
| 237 |
+
<div class="flex items-center justify-between">
|
| 238 |
<h3 class="font-label-caps text-label-caps text-secondary uppercase" id="schema-title">Active Schema: ...</h3>
|
| 239 |
+
<select class="px-2 py-1 border border-border-subtle rounded text-status-badge font-status-badge bg-white text-on-surface" id="sample-table-select" title="Select table to preview"></select>
|
| 240 |
+
</div>
|
| 241 |
+
<!-- Data preview table (same style as upload preview) -->
|
| 242 |
+
<div id="sample-preview-wrap">
|
| 243 |
+
<div class="overflow-x-auto rounded border border-border-subtle">
|
| 244 |
+
<table class="w-full text-left font-body-sm text-body-sm" id="sample-preview-table">
|
| 245 |
+
<thead class="bg-surface-container-high border-b border-border-subtle font-code-block uppercase text-[11px]"><tr></tr></thead>
|
| 246 |
+
<tbody class="divide-y divide-border-subtle bg-white"></tbody>
|
| 247 |
+
</table>
|
| 248 |
+
</div>
|
| 249 |
+
<div class="flex items-center justify-between mt-3">
|
| 250 |
+
<button class="px-3 py-1 border border-border-subtle rounded text-body-sm font-label-caps text-label-caps uppercase bg-white hover:bg-surface-container-low disabled:opacity-40 disabled:cursor-not-allowed" disabled id="sample-prev-btn">‹ Previous</button>
|
| 251 |
+
<span class="text-body-sm text-secondary" id="sample-page-label">Loading...</span>
|
| 252 |
+
<button class="px-3 py-1 border border-border-subtle rounded text-body-sm font-label-caps text-label-caps uppercase bg-white hover:bg-surface-container-low disabled:opacity-40 disabled:cursor-not-allowed" disabled id="sample-next-btn">Next ›</button>
|
| 253 |
+
</div>
|
| 254 |
+
</div>
|
| 255 |
+
<!-- Schema string (collapsible) -->
|
| 256 |
+
<details class="mt-1">
|
| 257 |
+
<summary class="font-label-caps text-label-caps text-secondary uppercase cursor-pointer select-none hover:text-primary transition-colors text-[11px]">View schema string</summary>
|
| 258 |
+
<div class="bg-code-bg border border-border-subtle p-4 rounded font-code-block text-code-block text-on-surface-variant overflow-x-auto mt-2">
|
| 259 |
<pre id="schema-block">Loading schema...</pre>
|
| 260 |
</div>
|
| 261 |
+
</details>
|
| 262 |
</div>
|
| 263 |
<!-- Upload Mode Content (Hidden by default) -->
|
| 264 |
<div class="hidden space-y-4" id="source-upload">
|
|
|
|
| 476 |
}
|
| 477 |
|
| 478 |
toggleDataSource(meta.mode === 'uploaded' ? 'upload' : 'sample');
|
| 479 |
+
if (meta.mode !== 'uploaded') loadSamplePreview();
|
| 480 |
loadModels();
|
| 481 |
}
|
| 482 |
|
|
|
|
| 594 |
}
|
| 595 |
});
|
| 596 |
|
| 597 |
+
// ---- Sample database table preview ----
|
| 598 |
+
let samplePreviewState = { columns: [], rows: [], rowCount: 0, tableNames: [], activeTable: '', page: 0 };
|
| 599 |
+
|
| 600 |
+
async function loadSamplePreview(table) {
|
| 601 |
+
try {
|
| 602 |
+
const url = `${API_BASE}/api/preview` + (table ? `?table=${encodeURIComponent(table)}` : '');
|
| 603 |
+
const res = await fetch(url);
|
| 604 |
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
| 605 |
+
const data = await res.json();
|
| 606 |
+
samplePreviewState = { columns: data.columns, rows: data.rows, rowCount: data.row_count,
|
| 607 |
+
truncated: data.truncated, tableNames: data.table_names, activeTable: data.active_table, page: 0 };
|
| 608 |
+
|
| 609 |
+
const sel = document.getElementById('sample-table-select');
|
| 610 |
+
sel.innerHTML = samplePreviewState.tableNames.map(t =>
|
| 611 |
+
`<option value="${t}" ${t === data.active_table ? 'selected' : ''}>${t}</option>`
|
| 612 |
+
).join('');
|
| 613 |
+
|
| 614 |
+
renderSamplePreviewPage();
|
| 615 |
+
} catch (err) {
|
| 616 |
+
console.error('Failed to load sample preview:', err);
|
| 617 |
+
}
|
| 618 |
+
}
|
| 619 |
+
|
| 620 |
+
function renderSamplePreviewPage() {
|
| 621 |
+
const { columns, rows, rowCount, page } = samplePreviewState;
|
| 622 |
+
const totalPages = Math.max(1, Math.ceil(rows.length / PREVIEW_PAGE_SIZE));
|
| 623 |
+
const start = page * PREVIEW_PAGE_SIZE;
|
| 624 |
+
const pageRows = rows.slice(start, start + PREVIEW_PAGE_SIZE);
|
| 625 |
+
|
| 626 |
+
const thead = document.querySelector('#sample-preview-table thead tr');
|
| 627 |
+
thead.innerHTML = columns.map(c => `<th class="px-4 py-2 border-r border-border-subtle">${escapeHtml(String(c))}</th>`).join('');
|
| 628 |
+
|
| 629 |
+
const tbody = document.querySelector('#sample-preview-table tbody');
|
| 630 |
+
tbody.innerHTML = pageRows.map(row =>
|
| 631 |
+
`<tr class="hover:bg-surface-container-low">${row.map(v =>
|
| 632 |
+
`<td class="px-4 py-2 border-r border-border-subtle">${escapeHtml(v === null ? '' : String(v))}</td>`
|
| 633 |
+
).join('')}</tr>`
|
| 634 |
+
).join('');
|
| 635 |
+
|
| 636 |
+
document.getElementById('sample-page-label').textContent =
|
| 637 |
+
`Rows ${start + 1}–${start + pageRows.length} of ${rowCount} total (page ${page + 1} / ${totalPages})`;
|
| 638 |
+
document.getElementById('sample-prev-btn').disabled = page <= 0;
|
| 639 |
+
document.getElementById('sample-next-btn').disabled = page >= totalPages - 1;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
document.getElementById('sample-prev-btn').addEventListener('click', () => {
|
| 643 |
+
if (samplePreviewState.page > 0) { samplePreviewState.page -= 1; renderSamplePreviewPage(); }
|
| 644 |
+
});
|
| 645 |
+
document.getElementById('sample-next-btn').addEventListener('click', () => {
|
| 646 |
+
const totalPages = Math.max(1, Math.ceil(samplePreviewState.rows.length / PREVIEW_PAGE_SIZE));
|
| 647 |
+
if (samplePreviewState.page < totalPages - 1) { samplePreviewState.page += 1; renderSamplePreviewPage(); }
|
| 648 |
+
});
|
| 649 |
+
document.getElementById('sample-table-select').addEventListener('change', (e) => {
|
| 650 |
+
loadSamplePreview(e.target.value);
|
| 651 |
+
});
|
| 652 |
+
|
| 653 |
// ---- Banners (validator block / execution error) ----
|
| 654 |
function renderBanners(data) {
|
| 655 |
const container = document.getElementById('banners');
|