// Product URLs comparison functionality let currentPage = 0; let currentM1Page = 0; let currentM2Page = 0; const pageSize = 100; let currentComparisonData = []; let currentM1Data = []; let currentM2Data = []; let currentFilter = 'all'; // Compare URLs between M1 and M2 window.compareUrls = async function compareUrls() { const sku = document.getElementById('skuFilter').value.trim(); const btn = document.getElementById('compareUrlsBtn'); btn.disabled = true; btn.textContent = 'Comparing...'; try { const response = await fetch(window.productUrlsRoutes.compareUrls + '?sku=' + encodeURIComponent(sku) + '&limit=' + pageSize + '&offset=' + (currentPage * pageSize), { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content } }); const data = await response.json(); if (data.success) { currentComparisonData = data.comparison; displayComparison(data); updateSummary(data.summary); document.getElementById('comparisonSection').style.display = 'block'; document.getElementById('summarySection').style.display = 'block'; } else { alert('Error: ' + data.message); } } catch (error) { console.error('Error comparing URLs:', error); alert('Failed to compare URLs: ' + error.message); } finally { btn.disabled = false; btn.textContent = 'Compare URLs'; } } // Display comparison results function displayComparison(data) { const tbody = document.getElementById('comparisonTableBody'); tbody.innerHTML = ''; if (data.comparison.length === 0) { tbody.innerHTML = 'No results found'; return; } data.comparison.forEach(item => { const row = document.createElement('tr'); const statusClass = getStatusClass(item.status); const statusLabel = getStatusLabel(item.status); row.innerHTML = ` ${escapeHtml(item.sku || 'N/A')} ${item.m1_product_id || '-'} ${item.m2_product_id || '-'} ${item.store_id || '-'} ${escapeHtml(item.m1_url || '-')} ${escapeHtml(item.m2_url || '-')} ${statusLabel} `; tbody.appendChild(row); }); // Update pagination updatePagination(data.total, currentPage); document.getElementById('resultsCount').textContent = `Showing ${data.comparison.length} of ${data.total} results`; } // Update summary statistics function updateSummary(summary) { document.getElementById('summaryMatch').textContent = summary.match || 0; document.getElementById('summaryMissingM2').textContent = summary.missing_in_m2 || 0; document.getElementById('summaryMissingM1').textContent = summary.missing_in_m1 || 0; document.getElementById('summaryDifferent').textContent = summary.different || 0; } // Get status class for styling function getStatusClass(status) { switch(status) { case 'match': return 'status-match'; case 'missing_in_m2': return 'status-warning'; case 'missing_in_m1': return 'status-info'; case 'different': return 'status-error'; default: return ''; } } // Get status label function getStatusLabel(status) { switch(status) { case 'match': return 'Match'; case 'missing_in_m2': return 'Missing in M2'; case 'missing_in_m1': return 'Missing in M1'; case 'different': return 'Different'; default: return status; } } // Filter results by status window.filterResults = function filterResults() { const filter = document.getElementById('statusFilter').value; currentFilter = filter; // Re-fetch with filter (or filter client-side) // For now, we'll filter client-side if we have all data // In a real implementation, you might want to pass filter to the server compareUrls(); } // Load Magento 1 URLs window.loadM1Urls = async function loadM1Urls() { const sku = document.getElementById('skuFilter').value.trim(); const btn = document.getElementById('loadM1UrlsBtn'); btn.disabled = true; btn.textContent = 'Loading...'; try { const response = await fetch(window.productUrlsRoutes.getM1Urls + '?sku=' + encodeURIComponent(sku) + '&limit=' + pageSize + '&offset=' + (currentM1Page * pageSize), { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content } }); const data = await response.json(); if (data.success) { currentM1Data = data; displayM1Urls(data); document.getElementById('m1UrlsSection').style.display = 'block'; } else { alert('Error: ' + data.message); } } catch (error) { console.error('Error loading M1 URLs:', error); alert('Failed to load M1 URLs: ' + error.message); } finally { btn.disabled = false; btn.textContent = 'Load M1 URLs'; } } // Display M1 URLs function displayM1Urls(data) { const tbody = document.getElementById('m1UrlsTableBody'); tbody.innerHTML = ''; if (data.urls.length === 0) { tbody.innerHTML = 'No URLs found'; return; } data.urls.forEach(item => { const row = document.createElement('tr'); row.innerHTML = ` ${item.entity_id || '-'} ${escapeHtml(item.sku || 'N/A')} ${item.store_id || '-'} ${escapeHtml(item.request_path || '-')} ${escapeHtml(item.target_path || '-')} `; tbody.appendChild(row); }); updateM1Pagination(data.total, currentM1Page); } // Load Magento 2 URLs window.loadM2Urls = async function loadM2Urls() { const sku = document.getElementById('skuFilter').value.trim(); const btn = document.getElementById('loadM2UrlsBtn'); btn.disabled = true; btn.textContent = 'Loading...'; try { const response = await fetch(window.productUrlsRoutes.getM2Urls + '?sku=' + encodeURIComponent(sku) + '&limit=' + pageSize + '&offset=' + (currentM2Page * pageSize), { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content } }); const data = await response.json(); if (data.success) { currentM2Data = data; displayM2Urls(data); document.getElementById('m2UrlsSection').style.display = 'block'; } else { alert('Error: ' + data.message); } } catch (error) { console.error('Error loading M2 URLs:', error); alert('Failed to load M2 URLs: ' + error.message); } finally { btn.disabled = false; btn.textContent = 'Load M2 URLs'; } } // Display M2 URLs function displayM2Urls(data) { const tbody = document.getElementById('m2UrlsTableBody'); tbody.innerHTML = ''; if (data.urls.length === 0) { tbody.innerHTML = 'No URLs found'; return; } data.urls.forEach(item => { const row = document.createElement('tr'); row.innerHTML = ` ${item.entity_id || '-'} ${escapeHtml(item.sku || 'N/A')} ${item.store_id || '-'} ${escapeHtml(item.request_path || '-')} ${escapeHtml(item.target_path || '-')} `; tbody.appendChild(row); }); updateM2Pagination(data.total, currentM2Page); } // Pagination functions window.changePage = function changePage(direction) { currentPage += direction; if (currentPage < 0) currentPage = 0; compareUrls(); } window.changeM1Page = function changeM1Page(direction) { currentM1Page += direction; if (currentM1Page < 0) currentM1Page = 0; loadM1Urls(); } window.changeM2Page = function changeM2Page(direction) { currentM2Page += direction; if (currentM2Page < 0) currentM2Page = 0; loadM2Urls(); } function updatePagination(total, currentPage) { const totalPages = Math.ceil(total / pageSize); const pageInfo = document.getElementById('pageInfo'); const prevBtn = document.getElementById('prevPageBtn'); const nextBtn = document.getElementById('nextPageBtn'); pageInfo.textContent = `Page ${currentPage + 1} of ${totalPages}`; prevBtn.disabled = currentPage === 0; nextBtn.disabled = currentPage >= totalPages - 1; } function updateM1Pagination(total, currentPage) { const totalPages = Math.ceil(total / pageSize); const pageInfo = document.getElementById('m1PageInfo'); const prevBtn = document.getElementById('m1PrevPageBtn'); const nextBtn = document.getElementById('m1NextPageBtn'); pageInfo.textContent = `Page ${currentPage + 1} of ${totalPages}`; prevBtn.disabled = currentPage === 0; nextBtn.disabled = currentPage >= totalPages - 1; } function updateM2Pagination(total, currentPage) { const totalPages = Math.ceil(total / pageSize); const pageInfo = document.getElementById('m2PageInfo'); const prevBtn = document.getElementById('m2PrevPageBtn'); const nextBtn = document.getElementById('m2NextPageBtn'); pageInfo.textContent = `Page ${currentPage + 1} of ${totalPages}`; prevBtn.disabled = currentPage === 0; nextBtn.disabled = currentPage >= totalPages - 1; } // Utility function to escape HTML function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // Compare single product SKU window.compareSingleSku = async function compareSingleSku() { const sku = document.getElementById('singleSkuInput').value.trim(); const btn = document.getElementById('compareSingleSkuBtn'); const section = document.getElementById('singleProductComparisonSection'); const content = document.getElementById('singleProductComparisonContent'); if (!sku) { alert('Please enter a product SKU'); return; } btn.disabled = true; btn.textContent = 'Comparing...'; content.innerHTML = '
Loading...
'; section.style.display = 'block'; document.getElementById('singleSkuDisplay').textContent = sku; try { const response = await fetch(window.productUrlsRoutes.compareSingleSku + '?sku=' + encodeURIComponent(sku), { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content } }); const data = await response.json(); if (data.success) { displaySingleProductComparison(data); } else { content.innerHTML = '
Error: ' + escapeHtml(data.message) + '
'; } } catch (error) { console.error('Error comparing single SKU:', error); content.innerHTML = '
Failed to compare URLs: ' + escapeHtml(error.message) + '
'; } finally { btn.disabled = false; btn.textContent = 'Compare Product URLs'; } } // Display single product comparison results function displaySingleProductComparison(data) { const content = document.getElementById('singleProductComparisonContent'); if (!data.comparison || data.comparison.length === 0) { content.innerHTML = '
No URLs found for this product SKU.
'; return; } let html = '
'; html += '
'; html += '
'; html += '
' + (data.summary.match || 0) + '
'; html += '
Matching Stores
'; html += '
'; html += '
' + (data.summary.missing_in_m2 || 0) + '
'; html += '
Missing in M2
'; html += '
'; html += '
' + (data.summary.missing_in_m1 || 0) + '
'; html += '
Missing in M1
'; html += '
'; html += '
' + (data.summary.different || 0) + '
'; html += '
Different URLs
'; html += '
'; html += '
'; html += '
Product IDs: M1: ' + (data.m1_product_id || 'N/A') + ' | M2: ' + (data.m2_product_id || 'N/A') + '
'; html += '
Total URLs: M1: ' + (data.summary.total_m1_urls || 0) + ' | M2: ' + (data.summary.total_m2_urls || 0) + ' | Stores: ' + (data.summary.total_stores || 0) + '
'; html += '
'; html += '
'; // Group by store data.comparison.forEach(storeData => { const statusClass = getStatusClass(storeData.status); const statusLabel = getStatusLabel(storeData.status); const storeId = storeData.store_id || 'Default'; html += '
'; html += '
'; html += '
Store ID: ' + storeId + '
'; html += '
' + statusLabel + '
'; html += '
'; html += '
'; html += '
'; // Magento 1 URLs html += '
'; html += '

Magento 1 URLs (' + (storeData.m1_urls.length || 0) + ')

'; if (storeData.m1_urls.length > 0) { html += '
'; storeData.m1_urls.forEach((urlData, index) => { html += '
'; html += '
URL ' + (index + 1) + ':
'; html += '
' + escapeHtml(urlData.url || '-') + '
'; if (urlData.target_path) { html += '
Target: ' + escapeHtml(urlData.target_path) + '
'; } html += '
'; }); html += '
'; } else { html += '
No URLs found in Magento 1
'; } html += '
'; // Magento 2 URLs html += '
'; html += '

Magento 2 URLs (' + (storeData.m2_urls.length || 0) + ')

'; if (storeData.m2_urls.length > 0) { html += '
'; storeData.m2_urls.forEach((urlData, index) => { html += '
'; html += '
URL ' + (index + 1) + ':
'; html += '
' + escapeHtml(urlData.url || '-') + '
'; if (urlData.target_path) { html += '
Target: ' + escapeHtml(urlData.target_path) + '
'; } html += '
'; }); html += '
'; } else { html += '
No URLs found in Magento 2
'; } html += '
'; html += '
'; html += '
'; html += '
'; }); content.innerHTML = html; } // Allow Enter key to trigger search document.addEventListener('DOMContentLoaded', function() { const skuFilter = document.getElementById('skuFilter'); if (skuFilter) { skuFilter.addEventListener('keypress', function(e) { if (e.key === 'Enter') { compareUrls(); } }); } const singleSkuInput = document.getElementById('singleSkuInput'); if (singleSkuInput) { singleSkuInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { compareSingleSku(); } }); } }); // Fix / migrate product URLs from M1 to M2 window.fixProductUrls = async function fixProductUrls() { const sku = document.getElementById('fixSkuInput').value.trim(); const dryRun = document.getElementById('fixDryRunInput').checked; const btn = document.getElementById('fixUrlsBtn'); if (!dryRun && !confirm('This will INSERT URL rewrites into Magento 2. Continue?')) { return; } btn.disabled = true; btn.textContent = dryRun ? 'Previewing...' : 'Fixing...'; try { const formData = new FormData(); if (sku) formData.append('sku', sku); formData.append('dry_run', dryRun ? '1' : '0'); const response = await fetch(window.productUrlsRoutes.fixUrls, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, 'Accept': 'application/json' }, body: formData }); const data = await response.json(); if (!data.success) { alert('Error: ' + (data.message || 'unknown')); return; } document.getElementById('fixAdded').textContent = data.added; document.getElementById('fixAddedLabel').textContent = data.dry_run ? 'Would Add' : 'Added'; document.getElementById('fixSkippedExisting').textContent = data.skipped_existing; document.getElementById('fixSkippedNoProduct').textContent = data.skipped_no_m2_product; document.getElementById('fixErrors').textContent = data.errors; document.getElementById('fixLogOutput').textContent = (data.log || []).join('\n') || `(no log lines — ${data.total_m1_rewrites} M1 rewrites scanned)`; document.getElementById('fixResultsSection').style.display = 'block'; } catch (error) { console.error('fixProductUrls error:', error); alert('Failed: ' + error.message); } finally { btn.disabled = false; btn.textContent = 'Fix URLs'; } };