LocalScriptsWeb/frontend/static/js/main.js

226 lines
7.1 KiB
JavaScript

// frontend/static/js/main.js
// Estado global
let currentProfile = null;
let currentGroup = null;
// Estilos comunes
const STYLES = {
editableInput: "mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500",
readonlyInput: "mt-1 block w-full rounded-md border-2 border-gray-200 bg-gray-100 px-3 py-2 shadow-sm",
button: "px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600",
buttonSecondary: "px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300"
};
// Inicialización de la aplicación
async function initializeApp() {
try {
console.log('Initializing application...');
// Cargar perfiles
const profiles = await apiRequest('/profiles');
console.log('Profiles loaded:', profiles);
// Obtener último perfil usado
const lastProfileId = localStorage.getItem('lastProfileId') || 'default';
console.log('Last profile ID:', lastProfileId);
// Actualizar selector de perfiles
updateProfileSelector(profiles);
// Seleccionar el último perfil usado
const selectedProfile = profiles.find(p => p.id === lastProfileId) || profiles[0];
if (selectedProfile) {
console.log('Selecting profile:', selectedProfile.id);
await selectProfile(selectedProfile.id);
}
// Restaurar último estado
await restoreLastState();
} catch (error) {
console.error('Error initializing application:', error);
showError('Error initializing application');
}
}
// Funciones de API
async function apiRequest(endpoint, options = {}) {
try {
const response = await fetch(`/api${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'API request error');
}
return await response.json();
} catch (error) {
console.error('API Error:', error);
showError(error.message);
throw error;
}
}
// Funciones de gestión de perfiles
async function selectProfile(profileId) {
try {
console.log('Selecting profile:', profileId);
// Cargar perfil
currentProfile = await apiRequest(`/profiles/${profileId}`);
// Guardar en localStorage
localStorage.setItem('lastProfileId', profileId);
console.log('Profile ID saved:', profileId);
// Actualizar UI
updateProfileSelector([currentProfile]);
updateProfileDisplay();
return currentProfile;
} catch (error) {
console.error('Error selecting profile:', error);
showError('Error loading profile');
throw error;
}
}
function updateProfileSelector(profiles) {
const select = document.getElementById('profileSelect');
if (!select) return;
const lastProfileId = localStorage.getItem('lastProfileId') || 'default';
select.innerHTML = profiles.map(profile => `
<option value="${profile.id}" ${profile.id === lastProfileId ? 'selected' : ''}>
${profile.name}
</option>
`).join('');
}
function updateProfileDisplay() {
const container = document.getElementById('profileConfig');
if (!container || !currentProfile) return;
container.innerHTML = `
<div class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700">Profile ID</label>
<input type="text" value="${currentProfile.id}" readonly
class="${STYLES.readonlyInput}">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Name</label>
<input type="text" value="${currentProfile.name}" readonly
class="${STYLES.readonlyInput}">
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700">Model</label>
<input type="text" value="${currentProfile.llm_settings?.model || ''}" readonly
class="${STYLES.readonlyInput}">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Temperature</label>
<input type="text" value="${currentProfile.llm_settings?.temperature || ''}" readonly
class="${STYLES.readonlyInput}">
</div>
</div>
</div>
`;
}
// Funciones de estado
async function restoreLastState() {
try {
// Restaurar último grupo seleccionado
const lastGroupId = localStorage.getItem('lastGroupId');
if (lastGroupId) {
const groupSelect = document.getElementById('groupSelect');
if (groupSelect) {
groupSelect.value = lastGroupId;
await handleGroupChange({ target: { value: lastGroupId } });
}
}
} catch (error) {
console.error('Error restoring state:', error);
}
}
// Funciones de utilidad UI
function showError(message) {
const output = document.getElementById('outputArea');
if (!output) return;
const timestamp = new Date().toLocaleTimeString();
output.innerHTML += `\n[${timestamp}] ERROR: ${message}`;
output.scrollTop = output.scrollHeight;
}
function showSuccess(message) {
const output = document.getElementById('outputArea');
if (!output) return;
const timestamp = new Date().toLocaleTimeString();
output.innerHTML += `\n[${timestamp}] SUCCESS: ${message}`;
output.scrollTop = output.scrollHeight;
}
function clearOutput() {
const output = document.getElementById('outputArea');
if (output) {
output.innerHTML = '';
}
}
// Event Handlers
async function handleProfileChange(event) {
const profileId = event.target.value;
if (profileId) {
await selectProfile(profileId);
}
}
async function handleGroupChange(event) {
const groupId = event.target.value;
if (groupId) {
localStorage.setItem('lastGroupId', groupId);
await selectGroup(groupId);
} else {
localStorage.removeItem('lastGroupId');
currentGroup = null;
updateGroupDisplay();
}
}
// Modal Helpers
function closeModal(button) {
const modal = button.closest('.modal');
if (modal) {
modal.remove();
}
}
// Error Handler Global
window.addEventListener('unhandledrejection', function(event) {
console.error('Unhandled promise rejection:', event.reason);
showError('An unexpected error occurred');
});
// Exportar funciones globales
window.showError = showError;
window.showSuccess = showSuccess;
window.closeModal = closeModal;
window.STYLES = STYLES;
// Inicializar cuando la página carga
document.addEventListener('DOMContentLoaded', initializeApp);