All-in-One Migration Tool :root { –bg: #f0f0f1; –card-bg: #ffffff; –primary: #2271b1; –primary-hover: #135e96; –success: #00a32a; –danger: #d63638; –warning: #dba617; –text: #1d2327; –text-light: #646970; –border: #c3c4c7; –shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06); –shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08); –radius: 8px; –radius-sm: 5px; –transition: 0.2s ease; –font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, sans-serif; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: var(–font); background: var(–bg); color: var(–text); min-height: 100vh; display: flex; justify-content: center; padding: 30px 20px; } .container { width: 100%; max-width: 780px; display: flex; flex-direction: column; gap: 24px; } /* Header */ .header { display: flex; align-items: center; gap: 14px; padding: 0 4px; } .header .logo { width: 44px; height: 44px; background: linear-gradient(135deg, #2271b1, #1a5a8b); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 20px; font-weight: 700; flex-shrink: 0; box-shadow: 0 4px 12px rgba(34, 113, 177, 0.3); } .header h1 { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.3px; color: #1d2327; } .header .badge { background: #e9f5ff; color: #2271b1; font-size: 0.7rem; font-weight: 600; padding: 4px 10px; border-radius: 20px; letter-spacing: 0.3px; text-transform: uppercase; } /* Cards */ .card { background: var(–card-bg); border-radius: var(–radius); box-shadow: var(–shadow); border: 1px solid #e5e7eb; overflow: hidden; transition: var(–transition); } .card-header { padding: 18px 22px; border-bottom: 1px solid #f0f0f1; display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 0.95rem; } .card-header .icon { width: 34px; height: 34px; border-radius: 7px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; } .icon-export { background: #f0f6fc; color: #2271b1; } .icon-import { background: #f0faf3; color: #00a32a; } .icon-backups { background: #fef8ee; color: #dba617; } .icon-settings { background: #f4f4f5; color: #646970; } .card-body { padding: 22px; } /* Buttons */ .btn { display: inline-flex; align-items: center; gap: 7px; padding: 11px 20px; border: none; border-radius: var(–radius-sm); font-size: 0.9rem; font-weight: 600; cursor: pointer; transition: all var(–transition); font-family: var(–font); letter-spacing: 0.1px; text-decoration: none; white-space: nowrap; } .btn-primary { background: var(–primary); color: #fff; } .btn-primary:hover { background: var(–primary-hover); box-shadow: 0 4px 14px rgba(34, 113, 177, 0.35); transform: translateY(-1px); } .btn-success { background: var(–success); color: #fff; } .btn-success:hover { background: #008a20; box-shadow: 0 4px 14px rgba(0, 163, 42, 0.35); transform: translateY(-1px); } .btn-outline { background: #fff; color: var(–text); border: 2px solid #dcdcde; } .btn-outline:hover { border-color: var(–primary); color: var(–primary); background: #f9fafe; } .btn-danger-outline { background: #fff; color: var(–danger); border: 2px solid #f5c6cb; } .btn-danger-outline:hover { background: #fef2f2; border-color: var(–danger); } .btn-sm { padding: 7px 14px; font-size: 0.8rem; border-radius: 4px; } .btn:disabled { opacity: 0.55; pointer-events: none; cursor: not-allowed; } .btn .spinner { width: 16px; height: 16px; border: 2px solid transparent; border-top-color: currentColor; border-radius: 50%; animation: spin 0.7s linear infinite; display: none; } .btn.loading .spinner { display: inline-block; } .btn.loading .btn-text { opacity: 0.7; } @keyframes spin { to { transform: rotate(360deg); } } /* Drop zone */ .drop-zone { border: 2.5px dashed #c3c4c7; border-radius: var(–radius); padding: 40px 30px; text-align: center; cursor: pointer; transition: all var(–transition); background: #fafafa; position: relative; } .drop-zone:hover, .drop-zone.drag-over { border-color: var(–primary); background: #f5f9fd; box-shadow: inset 0 0 0 4px rgba(34, 113, 177, 0.04); } .drop-zone.drag-over { background: #eef5fb; border-color: #2271b1; } .drop-zone .dz-icon { font-size: 48px; margin-bottom: 10px; display: block; opacity: 0.7; } .drop-zone p { color: var(–text-light); font-size: 0.9rem; margin: 4px 0; } .drop-zone .dz-supported { font-size: 0.75rem; color: #a7aaad; margin-top: 8px; } .drop-zone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; } /* Progress */ .progress-section { display: none; margin-top: 16px; } .progress-section.active { display: block; } .progress-bar-outer { background: #e5e7eb; border-radius: 20px; height: 12px; overflow: hidden; margin: 8px 0; } .progress-bar-inner { height: 100%; background: linear-gradient(90deg, #2271b1, #3b8fd4); border-radius: 20px; width: 0%; transition: width 0.3s ease; position: relative; } .progress-bar-inner.striped { background: linear-gradient(90deg, #2271b1 0%, #3b8fd4 25%, #2271b1 50%, #3b8fd4 75%, #2271b1 100%); background-size: 40px 100%; animation: stripe-move 0.8s linear infinite; } @keyframes stripe-move { to { background-position: 40px 0; } } .progress-text { font-size: 0.85rem; color: var(–text-light); display: flex; justify-content: space-between; } .progress-percentage { font-weight: 700; color: var(–primary); } /* File info */ .file-info { display: none; background: #f9fafb; border-radius: var(–radius-sm); padding: 14px 18px; margin-top: 12px; align-items: center; gap: 12px; border: 1px solid #e5e7eb; } .file-info.active { display: flex; } .file-info .fi-icon { font-size: 28px; flex-shrink: 0; } .file-info .fi-details { flex: 1; min-width: 0; } .file-info .fi-name { font-weight: 600; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .file-info .fi-size { font-size: 0.78rem; color: var(–text-light); } .file-info .fi-remove { cursor: pointer; color: #a7aaad; font-size: 20px; padding: 4px 8px; border-radius: 4px; transition: var(–transition); background: none; border: none; line-height: 1; } .file-info .fi-remove:hover { color: var(–danger); background: #fef2f2; } /* Backup list */ .backup-list { list-style: none; } .backup-item { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid #f0f0f1; transition: var(–transition); border-radius: 6px; } .backup-item:last-child { border-bottom: none; } .backup-item:hover { background: #fafafa; } .backup-item .bi-icon { font-size: 24px; flex-shrink: 0; } .backup-item .bi-info { flex: 1; min-width: 0; } .backup-item .bi-name { font-weight: 600; font-size: 0.88rem; } .backup-item .bi-meta { font-size: 0.75rem; color: var(–text-light); } .backup-item .bi-actions { display: flex; gap: 6px; flex-shrink: 0; } .empty-state { text-align: center; padding: 30px; color: var(–text-light); } .empty-state .empty-icon { font-size: 40px; display: block; margin-bottom: 8px; opacity: 0.5; } /* Toast */ .toast-container { position: fixed; top: 20px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 10px; pointer-events: none; } .toast { background: #1d2327; color: #fff; padding: 13px 20px; border-radius: 8px; font-size: 0.88rem; font-weight: 500; box-shadow: var(–shadow-lg); animation: slideIn 0.35s ease, fadeOut 0.35s ease 2.8s forwards; pointer-events: auto; max-width: 420px; display: flex; align-items: center; gap: 10px; } .toast.success { border-left: 4px solid #00a32a; } .toast.error { border-left: 4px solid #d63638; } .toast.info { border-left: 4px solid #2271b1; } @keyframes slideIn { from { transform: translateX(120%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes fadeOut { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(80%); } } /* Advanced options */ .advanced-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; font-weight: 600; font-size: 0.85rem; color: var(–primary); padding: 8px 0; user-select: none; } .advanced-toggle:hover { color: var(–primary-hover); } .advanced-toggle .arrow { transition: transform 0.25s ease; font-size: 0.7rem; } .advanced-toggle.open .arrow { transform: rotate(90deg); } .advanced-options { display: none; padding: 14px 0 0 0; border-top: 1px solid #f0f0f1; margin-top: 10px; } .advanced-options.open { display: block; } .checkbox-group { display: flex; flex-direction: column; gap: 10px; } .checkbox-group label { display: flex; align-items: center; gap: 10px; font-size: 0.88rem; cursor: pointer; padding: 6px 0; } .checkbox-group input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(–primary); cursor: pointer; flex-shrink: 0; } /* Responsive */ @media (max-width: 600px) { .card-body { padding: 16px; } .drop-zone { padding: 28px 16px; } .btn { padding: 10px 16px; font-size: 0.82rem; } .backup-item { flex-wrap: wrap; } .backup-item .bi-actions { width: 100%; justify-content: flex-end; margin-top: 4px; } }

All-in-One Migration

v4.7
📤 Export Site

Create a complete backup of your site. Download the file to your computer.

Advanced Options
Preparing export… 0%
📥 Import Site

Restore a backup by uploading a .wpress or .zip file.

📂

Drag & drop your backup file here

or click to browse

Supported: .wpress, .zip (Max: 512 MB)

📄
Uploading & extracting… 0%

⚠️ Warning: Importing will overwrite your current site data. Ensure you have a recent backup.

💾 Saved Backups
📭

No backups found on this device.

Exported files saved to this browser will appear here.

(function() { // ────────────────────────────────────── // State // ────────────────────────────────────── let selectedFile = null; let isExporting = false; let isImporting = false; const MAX_FILE_SIZE = 512 * 1024 * 1024; // 512 MB const STORAGE_KEY = 'aio_migration_backups'; // ────────────────────────────────────── // DOM Elements // ────────────────────────────────────── const dropZone = document.getElementById('dropZone'); const fileInput = document.getElementById('fileInput'); const fileInfo = document.getElementById('fileInfo'); const fileName = document.getElementById('fileName'); const fileSize = document.getElementById('fileSize'); const importBtn = document.getElementById('importBtn'); const clearBtn = document.getElementById('clearBtn'); const exportBtn = document.getElementById('exportBtn'); const exportProgress = document.getElementById('exportProgress'); const exportBar = document.getElementById('exportBar'); const exportStatus = document.getElementById('exportStatus'); const exportPercent = document.getElementById('exportPercent'); const importProgress = document.getElementById('importProgress'); const importBar = document.getElementById('importBar'); const importStatus = document.getElementById('importStatus'); const importPercent = document.getElementById('importPercent'); const importWarning = document.getElementById('importWarning'); const backupList = document.getElementById('backupList'); const emptyBackups = document.getElementById(’emptyBackups'); const toastContainer = document.getElementById('toastContainer'); // ────────────────────────────────────── // Toast System // ────────────────────────────────────── function showToast(message, type = 'info') { const toast = document.createElement('div'); toast.className = `toast ${type}`; const icons = { success: '✅', error: '❌', info: 'ℹ️' }; toast.innerHTML = `${icons[type] || 'ℹ️'} ${message}`; toastContainer.appendChild(toast); setTimeout(() => { if (toast.parentNode) toast.remove(); }, 3200); } // ────────────────────────────────────── // Formatting // ────────────────────────────────────── function formatBytes(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } function formatDate(date) { const d = new Date(date); return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } // ────────────────────────────────────── // File Handling // ────────────────────────────────────── function handleFileSelect(event) { const file = event.target.files[0]; if (file) processFile(file); } function processFile(file) { const validExtensions = ['.wpress', '.zip']; const ext = '.' + file.name.split('.').pop().toLowerCase(); if (!validExtensions.includes(ext)) { showToast('Invalid file type. Please upload a .wpress or .zip file.', 'error'); fileInput.value = "; return; } if (file.size > MAX_FILE_SIZE) { showToast('File is too large. Maximum size is 512 MB.', 'error'); fileInput.value = "; return; } selectedFile = file; fileName.textContent = file.name; fileSize.textContent = formatBytes(file.size); fileInfo.classList.add('active'); importBtn.disabled = false; clearBtn.disabled = false; importWarning.style.display = 'block'; showToast(`File selected: ${file.name}`, 'info'); } function clearFile() { selectedFile = null; fileInput.value = "; fileInfo.classList.remove('active'); importBtn.disabled = true; clearBtn.disabled = true; fileName.textContent = '—'; fileSize.textContent = '—'; importProgress.classList.remove('active'); importBar.style.width = '0%'; importPercent.textContent = '0%'; importStatus.textContent = 'Uploading & extracting…'; importWarning.style.display = 'block'; } // ────────────────────────────────────── // Drag & Drop // ────────────────────────────────────── dropZone.addEventListener('dragover', (e) => { e.preventDefault(); e.stopPropagation(); dropZone.classList.add('drag-over'); }); dropZone.addEventListener('dragleave', (e) => { e.preventDefault(); e.stopPropagation(); dropZone.classList.remove('drag-over'); }); dropZone.addEventListener('drop', (e) => { e.preventDefault(); e.stopPropagation(); dropZone.classList.remove('drag-over'); const file = e.dataTransfer.files[0]; if (file) { fileInput.files = e.dataTransfer.files; processFile(file); } }); dropZone.addEventListener('click', () => { fileInput.click(); }); // ────────────────────────────────────── // Export Simulation // ────────────────────────────────────── function startExport() { if (isExporting) return; isExporting = true; exportBtn.classList.add('loading'); exportBtn.disabled = true; exportProgress.classList.add('active'); exportBar.style.width = '0%'; exportBar.classList.add('striped'); exportPercent.textContent = '0%'; exportStatus.textContent = 'Preparing export…'; let progress = 0; const steps = [ { pct: 15, msg: 'Compressing database tables…', delay: 600 }, { pct: 30, msg: 'Packaging media files…', delay: 800 }, { pct: 50, msg: 'Bundling themes…', delay: 700 }, { pct: 65, msg: 'Bundling plugins…', delay: 700 }, { pct: 80, msg: 'Creating archive…', delay: 900 }, { pct: 92, msg: 'Finalizing…', delay: 600 }, { pct: 100, msg: 'Export complete!', delay: 500 }, ]; let currentStep = 0; function runStep() { if (currentStep >= steps.length) { // Done exportBar.classList.remove('striped'); exportBar.style.width = '100%'; exportPercent.textContent = '100%'; exportStatus.textContent = '✅ Export complete!'; exportBtn.classList.remove('loading'); exportBtn.disabled = false; isExporting = false; // Save to localStorage as a simulated backup const backupData = { id: Date.now(), name: `backup-${new Date().toISOString().slice(0,10)}-${Math.random().toString(36).slice(2,8)}.wpress`, size: Math.floor(Math.random() * 200 * 1024 * 1024) + 10 * 1024 * 1024, date: new Date().toISOString(), }; saveBackup(backupData); renderBackups(); showToast('Export completed successfully! File saved to backups.', 'success'); // Simulate download simulateDownload(backupData.name, backupData.size); // Reset after a moment setTimeout(() => { exportProgress.classList.remove('active'); exportBar.style.width = '0%'; exportBar.classList.add('striped'); exportPercent.textContent = '0%'; }, 2000); return; } const step = steps[currentStep]; progress = step.pct; exportBar.style.width = progress + '%'; exportPercent.textContent = progress + '%'; exportStatus.textContent = step.msg; currentStep++; setTimeout(runStep, step.delay); } runStep(); } function simulateDownload(filename, size) { // Create a blob and trigger download const content = `SIMULATED BACKUP FILE\nName: ${filename}\nSize: ${formatBytes(size)}\nDate: ${new Date().toISOString()}\nThis is a simulated migration backup for demonstration purposes.\n`; const blob = new Blob([content], { type: 'application/octet-stream' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // ────────────────────────────────────── // Import Simulation // ────────────────────────────────────── function startImport() { if (isImporting || !selectedFile) return; if (!confirm( '⚠️ Are you sure you want to import this backup?\n\nThis will overwrite all current site data. This action cannot be undone.' )) return; isImporting = true; importBtn.classList.add('loading'); importBtn.disabled = true; clearBtn.disabled = true; importProgress.classList.add('active'); importBar.style.width = '0%'; importBar.classList.add('striped'); importPercent.textContent = '0%'; importStatus.textContent = 'Uploading file…'; importWarning.style.display = 'none'; dropZone.style.pointerEvents = 'none'; dropZone.style.opacity = '0.5'; let progress = 0; const steps = [ { pct: 20, msg: 'Uploading & verifying…', delay: 700 }, { pct: 35, msg: 'Extracting archive…', delay: 1000 }, { pct: 50, msg: 'Importing database…', delay: 900 }, { pct: 65, msg: 'Restoring media files…', delay: 800 }, { pct: 78, msg: 'Restoring themes…', delay: 700 }, { pct: 88, msg: 'Restoring plugins…', delay: 700 }, { pct: 95, msg: 'Cleaning up…', delay: 600 }, { pct: 100, msg: 'Import complete!', delay: 500 }, ]; let currentStep = 0; function runStep() { if (currentStep >= steps.length) { importBar.classList.remove('striped'); importBar.style.width = '100%'; importPercent.textContent = '100%'; importStatus.textContent = '✅ Import complete! Reloading…'; importBtn.classList.remove('loading'); isImporting = false; dropZone.style.pointerEvents = 'auto'; dropZone.style.opacity = '1'; showToast('Import successful! Site restored from backup.', 'success'); clearFile(); setTimeout(() => { importProgress.classList.remove('active'); importBar.style.width = '0%'; importBar.classList.add('striped'); importPercent.textContent = '0%'; importWarning.style.display = 'block'; }, 2500); return; } const step = steps[currentStep]; progress = step.pct; importBar.style.width = progress + '%'; importPercent.textContent = progress + '%'; importStatus.textContent = step.msg; currentStep++; setTimeout(runStep, step.delay); } runStep(); } // ────────────────────────────────────── // Backups (localStorage) // ────────────────────────────────────── function getBackups() { try { const data = localStorage.getItem(STORAGE_KEY); return data ? JSON.parse(data) : []; } catch (e) { return []; } } function saveBackup(backup) { const backups = getBackups(); backups.unshift(backup); // Keep max 10 backups const trimmed = backups.slice(0, 10); localStorage.setItem(STORAGE_KEY, JSON.stringify(trimmed)); } function deleteBackup(id) { let backups = getBackups(); backups = backups.filter(b => b.id !== id); localStorage.setItem(STORAGE_KEY, JSON.stringify(backups)); renderBackups(); showToast('Backup deleted.', 'info'); } function downloadBackup(backup) { simulateDownload(backup.name, backup.size); showToast(`Downloading ${backup.name}…`, 'success'); } function renderBackups() { const backups = getBackups(); backupList.innerHTML = "; if (backups.length === 0) { emptyBackups.style.display = 'block'; backupList.style.display = 'none'; } else { emptyBackups.style.display = 'none'; backupList.style.display = 'block'; backups.forEach(backup => { const li = document.createElement('li'); li.className = 'backup-item'; li.innerHTML = ` 📦
${escapeHTML(backup.name)}
${formatBytes(backup.size)} • ${formatDate(backup.date)}
`; backupList.appendChild(li); }); } } function escapeHTML(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } // Expose functions for inline onclick window._deleteBackupById = function(id) { if (confirm('Delete this backup? This cannot be undone.')) { deleteBackup(id); } }; window._downloadBackupById = function(id) { const backups = getBackups(); const backup = backups.find(b => b.id === id); if (backup) downloadBackup(backup); }; // ────────────────────────────────────── // Advanced Options Toggle // ────────────────────────────────────── window.toggleAdvanced = function(id) { const panel = document.getElementById(id); const toggle = document.getElementById(id === 'exportAdvanced' ? 'exportAdvancedToggle' : null); if (!panel) return; panel.classList.toggle('open'); // Find the toggle element const allToggles = document.querySelectorAll('.advanced-toggle'); allToggles.forEach(t => { const targetId = t.getAttribute('onclick')?.match(/'([^']+)'/)?.[1]; if (targetId === id) { t.classList.toggle('open', panel.classList.contains('open')); } }); }; // Also handle toggle click more robustly document.querySelectorAll('.advanced-toggle').forEach(toggle => { toggle.addEventListener('click', function(e) { const match = this.getAttribute('onclick')?.match(/'([^']+)'/); if (match) { const id = match[1]; const panel = document.getElementById(id); if (panel) { this.classList.toggle('open', panel.classList.contains('open')); } } }); }); // ────────────────────────────────────── // Init // ────────────────────────────────────── renderBackups(); // Keyboard shortcut: Ctrl+E for export document.addEventListener('keydown', (e) => { if ((e.ctrlKey || e.metaKey) && e.key === 'e') { e.preventDefault(); if (!isExporting) startExport(); } if ((e.ctrlKey || e.metaKey) && e.key === 'i') { e.preventDefault(); if (selectedFile && !isImporting) startImport(); } }); console.log('🚀 All-in-One Migration Tool Ready'); console.log(' Ctrl+E → Quick Export'); console.log(' Ctrl+I → Quick Import (if file selected)'); console.log(' Drop .wpress or .zip files onto the import zone'); console.log(' Exports are saved to localStorage and auto-downloaded'); })();