UNPKG

gmail-to-exchange365

Version:

Complete Gmail to Exchange 365 migration tool with UI - Migrate emails, attachments, and folders seamlessly

263 lines (226 loc) 8.23 kB
// State management let migrationState = { googleConnected: false, msConnected: false, isRunning: false, isPaused: false }; // DOM elements const googleBtn = document.getElementById("google-btn"); const msBtn = document.getElementById("ms-btn"); const googleStatus = document.getElementById("google-status"); const msStatus = document.getElementById("ms-status"); const googleIndicator = document.getElementById("google-indicator"); const msIndicator = document.getElementById("ms-indicator"); const startBtn = document.getElementById("start-btn"); const pauseBtn = document.getElementById("pause-btn"); const resumeBtn = document.getElementById("resume-btn"); const stopBtn = document.getElementById("stop-btn"); const progressFill = document.getElementById("progress-fill"); const progressPercentage = document.getElementById("progress-percentage"); const progressCount = document.getElementById("progress-count"); const progressMessage = document.getElementById("progress-message"); const logsContainer = document.getElementById("logs"); const batchSizeInput = document.getElementById("batch-size"); const delayInput = document.getElementById("delay"); let eventSource = null; // Initialize document.addEventListener("DOMContentLoaded", () => { checkAuthStatus(); setupEventListeners(); checkUrlParams(); }); function checkUrlParams() { const params = new URLSearchParams(window.location.search); if (params.get("google") === "connected") { addLog("✅ Google account connected successfully", "success"); checkAuthStatus(); } if (params.get("ms") === "connected") { addLog("✅ Microsoft account connected successfully", "success"); checkAuthStatus(); } if (params.get("error")) { addLog(`❌ Error: ${params.get("error")}`, "error"); } } async function checkAuthStatus() { try { const response = await fetch("/api/status"); const data = await response.json(); migrationState.googleConnected = data.google; migrationState.msConnected = data.ms; updateUI(); } catch (error) { console.error("Error checking auth status:", error); } } function updateUI() { // Update Google status if (migrationState.googleConnected) { googleStatus.textContent = "Google Connected"; googleIndicator.className = "status-indicator connected"; googleBtn.classList.add("connected"); } else { googleStatus.textContent = "Connect Google"; googleIndicator.className = "status-indicator"; googleBtn.classList.remove("connected"); } // Update Microsoft status if (migrationState.msConnected) { msStatus.textContent = "Microsoft Connected"; msIndicator.className = "status-indicator connected"; msBtn.classList.add("connected"); } else { msStatus.textContent = "Connect Microsoft"; msIndicator.className = "status-indicator"; msBtn.classList.remove("connected"); } // Update start button startBtn.disabled = !(migrationState.googleConnected && migrationState.msConnected) || migrationState.isRunning; // Update control buttons pauseBtn.disabled = !migrationState.isRunning || migrationState.isPaused; resumeBtn.disabled = !migrationState.isRunning || !migrationState.isPaused; stopBtn.disabled = !migrationState.isRunning; } function setupEventListeners() { googleBtn.addEventListener("click", () => { window.location.href = "/google/auth"; }); msBtn.addEventListener("click", () => { window.location.href = "/ms/auth"; }); startBtn.addEventListener("click", startMigration); pauseBtn.addEventListener("click", pauseMigration); resumeBtn.addEventListener("click", resumeMigration); stopBtn.addEventListener("click", stopMigration); } async function startMigration() { if (!migrationState.googleConnected || !migrationState.msConnected) { addLog("❌ Please connect both Google and Microsoft accounts first", "error"); return; } migrationState.isRunning = true; migrationState.isPaused = false; updateUI(); const batchSize = parseInt(batchSizeInput.value) || 10; const delay = parseInt(delayInput.value) || 1000; addLog("🚀 Starting migration...", "info"); addLog(`📊 Configuration: Batch size=${batchSize}, Delay=${delay}ms`, "info"); try { const response = await fetch("/api/migrate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ batchSize, delayBetweenBatches: delay, retryAttempts: 3, retryDelay: 5000 }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (true) { const { value, done } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() || ""; for (const line of lines) { if (line.startsWith("data: ")) { try { const data = JSON.parse(line.substring(6)); handleProgressUpdate(data); } catch (e) { console.error("Error parsing progress data:", e); } } } } if (buffer.startsWith("data: ")) { try { const data = JSON.parse(buffer.substring(6)); handleProgressUpdate(data); } catch (e) { console.error("Error parsing final progress data:", e); } } } catch (error) { addLog(`❌ Migration error: ${error.message}`, "error"); migrationState.isRunning = false; updateUI(); } } function handleProgressUpdate(data) { if (data.error) { addLog(`❌ Error: ${data.error}`, "error"); migrationState.isRunning = false; updateUI(); return; } if (data.completed) { addLog("✅ Migration completed successfully!", "success"); migrationState.isRunning = false; updateUI(); return; } if (data.current !== undefined && data.total !== undefined) { const percentage = data.total > 0 ? Math.round((data.current / data.total) * 100) : 0; progressFill.style.width = `${percentage}%`; progressPercentage.textContent = `${percentage}%`; progressCount.textContent = `${data.current} / ${data.total}`; if (data.message) { progressMessage.textContent = data.message; if (data.current % 10 === 0 || data.current === data.total) { addLog(data.message, "info"); } } } } async function pauseMigration() { try { const response = await fetch("/api/migrate/pause", { method: "POST" }); const data = await response.json(); addLog("⏸️ Migration paused", "info"); migrationState.isPaused = true; updateUI(); } catch (error) { addLog(`❌ Error pausing migration: ${error.message}`, "error"); } } async function resumeMigration() { try { const response = await fetch("/api/migrate/resume", { method: "POST" }); const data = await response.json(); addLog("▶️ Migration resumed", "info"); migrationState.isPaused = false; updateUI(); } catch (error) { addLog(`❌ Error resuming migration: ${error.message}`, "error"); } } async function stopMigration() { try { const response = await fetch("/api/migrate/stop", { method: "POST" }); const data = await response.json(); addLog("⏹️ Migration stopped", "warning"); migrationState.isRunning = false; migrationState.isPaused = false; updateUI(); } catch (error) { addLog(`❌ Error stopping migration: ${error.message}`, "error"); } } function addLog(message, type = "info") { const logEntry = document.createElement("div"); logEntry.className = `log-entry log-${type}`; logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; logsContainer.appendChild(logEntry); logsContainer.scrollTop = logsContainer.scrollHeight; }