import sqlite3 import os import json from datetime import datetime class DatabaseManager: def __init__(self, db_path='dashboard.db'): self.db_path = db_path self.init_database() def init_database(self): """Initialize the database with required tables""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() # Create applications table for storing custom app data cursor.execute(''' CREATE TABLE IF NOT EXISTS applications ( id INTEGER PRIMARY KEY AUTOINCREMENT, container_id TEXT UNIQUE, container_name TEXT NOT NULL, display_name TEXT, icon TEXT DEFAULT 'fas fa-cube', color TEXT DEFAULT 'gray', description TEXT, url TEXT, status TEXT DEFAULT 'unknown', custom_data TEXT, -- JSON for additional custom fields created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') # Add status column if it doesn't exist (for backward compatibility) try: cursor.execute("ALTER TABLE applications ADD COLUMN status TEXT DEFAULT 'unknown'") print("Added status column to applications table") except sqlite3.OperationalError as e: if "duplicate column name" not in str(e).lower(): print(f"Note: {e}") # Create settings table for general configuration cursor.execute(''' CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') conn.commit() conn.close() def get_connection(self): """Get database connection""" return sqlite3.connect(self.db_path) def upsert_application(self, container_data): """Insert or update application data""" conn = self.get_connection() cursor = conn.cursor() container_id = container_data.get('id') container_name = container_data.get('name') display_name = container_data.get('display_name', container_name) icon = container_data.get('icon', 'fas fa-cube') color = container_data.get('color', 'gray') description = container_data.get('description', container_data.get('image', '')) url = container_data.get('url', '#') custom_data = json.dumps(container_data.get('custom_data', {})) cursor.execute(''' INSERT OR REPLACE INTO applications (container_id, container_name, display_name, icon, color, description, url, custom_data, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) ''', (container_id, container_name, display_name, icon, color, description, url, custom_data)) conn.commit() conn.close() def get_applications(self): """Get all applications""" conn = self.get_connection() cursor = conn.cursor() cursor.execute(''' SELECT container_id, container_name, display_name, icon, color, description, url, custom_data FROM applications ORDER BY display_name ''') results = cursor.fetchall() conn.close() applications = [] for row in results: app = { 'container_id': row[0], 'container_name': row[1], 'display_name': row[2], 'icon': row[3], 'color': row[4], 'description': row[5], 'url': row[6], 'custom_data': json.loads(row[7]) if row[7] else {} } applications.append(app) return applications def get_application(self, container_id): """Get specific application by container_id""" conn = self.get_connection() cursor = conn.cursor() cursor.execute(''' SELECT container_id, container_name, display_name, icon, color, description, url, custom_data FROM applications WHERE container_id = ? ''', (container_id,)) result = cursor.fetchone() conn.close() if result: return { 'container_id': result[0], 'container_name': result[1], 'display_name': result[2], 'icon': result[3], 'color': result[4], 'description': result[5], 'url': result[6], 'custom_data': json.loads(result[7]) if result[7] else {} } return None def update_application(self, container_id, updates): """Update application data""" conn = self.get_connection() cursor = conn.cursor() set_clause = [] values = [] for key, value in updates.items(): if key == 'custom_data': value = json.dumps(value) set_clause.append(f"{key} = ?") values.append(value) if set_clause: set_clause.append("updated_at = CURRENT_TIMESTAMP") values.append(container_id) query = f"UPDATE applications SET {', '.join(set_clause)} WHERE container_id = ?" cursor.execute(query, values) conn.commit() conn.close() def delete_application(self, container_id): """Delete application""" conn = self.get_connection() cursor = conn.cursor() cursor.execute('DELETE FROM applications WHERE container_id = ?', (container_id,)) conn.commit() conn.close() def sync_with_containers(self, containers): """Sync applications with current containers""" conn = self.get_connection() cursor = conn.cursor() # Get existing container IDs cursor.execute('SELECT container_id FROM applications') existing_ids = {row[0] for row in cursor.fetchall()} # Insert new containers for container in containers: container_id = container.get('id') if container_id not in existing_ids: self.upsert_application({ 'id': container_id, 'name': container.get('name', ''), 'description': container.get('image', ''), 'url': self._generate_url_from_ports(container.get('ports', [])) }) conn.close() def _generate_url_from_ports(self, ports): """Generate URL from container ports""" if ports and len(ports) > 0: port = ports[0] return f"http://localhost:{port.get('host_port', port.get('private_port', 80))}" return '#' # Global database instance db = DatabaseManager()