Files
GopherGate/static/js/pages/providers.js
hobokenchicken 686163780c feat: major dashboard overhaul and polish
- Switched from mock data to real backend APIs.
- Implemented unified ApiClient for consistent frontend data fetching.
- Refactored dashboard structure and styles for a modern SaaS aesthetic.
- Fixed Axum 0.8+ routing and parameter syntax issues.
- Implemented real client creation/deletion and provider health monitoring.
- Synchronized WebSocket event structures between backend and frontend.
2026-02-26 15:40:12 -05:00

143 lines
5.3 KiB
JavaScript

// Providers Page Module
class ProvidersPage {
constructor() {
this.providers = [];
this.init();
}
async init() {
await this.loadProviders();
this.setupEventListeners();
}
async loadProviders() {
try {
const data = await window.api.get('/providers');
this.providers = data;
this.renderProviders();
this.renderStats();
} catch (error) {
console.error('Error loading providers:', error);
window.authManager.showToast('Failed to load providers', 'error');
}
}
renderProviders() {
const container = document.getElementById('providers-list');
if (!container) return;
if (this.providers.length === 0) {
container.innerHTML = '<div class="empty-state">No providers configured</div>';
return;
}
container.innerHTML = `
<div class="provider-cards-grid">
${this.providers.map(provider => this.renderProviderCard(provider)).join('')}
</div>
`;
}
renderProviderCard(provider) {
const statusClass = provider.status === 'online' ? 'success' : 'warning';
const modelCount = provider.models ? provider.models.length : 0;
return `
<div class="provider-card ${provider.status}">
<div class="provider-card-header">
<div class="provider-info">
<h4 class="provider-name">${provider.name}</h4>
<span class="provider-id">${provider.id}</span>
</div>
<span class="status-badge ${statusClass}">
<i class="fas fa-circle"></i>
${provider.status}
</span>
</div>
<div class="provider-card-body">
<div class="provider-meta">
<div class="meta-item">
<i class="fas fa-microchip"></i>
<span>${modelCount} Models Available</span>
</div>
<div class="meta-item">
<i class="fas fa-clock"></i>
<span>Last used: ${provider.last_used ? window.api.formatTimeAgo(provider.last_used) : 'Never'}</span>
</div>
</div>
<div class="model-tags">
${(provider.models || []).slice(0, 5).map(m => `<span class="model-tag">${m}</span>`).join('')}
${modelCount > 5 ? `<span class="model-tag more">+${modelCount - 5} more</span>` : ''}
</div>
</div>
<div class="provider-card-footer">
<button class="btn btn-secondary btn-sm" onclick="window.providersPage.testProvider('${provider.id}')">
<i class="fas fa-vial"></i> Test
</button>
<button class="btn btn-primary btn-sm" onclick="window.providersPage.configureProvider('${provider.id}')">
<i class="fas fa-cog"></i> Config
</button>
</div>
</div>
`;
}
renderStats() {
const container = document.getElementById('provider-stats');
if (!container) return;
const onlineCount = this.providers.filter(p => p.status === 'online').length;
const totalModels = this.providers.reduce((sum, p) => sum + (p.models ? p.models.length : 0), 0);
container.innerHTML = `
<div class="stat-card">
<div class="stat-content">
<div class="stat-value">${this.providers.length}</div>
<div class="stat-label">Total Providers</div>
</div>
</div>
<div class="stat-card">
<div class="stat-content">
<div class="stat-value">${onlineCount}</div>
<div class="stat-label">Online Status</div>
</div>
</div>
<div class="stat-card">
<div class="stat-content">
<div class="stat-value">${totalModels}</div>
<div class="stat-label">Total Models</div>
</div>
</div>
`;
}
async testProvider(id) {
window.authManager.showToast(`Testing connection to ${id}...`, 'info');
try {
await window.api.post(`/providers/${id}/test`, {});
window.authManager.showToast(`${id} connection successful!`, 'success');
this.loadProviders();
} catch (error) {
window.authManager.showToast(`${id} test failed: ${error.message}`, 'error');
}
}
configureProvider(id) {
window.authManager.showToast('Provider configuration via UI not yet implemented', 'info');
}
setupEventListeners() {
const testAllBtn = document.getElementById('test-all-providers');
if (testAllBtn) {
testAllBtn.onclick = () => {
this.providers.forEach(p => this.testProvider(p.id));
};
}
}
}
window.initProviders = async () => {
window.providersPage = new ProvidersPage();
};