ishingiro / chatbot /config-ui.js
IZERE HIRWA Roger
add lg files
eeacc46
raw
history blame
15.3 kB
/**
* Configuration UI Management
* Provides UI components for managing frontend configuration
*/
(() => {
'use strict';
class ConfigUI {
constructor() {
this.config = window.AIMHSA?.Config;
this.init();
}
init() {
this.createConfigPanel();
this.bindEvents();
console.log('⚙️ Configuration UI initialized');
}
/**
* Create configuration panel
*/
createConfigPanel() {
const configPanel = document.createElement('div');
configPanel.id = 'configPanel';
configPanel.className = 'config-panel';
configPanel.innerHTML = `
<div class="config-header">
<h3><i class="fas fa-cog"></i> Configuration</h3>
<button class="btn btn-sm btn-outline-secondary" id="toggleConfigPanel">
<i class="fas fa-times"></i>
</button>
</div>
<div class="config-content">
<div class="config-section">
<h4>API Configuration</h4>
<div class="form-group">
<label>API Base URL</label>
<input type="url" id="apiBaseUrl" class="form-control"
value="${this.config?.getApiBaseUrl() || ''}"
placeholder="https://prodevroger-ishingiro.hf.space">
<small class="form-text text-muted">
Base URL for the backend API server
</small>
</div>
<div class="form-group">
<label>Environment</label>
<select id="environment" class="form-control">
<option value="development">Development</option>
<option value="staging">Staging</option>
<option value="production">Production</option>
</select>
</div>
<button class="btn btn-primary btn-sm" id="testConnection">
<i class="fas fa-plug"></i> Test Connection
</button>
</div>
<div class="config-section">
<h4>UI Configuration</h4>
<div class="form-group">
<label>Theme</label>
<select id="theme" class="form-control">
<option value="dark">Dark</option>
<option value="light">Light</option>
</select>
</div>
<div class="form-group">
<label>Auto-refresh Interval (seconds)</label>
<input type="number" id="autoRefresh" class="form-control"
value="${this.config?.get('ui.autoRefreshInterval', 30000) / 1000}"
min="5" max="300">
</div>
</div>
<div class="config-actions">
<button class="btn btn-success btn-sm" id="saveConfig">
<i class="fas fa-save"></i> Save Configuration
</button>
<button class="btn btn-warning btn-sm" id="resetConfig">
<i class="fas fa-undo"></i> Reset to Defaults
</button>
</div>
<div class="config-info">
<h4>Environment Information</h4>
<pre id="envInfo"></pre>
</div>
</div>
`;
// Add styles
const style = document.createElement('style');
style.textContent = `
.config-panel {
position: fixed;
top: 20px;
right: -400px;
width: 380px;
height: calc(100vh - 40px);
background: var(--surface, #1e293b);
border: 1px solid var(--border, #334155);
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
z-index: 10000;
transition: right 0.3s ease;
overflow-y: auto;
}
.config-panel.open {
right: 20px;
}
.config-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
border-bottom: 1px solid var(--border, #334155);
background: var(--primary, #7c3aed);
color: white;
border-radius: 12px 12px 0 0;
}
.config-header h3 {
margin: 0;
font-size: 1.1rem;
}
.config-content {
padding: 1rem;
}
.config-section {
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--border-light, #475569);
}
.config-section:last-child {
border-bottom: none;
}
.config-section h4 {
color: var(--text, #f8fafc);
font-size: 1rem;
margin-bottom: 1rem;
}
.config-actions {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
}
.config-info pre {
background: var(--background, #0f172a);
padding: 0.5rem;
border-radius: 4px;
font-size: 0.8rem;
color: var(--text-secondary, #cbd5e1);
border: 1px solid var(--border, #334155);
max-height: 200px;
overflow-y: auto;
}
.config-toggle {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
background: var(--primary, #7c3aed);
color: white;
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(124, 58, 237, 0.3);
}
.config-toggle:hover {
background: var(--primary-dark, #5b21b6);
transform: scale(1.1);
}
`;
document.head.appendChild(style);
document.body.appendChild(configPanel);
// Create toggle button
const toggleBtn = document.createElement('button');
toggleBtn.id = 'configToggle';
toggleBtn.className = 'config-toggle';
toggleBtn.innerHTML = '<i class="fas fa-cog"></i>';
toggleBtn.title = 'Configuration Settings';
document.body.appendChild(toggleBtn);
this.updateEnvironmentInfo();
}
/**
* Bind event handlers
*/
bindEvents() {
// Toggle panel
document.getElementById('configToggle').addEventListener('click', () => {
this.togglePanel();
});
document.getElementById('toggleConfigPanel').addEventListener('click', () => {
this.togglePanel();
});
// Save configuration
document.getElementById('saveConfig').addEventListener('click', () => {
this.saveConfiguration();
});
// Reset configuration
document.getElementById('resetConfig').addEventListener('click', () => {
this.resetConfiguration();
});
// Test connection
document.getElementById('testConnection').addEventListener('click', () => {
this.testConnection();
});
// Real-time updates
document.getElementById('apiBaseUrl').addEventListener('input', (e) => {
if (this.config) {
this.config.setApiBaseUrl(e.target.value);
}
});
// Close panel on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.closePanel();
}
});
}
/**
* Toggle configuration panel
*/
togglePanel() {
const panel = document.getElementById('configPanel');
panel.classList.toggle('open');
if (panel.classList.contains('open')) {
this.loadCurrentSettings();
this.updateEnvironmentInfo();
}
}
/**
* Close configuration panel
*/
closePanel() {
const panel = document.getElementById('configPanel');
panel.classList.remove('open');
}
/**
* Load current settings into UI
*/
loadCurrentSettings() {
if (!this.config) return;
document.getElementById('apiBaseUrl').value = this.config.getApiBaseUrl();
document.getElementById('environment').value = this.config.environment;
document.getElementById('theme').value = this.config.get('ui.theme', 'dark');
document.getElementById('autoRefresh').value = this.config.get('ui.autoRefreshInterval', 30000) / 1000;
}
/**
* Save configuration
*/
saveConfiguration() {
if (!this.config) return;
const apiBaseUrl = document.getElementById('apiBaseUrl').value;
const environment = document.getElementById('environment').value;
const theme = document.getElementById('theme').value;
const autoRefresh = parseInt(document.getElementById('autoRefresh').value) * 1000;
// Update configuration
this.config.setApiBaseUrl(apiBaseUrl);
this.config.set('ui.theme', theme);
this.config.set('ui.autoRefreshInterval', autoRefresh);
// Show success message
this.showToast('Configuration saved successfully!', 'success');
// Optionally reload the page to apply changes
if (confirm('Configuration saved. Reload the page to apply changes?')) {
window.location.reload();
}
}
/**
* Reset configuration to defaults
*/
resetConfiguration() {
if (!this.config) return;
if (confirm('Are you sure you want to reset all configuration to defaults?')) {
this.config.reset();
this.loadCurrentSettings();
this.updateEnvironmentInfo();
this.showToast('Configuration reset to defaults', 'info');
}
}
/**
* Test API connection
*/
async testConnection() {
if (!this.config) return;
const button = document.getElementById('testConnection');
const originalText = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Testing...';
button.disabled = true;
try {
const isConnected = await this.config.validateApiConnection();
if (isConnected) {
this.showToast('API connection successful!', 'success');
} else {
this.showToast('API connection failed', 'error');
}
} catch (error) {
this.showToast('Connection test failed: ' + error.message, 'error');
} finally {
button.innerHTML = originalText;
button.disabled = false;
}
}
/**
* Update environment information display
*/
updateEnvironmentInfo() {
if (!this.config) return;
const envInfo = this.config.getEnvironmentInfo();
const formattedInfo = JSON.stringify(envInfo, null, 2);
document.getElementById('envInfo').textContent = formattedInfo;
}
/**
* Show toast notification
*/
showToast(message, type = 'info') {
// Use SweetAlert2 if available
if (typeof Swal !== 'undefined') {
Swal.fire({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
icon: type === 'error' ? 'error' : type === 'success' ? 'success' : 'info',
title: message
});
return;
}
// Fallback to simple alert
const alertClass = type === 'error' ? 'alert-danger' :
type === 'success' ? 'alert-success' : 'alert-info';
const toast = document.createElement('div');
toast.className = `alert ${alertClass} alert-dismissible fade show`;
toast.style.cssText = `
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 10001;
min-width: 300px;
`;
toast.innerHTML = `
${message}
<button type="button" class="close" onclick="this.parentElement.remove()">
<span>&times;</span>
</button>
`;
document.body.appendChild(toast);
setTimeout(() => {
if (toast.parentElement) {
toast.remove();
}
}, 3000);
}
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
new ConfigUI();
});
} else {
new ConfigUI();
}
})();