Upload templates/dashboard.html with huggingface_hub
Browse files- templates/dashboard.html +174 -3
templates/dashboard.html
CHANGED
@@ -202,6 +202,37 @@
|
|
202 |
background: #f8f9fa;
|
203 |
}
|
204 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
.loading {
|
206 |
text-align: center;
|
207 |
padding: 20px;
|
@@ -360,6 +391,34 @@
|
|
360 |
</tbody>
|
361 |
</table>
|
362 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
</div>
|
364 |
</div>
|
365 |
</div>
|
@@ -395,6 +454,19 @@
|
|
395 |
}
|
396 |
}
|
397 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
function showError(message) {
|
399 |
document.getElementById('loading').style.display = 'none';
|
400 |
document.getElementById('content').style.display = 'none';
|
@@ -739,20 +811,118 @@
|
|
739 |
});
|
740 |
}
|
741 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
742 |
async function loadData() {
|
743 |
try {
|
744 |
const loadingEl = document.getElementById('loading');
|
745 |
const contentEl = document.getElementById('content');
|
746 |
const errorEl = document.getElementById('error');
|
|
|
747 |
|
748 |
loadingEl.style.display = 'block';
|
749 |
contentEl.style.display = 'none';
|
750 |
errorEl.style.display = 'none';
|
|
|
751 |
|
752 |
-
// Fetch
|
753 |
-
const [data, historicalData] = await Promise.all([
|
754 |
fetchProviderData(),
|
755 |
-
fetchHistoricalData()
|
|
|
756 |
]);
|
757 |
|
758 |
// Batch DOM updates using requestAnimationFrame
|
@@ -767,6 +937,7 @@
|
|
767 |
updateChart(data);
|
768 |
updateTable(data);
|
769 |
updateHistoricalChart(historicalData);
|
|
|
770 |
|
771 |
// Update historical chart title with date range
|
772 |
const titleElement = document.getElementById('historicalChartTitle');
|
|
|
202 |
background: #f8f9fa;
|
203 |
}
|
204 |
|
205 |
+
.matrix-cell {
|
206 |
+
text-align: center;
|
207 |
+
padding: 8px;
|
208 |
+
min-width: 100px;
|
209 |
+
}
|
210 |
+
|
211 |
+
.matrix-cell.supported {
|
212 |
+
color: #28a745;
|
213 |
+
font-weight: bold;
|
214 |
+
}
|
215 |
+
|
216 |
+
.matrix-cell.not-supported {
|
217 |
+
color: #dc3545;
|
218 |
+
font-weight: bold;
|
219 |
+
}
|
220 |
+
|
221 |
+
.model-id-cell {
|
222 |
+
position: sticky;
|
223 |
+
left: 0;
|
224 |
+
background: white;
|
225 |
+
z-index: 5;
|
226 |
+
border-right: 2px solid #dee2e6;
|
227 |
+
font-family: monospace;
|
228 |
+
font-size: 0.85rem;
|
229 |
+
}
|
230 |
+
|
231 |
+
.total-cell {
|
232 |
+
font-weight: bold;
|
233 |
+
background: #e9ecef;
|
234 |
+
}
|
235 |
+
|
236 |
.loading {
|
237 |
text-align: center;
|
238 |
padding: 20px;
|
|
|
391 |
</tbody>
|
392 |
</table>
|
393 |
</div>
|
394 |
+
|
395 |
+
<div class="table-container">
|
396 |
+
<h2>Model Support Matrix</h2>
|
397 |
+
<div id="modelsLoading" class="loading" style="display: none;">
|
398 |
+
<div class="spinner"></div>
|
399 |
+
<p>Loading models data...</p>
|
400 |
+
</div>
|
401 |
+
<div style="overflow-x: auto;">
|
402 |
+
<table id="modelsTable" style="min-width: 1200px;">
|
403 |
+
<thead>
|
404 |
+
<tr id="modelsTableHeader">
|
405 |
+
<th style="min-width: 300px; position: sticky; left: 0; background: #f8f9fa; z-index: 10;">Model ID</th>
|
406 |
+
<!-- Provider columns will be populated here -->
|
407 |
+
<th style="min-width: 80px;">Total</th>
|
408 |
+
</tr>
|
409 |
+
</thead>
|
410 |
+
<tbody id="modelsTableBody">
|
411 |
+
<!-- Models matrix rows will be populated here -->
|
412 |
+
</tbody>
|
413 |
+
<tfoot id="modelsTableFoot">
|
414 |
+
<!-- Totals row will be populated here -->
|
415 |
+
</tfoot>
|
416 |
+
</table>
|
417 |
+
</div>
|
418 |
+
<div id="providerLinks" style="margin-top: 20px; font-size: 0.9rem; color: #6c757d;">
|
419 |
+
<!-- Provider links will be populated here -->
|
420 |
+
</div>
|
421 |
+
</div>
|
422 |
</div>
|
423 |
</div>
|
424 |
</div>
|
|
|
454 |
}
|
455 |
}
|
456 |
|
457 |
+
async function fetchModelsData() {
|
458 |
+
try {
|
459 |
+
const response = await fetch('/api/models');
|
460 |
+
if (!response.ok) {
|
461 |
+
throw new Error(`HTTP error! status: ${response.status}`);
|
462 |
+
}
|
463 |
+
return await response.json();
|
464 |
+
} catch (error) {
|
465 |
+
console.error('Error fetching models data:', error);
|
466 |
+
return { models: {}, error: 'Failed to load models data' };
|
467 |
+
}
|
468 |
+
}
|
469 |
+
|
470 |
function showError(message) {
|
471 |
document.getElementById('loading').style.display = 'none';
|
472 |
document.getElementById('content').style.display = 'none';
|
|
|
811 |
});
|
812 |
}
|
813 |
|
814 |
+
function updateModelsTable(modelsData) {
|
815 |
+
const modelsTableBody = document.getElementById('modelsTableBody');
|
816 |
+
const modelsTableHeader = document.getElementById('modelsTableHeader');
|
817 |
+
const modelsTableFoot = document.getElementById('modelsTableFoot');
|
818 |
+
const modelsLoading = document.getElementById('modelsLoading');
|
819 |
+
|
820 |
+
if (modelsData.error) {
|
821 |
+
const errorRow = `
|
822 |
+
<tr>
|
823 |
+
<td colspan="100%" style="text-align: center; color: #6c757d; font-style: italic;">
|
824 |
+
${modelsData.error === 'HF_TOKEN required for models data' ?
|
825 |
+
'HF Token required to display models data' :
|
826 |
+
'Failed to load models data'}
|
827 |
+
</td>
|
828 |
+
</tr>
|
829 |
+
`;
|
830 |
+
requestAnimationFrame(() => {
|
831 |
+
modelsLoading.style.display = 'none';
|
832 |
+
modelsTableBody.innerHTML = errorRow;
|
833 |
+
modelsTableFoot.innerHTML = '';
|
834 |
+
});
|
835 |
+
return;
|
836 |
+
}
|
837 |
+
|
838 |
+
const providers = modelsData.providers || [];
|
839 |
+
const matrix = modelsData.matrix || [];
|
840 |
+
const providerTotals = modelsData.provider_totals || {};
|
841 |
+
const providerMapping = modelsData.provider_mapping || {};
|
842 |
+
|
843 |
+
// Build header with provider columns
|
844 |
+
const providerHeaders = providers.map(provider =>
|
845 |
+
`<th class="matrix-cell" style="min-width: 100px; writing-mode: vertical-rl; text-orientation: mixed;">${provider}</th>`
|
846 |
+
).join('');
|
847 |
+
|
848 |
+
// Update header
|
849 |
+
const headerHtml = `
|
850 |
+
<th style="min-width: 300px; position: sticky; left: 0; background: #f8f9fa; z-index: 10;">Model ID</th>
|
851 |
+
${providerHeaders}
|
852 |
+
<th style="min-width: 80px;" class="total-cell">Total</th>
|
853 |
+
`;
|
854 |
+
|
855 |
+
// Build matrix rows
|
856 |
+
const matrixRows = matrix.map(row => {
|
857 |
+
const providerCells = providers.map(provider => {
|
858 |
+
const isSupported = row.providers[provider];
|
859 |
+
return `<td class="matrix-cell ${isSupported ? 'supported' : 'not-supported'}">
|
860 |
+
${isSupported ? '✓' : '✗'}
|
861 |
+
</td>`;
|
862 |
+
}).join('');
|
863 |
+
|
864 |
+
return `
|
865 |
+
<tr>
|
866 |
+
<td class="model-id-cell">${row.model_id}</td>
|
867 |
+
${providerCells}
|
868 |
+
<td class="matrix-cell total-cell">${row.total_providers}</td>
|
869 |
+
</tr>
|
870 |
+
`;
|
871 |
+
}).join('');
|
872 |
+
|
873 |
+
// Build totals footer
|
874 |
+
const totalCells = providers.map(provider =>
|
875 |
+
`<td class="matrix-cell total-cell">${providerTotals[provider] || 0}</td>`
|
876 |
+
).join('');
|
877 |
+
|
878 |
+
const footerHtml = `
|
879 |
+
<tr>
|
880 |
+
<td class="model-id-cell total-cell">Total Models</td>
|
881 |
+
${totalCells}
|
882 |
+
<td class="matrix-cell total-cell">${modelsData.total_models || 0}</td>
|
883 |
+
</tr>
|
884 |
+
`;
|
885 |
+
|
886 |
+
// Generate provider links
|
887 |
+
const providerLinksDiv = document.getElementById('providerLinks');
|
888 |
+
const providerLinksHtml = providers
|
889 |
+
.filter(provider => providerMapping[provider]) // Only show providers with inference mapping
|
890 |
+
.map(provider => {
|
891 |
+
const inferenceProvider = providerMapping[provider];
|
892 |
+
const url = `https://huggingface.co/models?inference_provider=${inferenceProvider}&sort=trending`;
|
893 |
+
return `<strong>${provider}:</strong> To see all supported models, <a href="${url}" target="_blank" style="color: #667eea;">click here</a>`;
|
894 |
+
})
|
895 |
+
.join('<br>');
|
896 |
+
|
897 |
+
// Use requestAnimationFrame for smooth DOM updates
|
898 |
+
requestAnimationFrame(() => {
|
899 |
+
modelsLoading.style.display = 'none';
|
900 |
+
modelsTableHeader.innerHTML = headerHtml;
|
901 |
+
modelsTableBody.innerHTML = matrixRows;
|
902 |
+
modelsTableFoot.innerHTML = footerHtml;
|
903 |
+
if (providerLinksDiv) {
|
904 |
+
providerLinksDiv.innerHTML = providerLinksHtml;
|
905 |
+
}
|
906 |
+
});
|
907 |
+
}
|
908 |
+
|
909 |
async function loadData() {
|
910 |
try {
|
911 |
const loadingEl = document.getElementById('loading');
|
912 |
const contentEl = document.getElementById('content');
|
913 |
const errorEl = document.getElementById('error');
|
914 |
+
const modelsLoading = document.getElementById('modelsLoading');
|
915 |
|
916 |
loadingEl.style.display = 'block';
|
917 |
contentEl.style.display = 'none';
|
918 |
errorEl.style.display = 'none';
|
919 |
+
modelsLoading.style.display = 'block';
|
920 |
|
921 |
+
// Fetch current data, historical data, and models data
|
922 |
+
const [data, historicalData, modelsData] = await Promise.all([
|
923 |
fetchProviderData(),
|
924 |
+
fetchHistoricalData(),
|
925 |
+
fetchModelsData()
|
926 |
]);
|
927 |
|
928 |
// Batch DOM updates using requestAnimationFrame
|
|
|
937 |
updateChart(data);
|
938 |
updateTable(data);
|
939 |
updateHistoricalChart(historicalData);
|
940 |
+
updateModelsTable(modelsData);
|
941 |
|
942 |
// Update historical chart title with date range
|
943 |
const titleElement = document.getElementById('historicalChartTitle');
|