/** * CLAUDE.md Migration Wizard * Handles multi-step migration of CLAUDE.md rules to database */ let analysisResult = null; let selectedCandidates = []; // Initialize document.addEventListener('DOMContentLoaded', () => { initializeEventListeners(); checkAuth(); }); /** * Initialize all event listeners */ function initializeEventListeners() { // Step 1: Upload document.getElementById('file-upload').addEventListener('change', handleFileUpload); document.getElementById('analyze-btn').addEventListener('click', analyzeClaudeMd); // Step 2: Review document.getElementById('back-to-upload-btn').addEventListener('click', () => goToStep(1)); document.getElementById('create-rules-btn').addEventListener('click', createSelectedRules); // Step 3: Results document.getElementById('migrate-another-btn').addEventListener('click', () => goToStep(1)); // Tab switching document.querySelectorAll('.tab-btn').forEach(btn => { btn.addEventListener('click', (e) => switchTab(e.target.dataset.tab)); }); // Logout document.getElementById('logout-btn').addEventListener('click', logout); } /** * Check authentication */ async function checkAuth() { const token = localStorage.getItem('auth_token'); if (!token) { window.location.href = '/admin/login.html'; } } /** * Handle file upload */ function handleFileUpload(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { document.getElementById('claude-md-content').value = e.target.result; showToast('File loaded successfully', 'success'); }; reader.onerror = () => { showToast('Failed to read file', 'error'); }; reader.readAsText(file); } /** * Analyze CLAUDE.md content */ async function analyzeClaudeMd() { const content = document.getElementById('claude-md-content').value.trim(); if (!content) { showToast('Please upload or paste CLAUDE.md content', 'error'); return; } const analyzeBtn = document.getElementById('analyze-btn'); analyzeBtn.disabled = true; analyzeBtn.textContent = 'Analyzing...'; try { const response = await apiRequest('/api/admin/rules/analyze-claude-md', { method: 'POST', body: JSON.stringify({ content }) }); if (!response.success) { throw new Error(response.message || 'Analysis failed'); } analysisResult = response.analysis; displayAnalysisResults(analysisResult); goToStep(2); } catch (error) { console.error('Analysis error:', error); showToast(error.message || 'Failed to analyze CLAUDE.md', 'error'); } finally { analyzeBtn.disabled = false; analyzeBtn.textContent = 'Analyze CLAUDE.md'; } } /** * Display analysis results */ function displayAnalysisResults(analysis) { // Update statistics document.getElementById('stat-total').textContent = analysis.totalStatements; document.getElementById('stat-high-quality').textContent = analysis.quality.highQuality; document.getElementById('stat-needs-clarification').textContent = analysis.quality.needsClarification; document.getElementById('stat-too-nebulous').textContent = analysis.quality.tooNebulous; // Reset selected candidates selectedCandidates = []; // Display high-quality candidates (auto-selected) const highQualityList = document.getElementById('high-quality-list'); const highQualityCandidates = analysis.candidates.filter(c => c.quality === 'HIGH'); if (highQualityCandidates.length > 0) { highQualityList.innerHTML = highQualityCandidates.map((candidate, index) => `
Original:
${escapeHtml(candidate.originalText)}
Suggested:
${escapeHtml(candidate.suggestedRule.text)}
No high-quality candidates found.
'; } // Display needs clarification candidates const needsClarificationList = document.getElementById('needs-clarification-list'); const needsClarificationCandidates = analysis.candidates.filter(c => c.quality === 'NEEDS_CLARIFICATION'); if (needsClarificationCandidates.length > 0) { needsClarificationList.innerHTML = needsClarificationCandidates.map((candidate, index) => `Original:
${escapeHtml(candidate.originalText)}
Suggested:
${escapeHtml(candidate.suggestedRule.text)}
Issues:
No candidates needing clarification.
'; } // Display too nebulous candidates const tooNebulousList = document.getElementById('too-nebulous-list'); const tooNebulousCandidates = analysis.candidates.filter(c => c.quality === 'TOO_NEBULOUS'); if (tooNebulousCandidates.length > 0) { tooNebulousList.innerHTML = tooNebulousCandidates.map(candidate => `${escapeHtml(candidate.sectionTitle)}
${escapeHtml(candidate.originalText)}
${candidate.improvements && candidate.improvements.length > 0 ? `Suggestions:
No too-nebulous statements.
'; } // Display redundancies const redundanciesList = document.getElementById('redundancies-list'); if (analysis.redundancies && analysis.redundancies.length > 0) { redundanciesList.innerHTML = analysis.redundancies.map((group, index) => `Redundancy Group ${index + 1}
• ${escapeHtml(rule)}
`).join('')}Suggested Merge:
${escapeHtml(group.mergeSuggestion)}
No redundancies detected.
'; } } /** * Toggle candidate selection */ function toggleCandidate(candidate, checked) { if (checked) { selectedCandidates.push(candidate); } else { selectedCandidates = selectedCandidates.filter(c => c.originalText !== candidate.originalText); } // Update button text document.getElementById('create-rules-btn').textContent = `Create Selected Rules (${selectedCandidates.length})`; } /** * Create selected rules */ async function createSelectedRules() { if (selectedCandidates.length === 0) { showToast('Please select at least one rule to create', 'error'); return; } const createBtn = document.getElementById('create-rules-btn'); createBtn.disabled = true; createBtn.textContent = 'Creating...'; try { const response = await apiRequest('/api/admin/rules/migrate-from-claude-md', { method: 'POST', body: JSON.stringify({ selectedCandidates }) }); if (!response.success) { throw new Error(response.message || 'Migration failed'); } displayMigrationResults(response.results); goToStep(3); } catch (error) { console.error('Migration error:', error); showToast(error.message || 'Failed to create rules', 'error'); createBtn.disabled = false; createBtn.textContent = `Create Selected Rules (${selectedCandidates.length})`; } } /** * Display migration results */ function displayMigrationResults(results) { const summaryDiv = document.getElementById('results-summary'); summaryDiv.innerHTML = `Created Rules:
${escapeHtml(rule.text.substring(0, 80))}${rule.text.length > 80 ? '...' : ''}
Failed Rules:
${escapeHtml(fail.candidate.substring(0, 60))}...
Error: ${escapeHtml(fail.error)}