Changeset 0.4.3 (#32)
This commit is contained in:
122
src/js/ui.js
122
src/js/ui.js
@@ -89,22 +89,27 @@ function updateQuickModelSelector() {
|
||||
function openSettings() {
|
||||
updateSettingsUI();
|
||||
updateProfileSection();
|
||||
updateProviderSection();
|
||||
document.getElementById('settingsModal').classList.add('active');
|
||||
}
|
||||
|
||||
function updateProfileSection() {
|
||||
const profileSection = document.getElementById('profileSection');
|
||||
const unmanagedSettings = document.getElementById('unmanagedSettings');
|
||||
const modeBadge = document.getElementById('settingsModeBadge');
|
||||
|
||||
if (Backend.isManaged) {
|
||||
profileSection.style.display = '';
|
||||
unmanagedSettings.style.display = 'none';
|
||||
modeBadge.textContent = '🔗 Managed Mode — API keys are configured by your admin or in Providers below';
|
||||
modeBadge.className = 'settings-mode-badge mode-managed';
|
||||
loadProfileIntoSettings();
|
||||
} else {
|
||||
profileSection.style.display = 'none';
|
||||
unmanagedSettings.style.display = '';
|
||||
modeBadge.textContent = '📱 Offline Mode — Configure your own API endpoint and key';
|
||||
modeBadge.className = 'settings-mode-badge mode-unmanaged';
|
||||
}
|
||||
// Always reset password form
|
||||
document.getElementById('profileChangePwForm').style.display = 'none';
|
||||
}
|
||||
|
||||
@@ -170,6 +175,121 @@ async function handleChangePassword() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── API Providers (managed mode) ────────────
|
||||
|
||||
function updateProviderSection() {
|
||||
const managed = document.getElementById('managedProviders');
|
||||
if (Backend.isManaged) {
|
||||
managed.style.display = '';
|
||||
loadProviderList();
|
||||
} else {
|
||||
managed.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadProviderList() {
|
||||
const container = document.getElementById('providerList');
|
||||
container.innerHTML = '<div class="admin-loading">Loading...</div>';
|
||||
|
||||
try {
|
||||
const data = await Backend.listConfigs();
|
||||
const configs = data.configs || data.data || data || [];
|
||||
const list = Array.isArray(configs) ? configs : [];
|
||||
|
||||
if (list.length === 0) {
|
||||
container.innerHTML = '<div class="provider-empty">No providers configured. Add one to start chatting.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = list.map(c => `
|
||||
<div class="provider-row">
|
||||
<div class="provider-info">
|
||||
<span class="provider-name">${escapeHtmlUI(c.name)}</span>
|
||||
<span class="provider-meta">${c.provider} · ${c.model_default || 'no default'}</span>
|
||||
</div>
|
||||
<div class="provider-actions">
|
||||
<span class="admin-badge admin-badge-active">${c.has_key ? '🔑' : '⚠️'}</span>
|
||||
${c.user_id ? `<button class="btn btn-small btn-danger" onclick="deleteProvider('${c.id}', '${escapeHtmlUI(c.name)}')">Remove</button>` : '<span class="admin-badge admin-badge-moderator">global</span>'}
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
} catch (e) {
|
||||
container.innerHTML = '<div class="admin-error">Failed to load providers: ' + e.message + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
function showProviderForm() {
|
||||
document.getElementById('providerAddForm').style.display = '';
|
||||
document.getElementById('providerShowAddBtn').style.display = 'none';
|
||||
// Set default endpoint based on provider type
|
||||
updateProviderEndpointHint();
|
||||
}
|
||||
|
||||
function hideProviderForm() {
|
||||
document.getElementById('providerAddForm').style.display = 'none';
|
||||
document.getElementById('providerShowAddBtn').style.display = '';
|
||||
clearProviderForm();
|
||||
}
|
||||
|
||||
function clearProviderForm() {
|
||||
document.getElementById('providerName').value = '';
|
||||
document.getElementById('providerType').value = 'openai';
|
||||
document.getElementById('providerEndpoint').value = '';
|
||||
document.getElementById('providerApiKey').value = '';
|
||||
document.getElementById('providerDefaultModel').value = '';
|
||||
}
|
||||
|
||||
function updateProviderEndpointHint() {
|
||||
const type = document.getElementById('providerType').value;
|
||||
const endpoint = document.getElementById('providerEndpoint');
|
||||
if (!endpoint.value) {
|
||||
endpoint.placeholder = type === 'anthropic'
|
||||
? 'https://api.anthropic.com'
|
||||
: 'https://api.openai.com/v1';
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCreateProvider() {
|
||||
const name = document.getElementById('providerName').value.trim();
|
||||
const provider = document.getElementById('providerType').value;
|
||||
const endpoint = document.getElementById('providerEndpoint').value.trim();
|
||||
const apiKey = document.getElementById('providerApiKey').value.trim();
|
||||
const modelDefault = document.getElementById('providerDefaultModel').value.trim();
|
||||
|
||||
if (!name || !endpoint || !apiKey) {
|
||||
showToast('⚠️ Name, endpoint, and API key are required', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await Backend.createConfig(name, provider, endpoint, apiKey, modelDefault || null);
|
||||
showToast('✅ Provider added', 'success');
|
||||
hideProviderForm();
|
||||
loadProviderList();
|
||||
fetchModels(false); // Refresh model list
|
||||
} catch (e) {
|
||||
showToast('❌ ' + e.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteProvider(configId, name) {
|
||||
if (!confirm('Remove provider "' + name + '"?')) return;
|
||||
try {
|
||||
await Backend.deleteConfig(configId);
|
||||
showToast('✅ Provider removed', 'success');
|
||||
loadProviderList();
|
||||
fetchModels(false);
|
||||
} catch (e) {
|
||||
showToast('❌ ' + e.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtmlUI(str) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = str || '';
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function closeSettings() {
|
||||
document.getElementById('settingsModal').classList.remove('active');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user