// Pawprint Wrapper - Sidebar Logic class PawprintSidebar { constructor() { this.config = null; this.currentUser = null; this.sidebar = null; this.toggleBtn = null; } async init() { // Load configuration await this.loadConfig(); // Create sidebar elements this.createSidebar(); this.createToggleButton(); // Setup event listeners this.setupEventListeners(); // Check if user is already logged in this.checkCurrentUser(); // Load saved sidebar state this.loadSidebarState(); } async loadConfig() { try { const response = await fetch('/wrapper/config.json'); this.config = await response.json(); console.log('[Pawprint] Config loaded:', this.config.nest_name); } catch (error) { console.error('[Pawprint] Failed to load config:', error); // Use default config this.config = { nest_name: 'default', wrapper: { environment: { backend_url: 'http://localhost:8000', frontend_url: 'http://localhost:3000' }, users: [] } }; } } createSidebar() { const sidebar = document.createElement('div'); sidebar.id = 'pawprint-sidebar'; sidebar.innerHTML = this.getSidebarHTML(); document.body.appendChild(sidebar); this.sidebar = sidebar; } createToggleButton() { const button = document.createElement('button'); button.id = 'sidebar-toggle'; button.innerHTML = '◀'; button.title = 'Toggle Pawprint Sidebar (Ctrl+Shift+P)'; document.body.appendChild(button); this.toggleBtn = button; } getSidebarHTML() { const users = this.config.wrapper.users || []; return `
`; } setupEventListeners() { // Toggle button this.toggleBtn.addEventListener('click', () => this.toggle()); // Keyboard shortcut: Ctrl+Shift+P document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.shiftKey && e.key === 'P') { e.preventDefault(); this.toggle(); } }); } toggle() { this.sidebar.classList.toggle('expanded'); this.saveSidebarState(); } saveSidebarState() { const isExpanded = this.sidebar.classList.contains('expanded'); localStorage.setItem('pawprint_sidebar_expanded', isExpanded); } loadSidebarState() { const isExpanded = localStorage.getItem('pawprint_sidebar_expanded') === 'true'; if (isExpanded) { this.sidebar.classList.add('expanded'); } } showStatus(message, type = 'info') { const container = document.getElementById('status-container'); const statusDiv = document.createElement('div'); statusDiv.className = `status-message ${type}`; statusDiv.textContent = message; container.innerHTML = ''; container.appendChild(statusDiv); // Auto-remove after 5 seconds setTimeout(() => { statusDiv.remove(); }, 5000); } async loginAs(userId) { const user = this.config.wrapper.users.find(u => u.id === userId); if (!user) return; this.showStatus(`Logging in as ${user.label}... ⏳`, 'info'); try { const backendUrl = this.config.wrapper.environment.backend_url; const response = await fetch(`${backendUrl}/api/token/`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username: user.username, password: user.password }) }); if (!response.ok) { throw new Error(`Login failed: ${response.status}`); } const data = await response.json(); // Store tokens localStorage.setItem('access_token', data.access); localStorage.setItem('refresh_token', data.refresh); // Store user info localStorage.setItem('user_info', JSON.stringify({ username: user.username, label: user.label, role: data.details?.role || user.role })); this.showStatus(`✓ Logged in as ${user.label}`, 'success'); this.currentUser = user; this.updateCurrentUserDisplay(); // Reload page after short delay setTimeout(() => { window.location.reload(); }, 1000); } catch (error) { console.error('[Pawprint] Login error:', error); this.showStatus(`✗ Login failed: ${error.message}`, 'error'); } } logout() { localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); localStorage.removeItem('user_info'); this.showStatus('✓ Logged out', 'success'); this.currentUser = null; this.updateCurrentUserDisplay(); // Reload page after short delay setTimeout(() => { window.location.reload(); }, 1000); } checkCurrentUser() { const userInfo = localStorage.getItem('user_info'); if (userInfo) { try { this.currentUser = JSON.parse(userInfo); this.updateCurrentUserDisplay(); } catch (error) { console.error('[Pawprint] Failed to parse user info:', error); } } } updateCurrentUserDisplay() { const display = document.getElementById('current-user-display'); const username = document.getElementById('current-username'); if (this.currentUser) { display.style.display = 'block'; username.textContent = this.currentUser.username; // Highlight active user card document.querySelectorAll('.user-card').forEach(card => { card.classList.remove('active'); }); const activeCard = document.querySelector(`.user-card[data-user-id="${this.getUserIdByUsername(this.currentUser.username)}"]`); if (activeCard) { activeCard.classList.add('active'); } } else { display.style.display = 'none'; } } getUserIdByUsername(username) { const user = this.config.wrapper.users.find(u => u.username === username); return user ? user.id : null; } } // Initialize sidebar when DOM is ready const pawprintSidebar = new PawprintSidebar(); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => pawprintSidebar.init()); } else { pawprintSidebar.init(); } console.log('[Pawprint] Sidebar script loaded');