/** * Main Application Logic * Orchestrates API calls and UI updates */ class CVSRepositoryBrowser { constructor() { this.currentFile = null; this.currentHistory = null; this.initialize(); } /** * Initialize the application */ async initialize() { try { // Check API health await this.checkHealth(); // Load initial repository tree await this.loadTree(); // Setup event listeners this.setupEventListeners(); ui.updateStatus('Connected', 'connected'); } catch (error) { console.error('Initialization error:', error); ui.updateStatus('Connection Error', 'error'); } } /** * Check API health */ async checkHealth() { try { const health = await api.getHealth(); console.log('API Health:', health); return health; } catch (error) { throw new Error('Failed to connect to API'); } } /** * Load repository tree */ async loadTree() { try { ui.treeContainer.innerHTML = '
Loading repository...
'; const files = await api.getTree(); ui.buildTree(files, (filePath) => this.loadFile(filePath)); } catch (error) { console.error('Error loading tree:', error); ui.treeContainer.innerHTML = `
Error loading repository: ${error.message}
`; } } /** * Load file content * @param {string} filePath - Path to the file * @param {string} revision - Optional specific revision */ async loadFile(filePath, revision = null) { try { this.currentFile = filePath; ui.showLoading('Loading file...'); const content = await api.getFileContent(filePath, revision); ui.displayFile(filePath, content); // Load history for this file await this.loadFileHistory(filePath); } catch (error) { console.error('Error loading file:', error); ui.showError(`Error loading file: ${error.message}`); } } /** * Load file at specific revision * @param {string} filePath - Path to the file * @param {string} revision - Specific revision */ async loadFileAtRevision(filePath, revision) { try { await this.loadFile(filePath, revision); ui.showView(ui.fileView); } catch (error) { console.error('Error loading file at revision:', error); ui.showError(`Error loading file: ${error.message}`); } } /** * Load file history * @param {string} filePath - Path to the file */ async loadFileHistory(filePath) { try { const history = await api.getFileHistory(filePath); this.currentHistory = history; ui.populateRevisionSelectors(history); } catch (error) { console.error('Error loading history:', error); } } /** * Show file history view */ async showHistory() { if (!this.currentFile) return; try { ui.showLoading('Loading history...'); const history = await api.getFileHistory(this.currentFile); ui.displayHistory(history); } catch (error) { console.error('Error showing history:', error); ui.showError(`Error loading history: ${error.message}`); } } /** * Show diff view */ showDiffView() { if (!this.currentFile || !this.currentHistory) return; ui.populateRevisionSelectors(this.currentHistory); ui.showView(ui.diffView); } /** * Generate and display diff */ async generateDiff() { if (!this.currentFile) return; const rev1 = ui.rev1Select.value; const rev2 = ui.rev2Select.value; if (!rev1 || !rev2) { ui.showError('Please select two revisions'); return; } try { ui.diffContent.innerHTML = '
Generating diff...
'; const diffResult = await api.getDiff(this.currentFile, rev1, rev2); const diffText = diffResult.diff || diffResult; ui.displayDiff(diffText); } catch (error) { console.error('Error generating diff:', error); ui.showError(`Error generating diff: ${error.message}`); } } /** * Show diff for a history item (comparing with previous revision) * @param {string} filePath - Path to the file * @param {string} currentRevision - Current revision * @param {string} previousRevision - Previous revision (or null if this is the first) */ async showHistoryItemDiff(filePath, currentRevision, previousRevision) { if (!filePath) return; try { ui.diffContent.innerHTML = '
Generating diff...
'; if (!previousRevision) { // If there's no previous revision, show a message ui.diffContent.innerHTML = '
This is the first revision - no previous version to compare
'; ui.showView(ui.diffView); return; } // Generate diff between previous and current revision const diffResult = await api.getDiff(filePath, previousRevision, currentRevision); const diffText = diffResult.diff || diffResult; ui.displayDiff(diffText); } catch (error) { console.error('Error generating history item diff:', error); ui.diffContent.innerHTML = `
Error generating diff: ${error.message}
`; ui.showView(ui.diffView); } } /** * Show patchsets view */ async showPatchsets() { try { ui.patchsetContent.innerHTML = '
Loading patchsets...
'; const patchsets = await api.getPatchsets(); ui.displayPatchsets(patchsets); } catch (error) { console.error('Error showing patchsets:', error); ui.patchsetContent.innerHTML = `
Error loading patchsets: ${error.message}
`; ui.showView(ui.patchsetView); } } /** * Show patchset diff * @param {string} patchset - Patchset number */ async showPatchsetDiff(patchset) { try { ui.patchsetDiffContent.innerHTML = '
Loading patchset diff...
'; const diffResult = await api.getPatchsetDiff(patchset); const diffText = diffResult.diff || diffResult; ui.displayPatchsetDiff(diffText); } catch (error) { console.error('Error showing patchset diff:', error); ui.patchsetDiffContent.innerHTML = `
Error loading patchset diff: ${error.message}
`; ui.showView(ui.patchsetDiffView); } } /** * Setup event listeners */ setupEventListeners() { // File view buttons ui.historyBtn.addEventListener('click', () => this.showHistory()); ui.diffBtn.addEventListener('click', () => this.showDiffView()); // History view back button ui.backFromHistoryBtn.addEventListener('click', () => { ui.showView(ui.fileView); }); // Diff view buttons ui.generateDiffBtn.addEventListener('click', () => this.generateDiff()); ui.backFromDiffBtn.addEventListener('click', () => { ui.showView(ui.fileView); }); // Patchset view buttons ui.patchsetsBtn.addEventListener('click', () => this.showPatchsets()); ui.backFromPatchsetBtn.addEventListener('click', () => { ui.showView(ui.welcomeView); }); // Patchset diff view back button ui.backFromPatchsetDiffBtn.addEventListener('click', () => { ui.showView(ui.patchsetView); }); } } // Initialize application when DOM is ready document.addEventListener('DOMContentLoaded', () => { window.app = new CVSRepositoryBrowser(); });