/** * Brief Bench - Main Entry Point * * Главная точка входа приложения. * Импортирует все модули и инициализирует приложение. */ // Import services import * as authService from './services/auth.service.js' import settingsService from './services/settings.service.js' import queryService from './services/query.service.js' // Import UI components import authUI from './ui/auth.ui.js' import loadingUI from './ui/loading.ui.js' import settingsUI from './ui/settings.ui.js' import queryBuilderUI from './ui/query-builder.ui.js' import questionsListUI from './ui/questions-list.ui.js' import answerViewerUI from './ui/answer-viewer.ui.js' import annotationsUI from './ui/annotations.ui.js' // Import state import appState from './state/appState.js' // Import utils import { showToast } from './utils/dom.utils.js' import { downloadJSON } from './utils/file.utils.js' import { ENVIRONMENTS } from './config.js' // ============================================ // Global Functions (for HTML onclick handlers) // ============================================ /** * Expose functions to window for HTML onclick handlers */ window.selectAnswer = function(index) { questionsListUI.selectAnswer(index, (idx) => { answerViewerUI.render(idx, annotationsUI.loadForAnswer) }) } window.toggleExpansion = function(id) { answerViewerUI.toggleExpansion(id) } window.switchTab = function(tabButton, tabId) { queryBuilderUI.switchTab(tabButton, tabId) } // ============================================ // Environment Management // ============================================ /** * Switch to a different environment * @param {string} env - Environment name (ift/psi/prod) */ function switchEnvironment(env) { // Save current environment data const currentEnv = appState.getCurrentEnvironment() appState.saveEnvironmentToStorage(currentEnv) // Switch environment appState.setCurrentEnvironment(env) appState.updateSettings({ activeEnvironment: env }) // Update UI updateEnvironmentTabs() // Reload content for new environment const newEnv = appState.getCurrentEnv() if (newEnv.currentResponse) { questionsListUI.render() answerViewerUI.render(newEnv.currentAnswerIndex, annotationsUI.loadForAnswer) } else { queryBuilderUI.show() } console.log('Switched to environment:', env) } /** * Update environment tabs visual state */ function updateEnvironmentTabs() { const currentEnv = appState.getCurrentEnvironment() document.querySelectorAll('.env-tab').forEach(tab => { if (tab.dataset.env === currentEnv) { tab.classList.add('active') } else { tab.classList.remove('active') } }) } // ============================================ // Event Listeners Setup // ============================================ /** * Setup all event listeners */ function setupEventListeners() { // Prevent double-binding if (window._eventListenersSetup) { return } window._eventListenersSetup = true // Environment tabs document.querySelectorAll('.env-tab').forEach(tab => { tab.addEventListener('click', (e) => { const env = e.target.dataset.env if (env) { switchEnvironment(env) } }) }) // Settings environment selector change const settingsEnvSelector = document.getElementById('settings-env-selector') if (settingsEnvSelector) { settingsEnvSelector.addEventListener('change', () => { // Save current environment settings first const currentSettings = settingsUI.read() if (currentSettings) { appState.setSettings(currentSettings) } // Load new environment settings settingsUI.populate() }) } // Setup UI component listeners authUI.setupListeners() settingsUI.setupListeners() queryBuilderUI.setupListeners(() => { // Callback after successful query questionsListUI.render() answerViewerUI.render(0, annotationsUI.loadForAnswer) }) // Tab switching document.querySelectorAll('.tab').forEach(tab => { tab.addEventListener('click', (e) => { const tabId = e.target.dataset.tab if (tabId) { queryBuilderUI.switchTab(e.target, tabId) } }) }) // Close dialog on overlay click const settingsDialog = document.getElementById('settings-dialog') if (settingsDialog) { settingsDialog.addEventListener('click', (e) => { if (e.target.id === 'settings-dialog') { settingsUI.close() } }) } console.log('Event listeners setup complete') } // ============================================ // Export/Import Functions // ============================================ /** * Export current analysis to JSON file */ window.exportAnalysis = function() { const env = appState.getCurrentEnv() const currentEnvKey = appState.getCurrentEnvironment() if (!env.currentResponse) { showToast('Нет данных для экспорта', 'warning') return } const exportData = { environment: currentEnvKey, request_id: env.requestId, timestamp: env.requestTimestamp, request: env.currentRequest, response: env.currentResponse, annotations: env.annotations } const timestamp = new Date().toISOString().replace(/[:.]/g, '-').substring(0, 19) const filename = `brief-bench-analysis-${currentEnvKey}-${timestamp}.json` downloadJSON(exportData, filename) showToast(`Анализ экспортирован: ${filename}`, 'success') } /** * Import analysis from JSON file */ window.importAnalysis = function() { const input = document.createElement('input') input.type = 'file' input.accept = 'application/json' input.onchange = async (e) => { const file = e.target.files[0] if (!file) return try { loadingUI.show('Импорт анализа...') const text = await file.text() const data = JSON.parse(text) // Validate data if (!data.response || !data.response.answers) { throw new Error('Некорректный формат файла анализа') } const currentEnvKey = appState.getCurrentEnvironment() const env = appState.getEnvironment(currentEnvKey) // Load data env.currentRequest = data.request || [] env.currentResponse = data.response env.requestId = data.request_id || 'imported' env.requestTimestamp = data.timestamp || new Date().toISOString() env.annotations = data.annotations || {} env.currentAnswerIndex = 0 // Save to localStorage appState.saveEnvironmentToStorage(currentEnvKey) // Update UI questionsListUI.render() answerViewerUI.render(0, annotationsUI.loadForAnswer) loadingUI.hide() showToast('Анализ успешно импортирован', 'success') } catch (error) { loadingUI.hide() console.error('Failed to import analysis:', error) showToast(`Ошибка импорта: ${error.message}`, 'error') } } input.click() } // ============================================ // Application Initialization // ============================================ /** * Initialize application */ async function initApp() { try { // Load settings from server await settingsService.loadFromServer() // Set current environment from settings const activeEnv = appState.settings?.activeEnvironment || 'ift' appState.setCurrentEnvironment(activeEnv) // Load saved data for each environment from localStorage ENVIRONMENTS.forEach(env => { appState.loadEnvironmentFromStorage(env) }) // Setup event listeners setupEventListeners() // Update environment tabs updateEnvironmentTabs() // Show query builder by default queryBuilderUI.show() console.log('Brief Bench initialized - Environment:', appState.getCurrentEnvironment()) } catch (error) { console.error('Failed to initialize app:', error) showToast('Ошибка инициализации приложения', 'error') } } // ============================================ // Application Entry Point // ============================================ /** * Initialize app on DOM load */ document.addEventListener('DOMContentLoaded', async () => { console.log('Brief Bench starting...') // Setup event listeners first (including login/logout) setupEventListeners() // Check authentication const isAuthenticated = await authService.checkAuth() if (isAuthenticated) { // User is authenticated, initialize app authUI.hideLoginScreen() await initApp() } else { // User is not authenticated, show login screen authUI.showLoginScreen() } })