Changeset 0.22.7 (#149)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
// Chat Switchboard – Admin Handlers
|
||||
// ==========================================
|
||||
// Admin actions: user management, roles, model visibility,
|
||||
// presets, team management, global providers.
|
||||
// personas, team management, global providers.
|
||||
|
||||
// ── Admin Actions ────────────────────────────
|
||||
|
||||
@@ -155,7 +155,7 @@ async function toggleUserModelVisibility(modelId, currentlyHidden) {
|
||||
}
|
||||
|
||||
async function bulkSetUserModelVisibility(show) {
|
||||
const models = App.models.filter(m => !m.isPreset);
|
||||
const models = App.models.filter(m => !m.isPersona);
|
||||
if (!models.length) return;
|
||||
const shouldHide = !show;
|
||||
// Only update models not already in the desired state
|
||||
@@ -172,41 +172,41 @@ async function bulkSetUserModelVisibility(show) {
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function deleteUserPreset(id, name) {
|
||||
if (!await showConfirm(`Delete preset "${name}"?`)) return;
|
||||
async function deleteUserPersona(id, name) {
|
||||
if (!await showConfirm(`Delete persona "${name}"?`)) return;
|
||||
try {
|
||||
await API.deleteUserPreset(id);
|
||||
UI.toast('Preset deleted');
|
||||
await UI.loadUserPresets();
|
||||
await API.deleteUserPersona(id);
|
||||
UI.toast('Persona deleted');
|
||||
await UI.loadUserPersonas();
|
||||
await fetchModels();
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
// ── Admin Presets ────────────────────────────
|
||||
// ── Admin Personas ────────────────────────────
|
||||
|
||||
var _adminPresetForm = null;
|
||||
function ensureAdminPresetForm() {
|
||||
if (_adminPresetForm) return _adminPresetForm;
|
||||
const container = document.getElementById('adminAddPresetForm');
|
||||
var _adminPersonaForm = null;
|
||||
function ensureAdminPersonaForm() {
|
||||
if (_adminPersonaForm) return _adminPersonaForm;
|
||||
const container = document.getElementById('adminAddPersonaForm');
|
||||
if (!container) return null;
|
||||
_adminPresetForm = renderPresetForm(container, {
|
||||
prefix: 'adminPreset',
|
||||
_adminPersonaForm = renderPersonaForm(container, {
|
||||
prefix: 'adminPersona',
|
||||
showAvatar: true,
|
||||
showProviderConfig: true,
|
||||
showKBPicker: true,
|
||||
kbScope: 'admin',
|
||||
onSubmit: (vals) => createAdminPreset(vals),
|
||||
onSubmit: (vals) => createAdminPersona(vals),
|
||||
onCancel: () => {
|
||||
container.style.display = 'none';
|
||||
_editingPresetId = null;
|
||||
_adminPresetForm.setSubmitLabel('Create');
|
||||
_adminPresetForm.clearForm();
|
||||
_editingPersonaId = null;
|
||||
_adminPersonaForm.setSubmitLabel('Create');
|
||||
_adminPersonaForm.clearForm();
|
||||
}
|
||||
});
|
||||
// Override avatar handlers for edit-mode (upload immediately for existing presets)
|
||||
const fileInput = document.getElementById('adminPreset_avatarFileInput');
|
||||
// Override avatar handlers for edit-mode (upload immediately for existing personas)
|
||||
const fileInput = document.getElementById('adminPersona_avatarFileInput');
|
||||
if (fileInput) {
|
||||
// Remove default handler set by renderPresetForm, add edit-aware one
|
||||
// Remove default handler set by renderPersonaForm, add edit-aware one
|
||||
const newInput = fileInput.cloneNode(true);
|
||||
fileInput.parentNode.replaceChild(newInput, fileInput);
|
||||
newInput.addEventListener('change', async function() {
|
||||
@@ -214,55 +214,55 @@ function ensureAdminPresetForm() {
|
||||
if (!file) return;
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
if (_editingPresetId) {
|
||||
if (_editingPersonaId) {
|
||||
try {
|
||||
const data = await API.adminUploadPresetAvatar(_editingPresetId, reader.result);
|
||||
const data = await API.adminUploadPersonaAvatar(_editingPersonaId, reader.result);
|
||||
if (data.avatar) {
|
||||
_adminPresetForm.updateAvatarPreview(data.avatar);
|
||||
await UI.loadAdminPresets(true);
|
||||
_adminPersonaForm.updateAvatarPreview(data.avatar);
|
||||
await UI.loadAdminPersonas(true);
|
||||
await fetchModels();
|
||||
UI.toast('Preset avatar updated');
|
||||
UI.toast('Persona avatar updated');
|
||||
}
|
||||
} catch (e) { UI.toast(e.message || 'Upload failed', 'error'); }
|
||||
} else {
|
||||
_adminPresetForm.updateAvatarPreview(reader.result);
|
||||
_adminPersonaForm.updateAvatarPreview(reader.result);
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
this.value = '';
|
||||
});
|
||||
document.getElementById('adminPreset_avatarUploadBtn')?.addEventListener('click', () => newInput.click());
|
||||
document.getElementById('adminPersona_avatarUploadBtn')?.addEventListener('click', () => newInput.click());
|
||||
}
|
||||
const removeBtn = document.getElementById('adminPreset_avatarRemoveBtn');
|
||||
const removeBtn = document.getElementById('adminPersona_avatarRemoveBtn');
|
||||
if (removeBtn) {
|
||||
const newBtn = removeBtn.cloneNode(true);
|
||||
removeBtn.parentNode.replaceChild(newBtn, removeBtn);
|
||||
newBtn.addEventListener('click', async () => {
|
||||
if (_editingPresetId) {
|
||||
if (_editingPersonaId) {
|
||||
try {
|
||||
await API.adminDeletePresetAvatar(_editingPresetId);
|
||||
_adminPresetForm.updateAvatarPreview(null);
|
||||
await UI.loadAdminPresets(true);
|
||||
await API.adminDeletePersonaAvatar(_editingPersonaId);
|
||||
_adminPersonaForm.updateAvatarPreview(null);
|
||||
await UI.loadAdminPersonas(true);
|
||||
await fetchModels();
|
||||
UI.toast('Preset avatar removed');
|
||||
UI.toast('Persona avatar removed');
|
||||
} catch (e) { UI.toast(e.message || 'Remove failed', 'error'); }
|
||||
} else {
|
||||
_adminPresetForm.updateAvatarPreview(null);
|
||||
_adminPersonaForm.updateAvatarPreview(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
return _adminPresetForm;
|
||||
return _adminPersonaForm;
|
||||
}
|
||||
|
||||
var _editingPresetId = null;
|
||||
function editAdminPreset(id) {
|
||||
const p = UI._presetCache?.[id];
|
||||
var _editingPersonaId = null;
|
||||
function editAdminPersona(id) {
|
||||
const p = UI._personaCache?.[id];
|
||||
if (!p) return;
|
||||
_editingPresetId = id;
|
||||
ensureAdminPresetForm();
|
||||
const form = _adminPresetForm;
|
||||
_editingPersonaId = id;
|
||||
ensureAdminPersonaForm();
|
||||
const form = _adminPersonaForm;
|
||||
if (!form) return;
|
||||
document.getElementById('adminAddPresetForm').style.display = '';
|
||||
document.getElementById('adminAddPersonaForm').style.display = '';
|
||||
form.setValues(p);
|
||||
form.setSubmitLabel('Update');
|
||||
// Load KB bindings (v0.17.0)
|
||||
@@ -271,73 +271,73 @@ function editAdminPreset(id) {
|
||||
}
|
||||
}
|
||||
|
||||
async function createAdminPreset(vals) {
|
||||
async function createAdminPersona(vals) {
|
||||
if (!vals) {
|
||||
if (_adminPresetForm) vals = _adminPresetForm.getValues();
|
||||
if (_adminPersonaForm) vals = _adminPersonaForm.getValues();
|
||||
else return;
|
||||
}
|
||||
if (!vals.name || !vals.base_model_id) { UI.toast('Name and base model are required', 'warning'); return; }
|
||||
|
||||
const preset = {
|
||||
const persona = {
|
||||
name: vals.name,
|
||||
base_model_id: vals.base_model_id,
|
||||
description: vals.description || '',
|
||||
system_prompt: vals.system_prompt || '',
|
||||
};
|
||||
if (vals.provider_config_id) preset.provider_config_id = vals.provider_config_id;
|
||||
if (vals.temperature != null) preset.temperature = vals.temperature;
|
||||
if (vals.max_tokens != null) preset.max_tokens = vals.max_tokens;
|
||||
if (vals.provider_config_id) persona.provider_config_id = vals.provider_config_id;
|
||||
if (vals.temperature != null) persona.temperature = vals.temperature;
|
||||
if (vals.max_tokens != null) persona.max_tokens = vals.max_tokens;
|
||||
|
||||
try {
|
||||
let presetId = _editingPresetId;
|
||||
if (_editingPresetId) {
|
||||
await API.adminUpdatePreset(_editingPresetId, preset);
|
||||
UI.toast('Preset updated', 'success');
|
||||
let personaId = _editingPersonaId;
|
||||
if (_editingPersonaId) {
|
||||
await API.adminUpdatePersona(_editingPersonaId, preset);
|
||||
UI.toast('Persona updated', 'success');
|
||||
} else {
|
||||
const result = await API.adminCreatePreset(preset);
|
||||
presetId = result?.id || result?.preset?.id;
|
||||
UI.toast('Preset created', 'success');
|
||||
const result = await API.adminCreatePersona(preset);
|
||||
personaId = result?.id || result?.preset?.id;
|
||||
UI.toast('Persona created', 'success');
|
||||
}
|
||||
|
||||
// Upload pending avatar for new presets
|
||||
if (!_editingPresetId && presetId && vals._pendingAvatar) {
|
||||
try { await API.adminUploadPresetAvatar(presetId, vals._pendingAvatar); }
|
||||
catch (e) { console.warn('Preset avatar upload failed:', e.message); }
|
||||
// Upload pending avatar for new personas
|
||||
if (!_editingPersonaId && personaId && vals._pendingAvatar) {
|
||||
try { await API.adminUploadPersonaAvatar(personaId, vals._pendingAvatar); }
|
||||
catch (e) { console.warn('Persona avatar upload failed:', e.message); }
|
||||
}
|
||||
|
||||
// Save KB bindings (v0.17.0)
|
||||
if (presetId && vals._kbValues && _adminPresetForm?.kbPicker) {
|
||||
try { await API.adminSetPresetKBs(presetId, vals._kbValues); }
|
||||
catch (e) { console.warn('Preset KB binding failed:', e.message); }
|
||||
if (personaId && vals._kbValues && _adminPersonaForm?.kbPicker) {
|
||||
try { await API.adminSetPresetKBs(personaId, vals._kbValues); }
|
||||
catch (e) { console.warn('Persona KB binding failed:', e.message); }
|
||||
}
|
||||
|
||||
_editingPresetId = null;
|
||||
document.getElementById('adminAddPresetForm').style.display = 'none';
|
||||
if (_adminPresetForm) {
|
||||
_adminPresetForm.setSubmitLabel('Create');
|
||||
_adminPresetForm.clearForm();
|
||||
_editingPersonaId = null;
|
||||
document.getElementById('adminAddPersonaForm').style.display = 'none';
|
||||
if (_adminPersonaForm) {
|
||||
_adminPersonaForm.setSubmitLabel('Create');
|
||||
_adminPersonaForm.clearForm();
|
||||
}
|
||||
await UI.loadAdminPresets();
|
||||
await UI.loadAdminPersonas();
|
||||
await fetchModels();
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function toggleAdminPreset(id, active) {
|
||||
async function toggleAdminPersona(id, active) {
|
||||
try {
|
||||
const el = _adminScroll(), pos = el?.scrollTop || 0;
|
||||
await API.adminUpdatePreset(id, { is_active: active });
|
||||
await UI.loadAdminPresets(true);
|
||||
await API.adminUpdatePersona(id, { is_active: active });
|
||||
await UI.loadAdminPersonas(true);
|
||||
_restoreScroll(el, pos);
|
||||
await fetchModels();
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function deleteAdminPreset(id, name) {
|
||||
if (!await showConfirm(`Delete preset "${name}"?`)) return;
|
||||
async function deleteAdminPersona(id, name) {
|
||||
if (!await showConfirm(`Delete persona "${name}"?`)) return;
|
||||
try {
|
||||
await API.adminDeletePreset(id);
|
||||
UI.toast('Preset deleted', 'success');
|
||||
await UI.loadAdminPresets();
|
||||
await API.adminDeletePersona(id);
|
||||
UI.toast('Persona deleted', 'success');
|
||||
await UI.loadAdminPersonas();
|
||||
await fetchModels();
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
@@ -400,12 +400,12 @@ async function settingsRemoveTeamMember(teamId, memberId, email) {
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function settingsDeleteTeamPreset(teamId, presetId, name) {
|
||||
if (!await showConfirm(`Delete team preset "${name}"?`)) return;
|
||||
async function settingsDeleteTeamPersona(teamId, personaId, name) {
|
||||
if (!await showConfirm(`Delete team persona "${name}"?`)) return;
|
||||
try {
|
||||
await API.teamDeletePreset(teamId, presetId);
|
||||
UI.toast('Preset deleted');
|
||||
await UI.loadTeamManagePresets(teamId);
|
||||
await API.teamDeletePreset(teamId, personaId);
|
||||
UI.toast('Persona deleted');
|
||||
await UI.loadTeamManagePersonas(teamId);
|
||||
await fetchModels();
|
||||
} catch (e) { UI.toast(e.message, 'error'); }
|
||||
}
|
||||
@@ -483,14 +483,14 @@ function _initAdminListeners() {
|
||||
// Admin — models
|
||||
document.getElementById('adminFetchModelsBtn')?.addEventListener('click', fetchAdminModels);
|
||||
|
||||
// Admin — presets (shared form)
|
||||
document.getElementById('adminAddPresetBtn')?.addEventListener('click', () => {
|
||||
const form = ensureAdminPresetForm();
|
||||
// Admin — personas (shared form)
|
||||
document.getElementById('adminAddPersonaBtn')?.addEventListener('click', () => {
|
||||
const form = ensureAdminPersonaForm();
|
||||
if (!form) return;
|
||||
_editingPresetId = null;
|
||||
_editingPersonaId = null;
|
||||
form.setSubmitLabel('Create');
|
||||
form.clearForm();
|
||||
const f = document.getElementById('adminAddPresetForm');
|
||||
const f = document.getElementById('adminAddPersonaForm');
|
||||
f.style.display = f.style.display === 'none' ? '' : 'none';
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user