Fix search API calls - use correct parameter name 'query' instead of 'q'
Browse files- app/templates/dashboard.html +250 -20
app/templates/dashboard.html
CHANGED
|
@@ -180,6 +180,24 @@
|
|
| 180 |
border-radius: 10px;
|
| 181 |
font-size: 0.85rem;
|
| 182 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
</style>
|
| 184 |
</head>
|
| 185 |
<body>
|
|
@@ -415,7 +433,7 @@
|
|
| 415 |
<div class="col-md-8">
|
| 416 |
<div class="search-box mb-3">
|
| 417 |
<i class="bi bi-search"></i>
|
| 418 |
-
<input type="text" class="form-control" id="model-search" placeholder="Search models...">
|
| 419 |
</div>
|
| 420 |
<input type="hidden" id="selected-model" name="model_name" required>
|
| 421 |
</div>
|
|
@@ -427,6 +445,7 @@
|
|
| 427 |
</div>
|
| 428 |
<div id="model-results" class="row g-2 mt-2"></div>
|
| 429 |
<div id="model-info" class="mt-3" style="display: none;"></div>
|
|
|
|
| 430 |
</div>
|
| 431 |
|
| 432 |
<!-- Step 3: Dataset Selection -->
|
|
@@ -436,7 +455,7 @@
|
|
| 436 |
<div class="col-md-8">
|
| 437 |
<div class="search-box mb-3">
|
| 438 |
<i class="bi bi-search"></i>
|
| 439 |
-
<input type="text" class="form-control" id="dataset-search" placeholder="Search datasets...">
|
| 440 |
</div>
|
| 441 |
<input type="hidden" id="selected-dataset" name="dataset_name" required>
|
| 442 |
</div>
|
|
@@ -448,6 +467,7 @@
|
|
| 448 |
</div>
|
| 449 |
<div id="dataset-results" class="row g-2 mt-2"></div>
|
| 450 |
<div id="dataset-config" class="mt-3" style="display: none;"></div>
|
|
|
|
| 451 |
</div>
|
| 452 |
|
| 453 |
<!-- Step 4: Training Configuration -->
|
|
@@ -624,7 +644,20 @@
|
|
| 624 |
<i class="bi bi-box me-2"></i>Browse Models
|
| 625 |
</div>
|
| 626 |
<div class="card-body">
|
| 627 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 628 |
</div>
|
| 629 |
</div>
|
| 630 |
</div>
|
|
@@ -636,7 +669,20 @@
|
|
| 636 |
<i class="bi bi-database me-2"></i>Browse Datasets
|
| 637 |
</div>
|
| 638 |
<div class="card-body">
|
| 639 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 640 |
</div>
|
| 641 |
</div>
|
| 642 |
</div>
|
|
@@ -679,6 +725,9 @@
|
|
| 679 |
document.getElementById('section-' + sectionId).style.display = 'block';
|
| 680 |
if (sectionId === 'dashboard') loadDashboard();
|
| 681 |
if (sectionId === 'jobs') loadJobs();
|
|
|
|
|
|
|
|
|
|
| 682 |
}
|
| 683 |
|
| 684 |
async function loadDashboard() {
|
|
@@ -724,23 +773,69 @@
|
|
| 724 |
document.querySelectorAll('.task-card').forEach(card => card.classList.remove('selected'));
|
| 725 |
document.querySelector('.task-card[data-task="' + task + '"]').classList.add('selected');
|
| 726 |
document.getElementById('selected-task').value = task;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
}
|
| 728 |
|
| 729 |
async function searchModels() {
|
| 730 |
-
const query = document.getElementById('model-search').value;
|
| 731 |
-
if (!query)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 732 |
try {
|
| 733 |
-
const res = await fetch(API_BASE + '/models/search?
|
|
|
|
|
|
|
|
|
|
| 734 |
const data = await res.json();
|
| 735 |
-
|
|
|
|
| 736 |
} catch (error) {
|
| 737 |
console.error('Error searching models:', error);
|
|
|
|
| 738 |
}
|
| 739 |
}
|
| 740 |
|
| 741 |
function renderModelResults(models) {
|
| 742 |
const container = document.getElementById('model-results');
|
| 743 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 744 |
}
|
| 745 |
|
| 746 |
async function selectModel(modelId) {
|
|
@@ -748,31 +843,54 @@
|
|
| 748 |
document.getElementById('selected-model').value = modelId;
|
| 749 |
document.querySelectorAll('#model-results .task-card').forEach(card => card.classList.remove('selected'));
|
| 750 |
if (event.currentTarget) event.currentTarget.classList.add('selected');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 751 |
try {
|
| 752 |
-
const res = await fetch(API_BASE + '/models/' + encodeURIComponent(modelId)
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
|
|
|
|
|
|
| 757 |
} catch (error) {
|
| 758 |
console.error('Error loading model info:', error);
|
|
|
|
| 759 |
}
|
| 760 |
}
|
| 761 |
|
| 762 |
async function searchDatasets() {
|
| 763 |
-
const query = document.getElementById('dataset-search').value;
|
| 764 |
-
if (!query)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 765 |
try {
|
| 766 |
-
const res = await fetch(API_BASE + '/datasets/search?
|
|
|
|
|
|
|
|
|
|
| 767 |
const data = await res.json();
|
| 768 |
-
|
|
|
|
| 769 |
} catch (error) {
|
| 770 |
console.error('Error searching datasets:', error);
|
|
|
|
| 771 |
}
|
| 772 |
}
|
| 773 |
|
| 774 |
function renderDatasetResults(datasets) {
|
| 775 |
const container = document.getElementById('dataset-results');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 776 |
container.innerHTML = datasets.slice(0, 12).map(ds => '<div class="col-md-3"><div class="card task-card" onclick="selectDataset(\'' + ds.id + '\')"><div class="card-body py-2"><small class="fw-bold">' + ds.id + '</small><br><small class="text-muted">' + (ds.downloads?.toLocaleString() || 0) + ' downloads</small></div></div></div>').join('');
|
| 777 |
}
|
| 778 |
|
|
@@ -783,6 +901,104 @@
|
|
| 783 |
if (event.currentTarget) event.currentTarget.classList.add('selected');
|
| 784 |
}
|
| 785 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 786 |
async function loadJobs() {
|
| 787 |
try {
|
| 788 |
const res = await fetch(API_BASE + '/jobs/');
|
|
@@ -816,6 +1032,20 @@
|
|
| 816 |
|
| 817 |
document.getElementById('training-form').addEventListener('submit', async (e) => {
|
| 818 |
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 819 |
const formData = {
|
| 820 |
task_type: selectedTask,
|
| 821 |
model_name: selectedModel,
|
|
@@ -845,11 +1075,11 @@
|
|
| 845 |
alert('Training started! Job ID: ' + data.job_id);
|
| 846 |
showSection('jobs');
|
| 847 |
} else {
|
| 848 |
-
alert('Error starting training: ' + (data.error || 'Unknown error'));
|
| 849 |
}
|
| 850 |
} catch (error) {
|
| 851 |
console.error('Error starting training:', error);
|
| 852 |
-
alert('Error starting training');
|
| 853 |
}
|
| 854 |
});
|
| 855 |
|
|
|
|
| 180 |
border-radius: 10px;
|
| 181 |
font-size: 0.85rem;
|
| 182 |
}
|
| 183 |
+
.search-loading {
|
| 184 |
+
opacity: 0.6;
|
| 185 |
+
pointer-events: none;
|
| 186 |
+
}
|
| 187 |
+
.error-message {
|
| 188 |
+
background: #ffebee;
|
| 189 |
+
color: #c62828;
|
| 190 |
+
padding: 10px 15px;
|
| 191 |
+
border-radius: 8px;
|
| 192 |
+
margin-top: 10px;
|
| 193 |
+
}
|
| 194 |
+
.success-message {
|
| 195 |
+
background: #e8f5e9;
|
| 196 |
+
color: #2e7d32;
|
| 197 |
+
padding: 10px 15px;
|
| 198 |
+
border-radius: 8px;
|
| 199 |
+
margin-top: 10px;
|
| 200 |
+
}
|
| 201 |
</style>
|
| 202 |
</head>
|
| 203 |
<body>
|
|
|
|
| 433 |
<div class="col-md-8">
|
| 434 |
<div class="search-box mb-3">
|
| 435 |
<i class="bi bi-search"></i>
|
| 436 |
+
<input type="text" class="form-control" id="model-search" placeholder="Search models (e.g., gpt2, bert, llama)...">
|
| 437 |
</div>
|
| 438 |
<input type="hidden" id="selected-model" name="model_name" required>
|
| 439 |
</div>
|
|
|
|
| 445 |
</div>
|
| 446 |
<div id="model-results" class="row g-2 mt-2"></div>
|
| 447 |
<div id="model-info" class="mt-3" style="display: none;"></div>
|
| 448 |
+
<div id="model-recommendations" class="mt-3"></div>
|
| 449 |
</div>
|
| 450 |
|
| 451 |
<!-- Step 3: Dataset Selection -->
|
|
|
|
| 455 |
<div class="col-md-8">
|
| 456 |
<div class="search-box mb-3">
|
| 457 |
<i class="bi bi-search"></i>
|
| 458 |
+
<input type="text" class="form-control" id="dataset-search" placeholder="Search datasets (e.g., squad, imdb, wikitext)...">
|
| 459 |
</div>
|
| 460 |
<input type="hidden" id="selected-dataset" name="dataset_name" required>
|
| 461 |
</div>
|
|
|
|
| 467 |
</div>
|
| 468 |
<div id="dataset-results" class="row g-2 mt-2"></div>
|
| 469 |
<div id="dataset-config" class="mt-3" style="display: none;"></div>
|
| 470 |
+
<div id="dataset-recommendations" class="mt-3"></div>
|
| 471 |
</div>
|
| 472 |
|
| 473 |
<!-- Step 4: Training Configuration -->
|
|
|
|
| 644 |
<i class="bi bi-box me-2"></i>Browse Models
|
| 645 |
</div>
|
| 646 |
<div class="card-body">
|
| 647 |
+
<div class="row mb-3">
|
| 648 |
+
<div class="col-md-8">
|
| 649 |
+
<div class="search-box">
|
| 650 |
+
<i class="bi bi-search"></i>
|
| 651 |
+
<input type="text" class="form-control" id="models-page-search" placeholder="Search models...">
|
| 652 |
+
</div>
|
| 653 |
+
</div>
|
| 654 |
+
<div class="col-md-4">
|
| 655 |
+
<button type="button" class="btn btn-primary w-100" onclick="searchModelsPage()">
|
| 656 |
+
<i class="bi bi-search me-1"></i>Search
|
| 657 |
+
</button>
|
| 658 |
+
</div>
|
| 659 |
+
</div>
|
| 660 |
+
<div id="models-page-results" class="row g-3"></div>
|
| 661 |
</div>
|
| 662 |
</div>
|
| 663 |
</div>
|
|
|
|
| 669 |
<i class="bi bi-database me-2"></i>Browse Datasets
|
| 670 |
</div>
|
| 671 |
<div class="card-body">
|
| 672 |
+
<div class="row mb-3">
|
| 673 |
+
<div class="col-md-8">
|
| 674 |
+
<div class="search-box">
|
| 675 |
+
<i class="bi bi-search"></i>
|
| 676 |
+
<input type="text" class="form-control" id="datasets-page-search" placeholder="Search datasets...">
|
| 677 |
+
</div>
|
| 678 |
+
</div>
|
| 679 |
+
<div class="col-md-4">
|
| 680 |
+
<button type="button" class="btn btn-primary w-100" onclick="searchDatasetsPage()">
|
| 681 |
+
<i class="bi bi-search me-1"></i>Search
|
| 682 |
+
</button>
|
| 683 |
+
</div>
|
| 684 |
+
</div>
|
| 685 |
+
<div id="datasets-page-results" class="row g-3"></div>
|
| 686 |
</div>
|
| 687 |
</div>
|
| 688 |
</div>
|
|
|
|
| 725 |
document.getElementById('section-' + sectionId).style.display = 'block';
|
| 726 |
if (sectionId === 'dashboard') loadDashboard();
|
| 727 |
if (sectionId === 'jobs') loadJobs();
|
| 728 |
+
if (sectionId === 'new-training') loadRecommendations();
|
| 729 |
+
if (sectionId === 'models') loadPopularModels();
|
| 730 |
+
if (sectionId === 'datasets') loadPopularDatasets();
|
| 731 |
}
|
| 732 |
|
| 733 |
async function loadDashboard() {
|
|
|
|
| 773 |
document.querySelectorAll('.task-card').forEach(card => card.classList.remove('selected'));
|
| 774 |
document.querySelector('.task-card[data-task="' + task + '"]').classList.add('selected');
|
| 775 |
document.getElementById('selected-task').value = task;
|
| 776 |
+
loadRecommendations();
|
| 777 |
+
}
|
| 778 |
+
|
| 779 |
+
async function loadRecommendations() {
|
| 780 |
+
if (!selectedTask) return;
|
| 781 |
+
|
| 782 |
+
try {
|
| 783 |
+
// Load model recommendations
|
| 784 |
+
const modelRecRes = await fetch(API_BASE + '/models/recommend/' + selectedTask);
|
| 785 |
+
if (modelRecRes.ok) {
|
| 786 |
+
const modelRecs = await modelRecRes.json();
|
| 787 |
+
const modelContainer = document.getElementById('model-recommendations');
|
| 788 |
+
if (modelRecs && modelRecs.length > 0) {
|
| 789 |
+
modelContainer.innerHTML = '<h6 class="mb-2">Recommended Models:</h6><div class="row g-2">' +
|
| 790 |
+
modelRecs.slice(0, 4).map(m => '<div class="col-md-3"><div class="card task-card" onclick="selectModel(\'' + m.model_id + '\')"><div class="card-body py-2"><small class="fw-bold">' + m.model_id + '</small><br><small class="text-muted">' + (m.size || '') + '</small></div></div></div>').join('') + '</div>';
|
| 791 |
+
}
|
| 792 |
+
}
|
| 793 |
+
|
| 794 |
+
// Load dataset recommendations
|
| 795 |
+
const datasetRecRes = await fetch(API_BASE + '/datasets/recommend/' + selectedTask);
|
| 796 |
+
if (datasetRecRes.ok) {
|
| 797 |
+
const datasetRecs = await datasetRecRes.json();
|
| 798 |
+
const datasetContainer = document.getElementById('dataset-recommendations');
|
| 799 |
+
if (datasetRecs && datasetRecs.length > 0) {
|
| 800 |
+
datasetContainer.innerHTML = '<h6 class="mb-2">Recommended Datasets:</h6><div class="row g-2">' +
|
| 801 |
+
datasetRecs.slice(0, 4).map(d => '<div class="col-md-3"><div class="card task-card" onclick="selectDataset(\'' + d.dataset_id + '\')"><div class="card-body py-2"><small class="fw-bold">' + d.dataset_id + '</small><br><small class="text-muted">' + (d.size || '') + '</small></div></div></div>').join('') + '</div>';
|
| 802 |
+
}
|
| 803 |
+
}
|
| 804 |
+
} catch (error) {
|
| 805 |
+
console.error('Error loading recommendations:', error);
|
| 806 |
+
}
|
| 807 |
}
|
| 808 |
|
| 809 |
async function searchModels() {
|
| 810 |
+
const query = document.getElementById('model-search').value.trim();
|
| 811 |
+
if (!query) {
|
| 812 |
+
alert('Please enter a search term');
|
| 813 |
+
return;
|
| 814 |
+
}
|
| 815 |
+
const container = document.getElementById('model-results');
|
| 816 |
+
container.innerHTML = '<div class="col-12 text-center"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
| 817 |
+
|
| 818 |
try {
|
| 819 |
+
const res = await fetch(API_BASE + '/models/search?query=' + encodeURIComponent(query) + '&limit=12');
|
| 820 |
+
if (!res.ok) {
|
| 821 |
+
throw new Error('Search failed: ' + res.status);
|
| 822 |
+
}
|
| 823 |
const data = await res.json();
|
| 824 |
+
console.log('Model search results:', data);
|
| 825 |
+
renderModelResults(data);
|
| 826 |
} catch (error) {
|
| 827 |
console.error('Error searching models:', error);
|
| 828 |
+
container.innerHTML = '<div class="col-12"><div class="error-message"><i class="bi bi-exclamation-triangle me-2"></i>Error searching models: ' + error.message + '</div></div>';
|
| 829 |
}
|
| 830 |
}
|
| 831 |
|
| 832 |
function renderModelResults(models) {
|
| 833 |
const container = document.getElementById('model-results');
|
| 834 |
+
if (!models || models.length === 0) {
|
| 835 |
+
container.innerHTML = '<div class="col-12 text-center text-muted py-3"><i class="bi bi-search fs-1 d-block mb-2"></i>No models found. Try a different search term.</div>';
|
| 836 |
+
return;
|
| 837 |
+
}
|
| 838 |
+
container.innerHTML = models.slice(0, 12).map(model => '<div class="col-md-3"><div class="card task-card" onclick="selectModel(\'' + (model.id || model.model_id) + '\')"><div class="card-body py-2"><small class="fw-bold">' + (model.id || model.model_id) + '</small><br><small class="text-muted">' + formatBytes(model.size_bytes || model.downloads || 0) + '</small></div></div></div>').join('');
|
| 839 |
}
|
| 840 |
|
| 841 |
async function selectModel(modelId) {
|
|
|
|
| 843 |
document.getElementById('selected-model').value = modelId;
|
| 844 |
document.querySelectorAll('#model-results .task-card').forEach(card => card.classList.remove('selected'));
|
| 845 |
if (event.currentTarget) event.currentTarget.classList.add('selected');
|
| 846 |
+
|
| 847 |
+
const container = document.getElementById('model-info');
|
| 848 |
+
container.style.display = 'block';
|
| 849 |
+
container.innerHTML = '<div class="card"><div class="card-body"><div class="spinner-border spinner-border-sm" role="status"></div> Loading model info...</div></div>';
|
| 850 |
+
|
| 851 |
try {
|
| 852 |
+
const res = await fetch(API_BASE + '/models/info/' + encodeURIComponent(modelId));
|
| 853 |
+
if (res.ok) {
|
| 854 |
+
const info = await res.json();
|
| 855 |
+
container.innerHTML = '<div class="card"><div class="card-body"><h6>' + info.model_id + '</h6><div class="row"><div class="col-6"><small class="text-muted">Downloads:</small></div><div class="col-6 text-end"><small>' + (info.downloads?.toLocaleString() || 'N/A') + '</small></div></div><div class="row"><div class="col-6"><small class="text-muted">Architecture:</small></div><div class="col-6 text-end"><small>' + (info.architectures?.[0] || info.architecture || 'Unknown') + '</small></div></div><div class="row"><div class="col-6"><small class="text-muted">Pipeline Tag:</small></div><div class="col-6 text-end"><small>' + (info.pipeline_tag || 'N/A') + '</small></div></div></div></div>';
|
| 856 |
+
} else {
|
| 857 |
+
container.innerHTML = '<div class="card"><div class="card-body"><small class="text-muted">Selected: ' + modelId + '</small></div></div>';
|
| 858 |
+
}
|
| 859 |
} catch (error) {
|
| 860 |
console.error('Error loading model info:', error);
|
| 861 |
+
container.innerHTML = '<div class="card"><div class="card-body"><small class="text-muted">Selected: ' + modelId + '</small></div></div>';
|
| 862 |
}
|
| 863 |
}
|
| 864 |
|
| 865 |
async function searchDatasets() {
|
| 866 |
+
const query = document.getElementById('dataset-search').value.trim();
|
| 867 |
+
if (!query) {
|
| 868 |
+
alert('Please enter a search term');
|
| 869 |
+
return;
|
| 870 |
+
}
|
| 871 |
+
const container = document.getElementById('dataset-results');
|
| 872 |
+
container.innerHTML = '<div class="col-12 text-center"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
| 873 |
+
|
| 874 |
try {
|
| 875 |
+
const res = await fetch(API_BASE + '/datasets/search?query=' + encodeURIComponent(query) + '&limit=12');
|
| 876 |
+
if (!res.ok) {
|
| 877 |
+
throw new Error('Search failed: ' + res.status);
|
| 878 |
+
}
|
| 879 |
const data = await res.json();
|
| 880 |
+
console.log('Dataset search results:', data);
|
| 881 |
+
renderDatasetResults(data);
|
| 882 |
} catch (error) {
|
| 883 |
console.error('Error searching datasets:', error);
|
| 884 |
+
container.innerHTML = '<div class="col-12"><div class="error-message"><i class="bi bi-exclamation-triangle me-2"></i>Error searching datasets: ' + error.message + '</div></div>';
|
| 885 |
}
|
| 886 |
}
|
| 887 |
|
| 888 |
function renderDatasetResults(datasets) {
|
| 889 |
const container = document.getElementById('dataset-results');
|
| 890 |
+
if (!datasets || datasets.length === 0) {
|
| 891 |
+
container.innerHTML = '<div class="col-12 text-center text-muted py-3"><i class="bi bi-search fs-1 d-block mb-2"></i>No datasets found. Try a different search term.</div>';
|
| 892 |
+
return;
|
| 893 |
+
}
|
| 894 |
container.innerHTML = datasets.slice(0, 12).map(ds => '<div class="col-md-3"><div class="card task-card" onclick="selectDataset(\'' + ds.id + '\')"><div class="card-body py-2"><small class="fw-bold">' + ds.id + '</small><br><small class="text-muted">' + (ds.downloads?.toLocaleString() || 0) + ' downloads</small></div></div></div>').join('');
|
| 895 |
}
|
| 896 |
|
|
|
|
| 901 |
if (event.currentTarget) event.currentTarget.classList.add('selected');
|
| 902 |
}
|
| 903 |
|
| 904 |
+
async function loadPopularModels() {
|
| 905 |
+
const container = document.getElementById('models-page-results');
|
| 906 |
+
container.innerHTML = '<div class="col-12 text-center"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
| 907 |
+
|
| 908 |
+
try {
|
| 909 |
+
const res = await fetch(API_BASE + '/models/popular?limit=20');
|
| 910 |
+
if (res.ok) {
|
| 911 |
+
const data = await res.json();
|
| 912 |
+
renderModelsPage(data);
|
| 913 |
+
} else {
|
| 914 |
+
container.innerHTML = '<div class="col-12 text-center text-muted">No models found</div>';
|
| 915 |
+
}
|
| 916 |
+
} catch (error) {
|
| 917 |
+
console.error('Error loading popular models:', error);
|
| 918 |
+
container.innerHTML = '<div class="col-12 text-center text-muted">Error loading models</div>';
|
| 919 |
+
}
|
| 920 |
+
}
|
| 921 |
+
|
| 922 |
+
async function searchModelsPage() {
|
| 923 |
+
const query = document.getElementById('models-page-search').value.trim();
|
| 924 |
+
if (!query) {
|
| 925 |
+
loadPopularModels();
|
| 926 |
+
return;
|
| 927 |
+
}
|
| 928 |
+
const container = document.getElementById('models-page-results');
|
| 929 |
+
container.innerHTML = '<div class="col-12 text-center"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
| 930 |
+
|
| 931 |
+
try {
|
| 932 |
+
const res = await fetch(API_BASE + '/models/search?query=' + encodeURIComponent(query) + '&limit=20');
|
| 933 |
+
if (res.ok) {
|
| 934 |
+
const data = await res.json();
|
| 935 |
+
renderModelsPage(data);
|
| 936 |
+
} else {
|
| 937 |
+
container.innerHTML = '<div class="col-12 text-center text-muted">No models found</div>';
|
| 938 |
+
}
|
| 939 |
+
} catch (error) {
|
| 940 |
+
console.error('Error searching models:', error);
|
| 941 |
+
}
|
| 942 |
+
}
|
| 943 |
+
|
| 944 |
+
function renderModelsPage(models) {
|
| 945 |
+
const container = document.getElementById('models-page-results');
|
| 946 |
+
if (!models || models.length === 0) {
|
| 947 |
+
container.innerHTML = '<div class="col-12 text-center text-muted py-3">No models found</div>';
|
| 948 |
+
return;
|
| 949 |
+
}
|
| 950 |
+
container.innerHTML = models.map(m => '<div class="col-md-3"><div class="card model-card"><div class="card-body"><h6>' + (m.id || m.model_id) + '</h6><small class="text-muted d-block">' + (m.pipeline_tag || 'Unknown') + '</small><small class="text-muted">' + (m.downloads?.toLocaleString() || 0) + ' downloads</small></div></div></div>').join('');
|
| 951 |
+
}
|
| 952 |
+
|
| 953 |
+
async function loadPopularDatasets() {
|
| 954 |
+
const container = document.getElementById('datasets-page-results');
|
| 955 |
+
container.innerHTML = '<div class="col-12 text-center"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
| 956 |
+
|
| 957 |
+
try {
|
| 958 |
+
const res = await fetch(API_BASE + '/datasets/popular?limit=20');
|
| 959 |
+
if (res.ok) {
|
| 960 |
+
const data = await res.json();
|
| 961 |
+
renderDatasetsPage(data);
|
| 962 |
+
} else {
|
| 963 |
+
container.innerHTML = '<div class="col-12 text-center text-muted">No datasets found</div>';
|
| 964 |
+
}
|
| 965 |
+
} catch (error) {
|
| 966 |
+
console.error('Error loading popular datasets:', error);
|
| 967 |
+
container.innerHTML = '<div class="col-12 text-center text-muted">Error loading datasets</div>';
|
| 968 |
+
}
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
async function searchDatasetsPage() {
|
| 972 |
+
const query = document.getElementById('datasets-page-search').value.trim();
|
| 973 |
+
if (!query) {
|
| 974 |
+
loadPopularDatasets();
|
| 975 |
+
return;
|
| 976 |
+
}
|
| 977 |
+
const container = document.getElementById('datasets-page-results');
|
| 978 |
+
container.innerHTML = '<div class="col-12 text-center"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
| 979 |
+
|
| 980 |
+
try {
|
| 981 |
+
const res = await fetch(API_BASE + '/datasets/search?query=' + encodeURIComponent(query) + '&limit=20');
|
| 982 |
+
if (res.ok) {
|
| 983 |
+
const data = await res.json();
|
| 984 |
+
renderDatasetsPage(data);
|
| 985 |
+
} else {
|
| 986 |
+
container.innerHTML = '<div class="col-12 text-center text-muted">No datasets found</div>';
|
| 987 |
+
}
|
| 988 |
+
} catch (error) {
|
| 989 |
+
console.error('Error searching datasets:', error);
|
| 990 |
+
}
|
| 991 |
+
}
|
| 992 |
+
|
| 993 |
+
function renderDatasetsPage(datasets) {
|
| 994 |
+
const container = document.getElementById('datasets-page-results');
|
| 995 |
+
if (!datasets || datasets.length === 0) {
|
| 996 |
+
container.innerHTML = '<div class="col-12 text-center text-muted py-3">No datasets found</div>';
|
| 997 |
+
return;
|
| 998 |
+
}
|
| 999 |
+
container.innerHTML = datasets.map(d => '<div class="col-md-3"><div class="card model-card"><div class="card-body"><h6>' + (d.id || d.dataset_id) + '</h6><small class="text-muted d-block">' + (d.description?.substring(0, 50) || 'No description') + '</small><small class="text-muted">' + (d.downloads?.toLocaleString() || 0) + ' downloads</small></div></div></div>').join('');
|
| 1000 |
+
}
|
| 1001 |
+
|
| 1002 |
async function loadJobs() {
|
| 1003 |
try {
|
| 1004 |
const res = await fetch(API_BASE + '/jobs/');
|
|
|
|
| 1032 |
|
| 1033 |
document.getElementById('training-form').addEventListener('submit', async (e) => {
|
| 1034 |
e.preventDefault();
|
| 1035 |
+
|
| 1036 |
+
if (!selectedTask) {
|
| 1037 |
+
alert('Please select a task type');
|
| 1038 |
+
return;
|
| 1039 |
+
}
|
| 1040 |
+
if (!selectedModel) {
|
| 1041 |
+
alert('Please select a model');
|
| 1042 |
+
return;
|
| 1043 |
+
}
|
| 1044 |
+
if (!selectedDataset) {
|
| 1045 |
+
alert('Please select a dataset');
|
| 1046 |
+
return;
|
| 1047 |
+
}
|
| 1048 |
+
|
| 1049 |
const formData = {
|
| 1050 |
task_type: selectedTask,
|
| 1051 |
model_name: selectedModel,
|
|
|
|
| 1075 |
alert('Training started! Job ID: ' + data.job_id);
|
| 1076 |
showSection('jobs');
|
| 1077 |
} else {
|
| 1078 |
+
alert('Error starting training: ' + (data.detail || data.error || 'Unknown error'));
|
| 1079 |
}
|
| 1080 |
} catch (error) {
|
| 1081 |
console.error('Error starting training:', error);
|
| 1082 |
+
alert('Error starting training: ' + error.message);
|
| 1083 |
}
|
| 1084 |
});
|
| 1085 |
|