Created
June 13, 2025 15:58
-
-
Save dexit/de8adbd96d76b002918bb7f8eb661712 to your computer and use it in GitHub Desktop.
datamigration.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Migration Process Tracker</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
/* Custom styles for enhanced UI */ | |
body { | |
background-color: #f8fafc; | |
font-family: 'Inter', sans-serif; | |
} | |
.card { | |
background-color: #ffffff; | |
border-radius: 0.75rem; | |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
transition: all 0.3s ease; | |
} | |
.card:hover { | |
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |
transform: translateY(-2px); | |
} | |
.log-entry { | |
transition: all 0.3s ease; | |
padding: 0.5rem 0; | |
border-bottom: 1px solid rgba(255, 255, 255, 0.1); | |
} | |
.log-entry:last-child { | |
border-bottom: none; | |
} | |
.log-entry:hover { | |
background-color: rgba(255, 255, 255, 0.05); | |
} | |
.stage-container { | |
display: flex; | |
align-items: center; | |
justify-content: space-between; | |
position: relative; | |
margin-bottom: 2rem; | |
} | |
.stage-container::before { | |
content: ''; | |
position: absolute; | |
top: 50%; | |
left: 0; | |
right: 0; | |
height: 4px; | |
background-color: #e5e7eb; | |
transform: translateY(-50%); | |
z-index: 0; | |
} | |
.stage-progress-line { | |
content: ''; | |
position: absolute; | |
top: 50%; | |
left: 0; | |
height: 4px; | |
background-color: #3b82f6; | |
transform: translateY(-50%); | |
z-index: 1; | |
width: 0%; | |
transition: width 0.5s ease-in-out; | |
} | |
.stage-indicator { | |
position: relative; | |
z-index: 2; | |
text-align: center; | |
flex-grow: 1; | |
padding: 0 10px; | |
} | |
.stage-indicator:first-child { | |
text-align: left; | |
transform: translateX(10px); | |
} | |
.stage-indicator:last-child { | |
text-align: right; | |
transform: translateX(-10px); | |
} | |
.progress-dot { | |
width: 24px; | |
height: 24px; | |
border-radius: 50%; | |
background-color: #d1d5db; | |
border: 3px solid #ffffff; | |
margin: 0 auto 0.5rem auto; | |
transition: all 0.3s ease; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
color: transparent; | |
font-size: 0.8rem; | |
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | |
} | |
.progress-dot.active { | |
background-color: #3b82f6; | |
border-color: #93c5fd; | |
box-shadow: 0 0 0 5px rgba(59, 130, 246, 0.3); | |
} | |
.progress-dot.completed { | |
background-color: #22c55e; | |
border-color: #86efac; | |
color: #ffffff; | |
} | |
.progress-dot.failed { | |
background-color: #ef4444; | |
border-color: #fca5a5; | |
color: #ffffff; | |
} | |
.progress-dot.pending { | |
background-color: #f59e0b; | |
border-color: #fcd34d; | |
color: #ffffff; | |
} | |
.stage-text { | |
font-size: 0.875rem; | |
font-weight: 500; | |
color: #6b7280; | |
transition: color 0.3s ease; | |
} | |
.stage-indicator.active .stage-text { | |
color: #3b82f6; | |
font-weight: 600; | |
} | |
.stage-indicator.completed .stage-text { | |
color: #22c55e; | |
font-weight: 600; | |
} | |
.stage-indicator.failed .stage-text { | |
color: #ef4444; | |
font-weight: 600; | |
} | |
.stage-indicator.pending .stage-text { | |
color: #f59e0b; | |
font-weight: 600; | |
} | |
/* Skeleton Loader Styles */ | |
.skeleton { | |
background-color: #e5e7eb; | |
border-radius: 0.25rem; | |
animation: pulse 1.5s infinite ease-in-out; | |
} | |
@keyframes pulse { | |
0%, 100% { opacity: 1; } | |
50% { opacity: 0.5; } | |
} | |
.skeleton-text { | |
height: 1em; | |
margin-bottom: 0.5em; | |
} | |
.skeleton-text.short { width: 60%; } | |
.skeleton-text.medium { width: 80%; } | |
.skeleton-text.long { width: 100%; } | |
.skeleton-circle { | |
width: 2rem; | |
height: 2rem; | |
border-radius: 50%; | |
} | |
.skeleton-table-row { | |
display: flex; | |
justify-content: space-between; | |
padding: 0.75rem 1rem; | |
border-bottom: 1px solid #f3f4f6; | |
} | |
.skeleton-table-cell { | |
height: 1em; | |
width: 30%; | |
margin-right: 1rem; | |
} | |
.skeleton-table-cell:last-child { | |
margin-right: 0; | |
} | |
/* Custom scrollbar */ | |
::-webkit-scrollbar { | |
width: 8px; | |
height: 8px; | |
} | |
::-webkit-scrollbar-track { | |
background: #f1f1f1; | |
border-radius: 4px; | |
} | |
::-webkit-scrollbar-thumb { | |
background: #cbd5e1; | |
border-radius: 4px; | |
} | |
::-webkit-scrollbar-thumb:hover { | |
background: #94a3b8; | |
} | |
/* Custom animations */ | |
@keyframes fadeIn { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
.fade-in { | |
animation: fadeIn 0.3s ease-in-out; | |
} | |
/* Status badges */ | |
.status-badge { | |
padding: 0.25rem 0.5rem; | |
border-radius: 9999px; | |
font-size: 0.75rem; | |
font-weight: 600; | |
display: inline-flex; | |
align-items: center; | |
} | |
.status-badge i { | |
margin-right: 0.25rem; | |
font-size: 0.625rem; | |
} | |
/* Tooltip */ | |
.tooltip { | |
position: relative; | |
} | |
.tooltip .tooltip-text { | |
visibility: hidden; | |
width: 120px; | |
background-color: #1e293b; | |
color: #fff; | |
text-align: center; | |
border-radius: 6px; | |
padding: 5px; | |
position: absolute; | |
z-index: 1; | |
bottom: 125%; | |
left: 50%; | |
margin-left: -60px; | |
opacity: 0; | |
transition: opacity 0.3s; | |
font-size: 0.75rem; | |
} | |
.tooltip:hover .tooltip-text { | |
visibility: visible; | |
opacity: 1; | |
} | |
/* Custom tabs */ | |
.tab { | |
padding: 0.75rem 1rem; | |
cursor: pointer; | |
border-bottom: 2px solid transparent; | |
transition: all 0.2s ease; | |
} | |
.tab.active { | |
border-bottom-color: #3b82f6; | |
color: #3b82f6; | |
font-weight: 600; | |
} | |
.tab:hover:not(.active) { | |
border-bottom-color: #e5e7eb; | |
} | |
/* Custom dropdown */ | |
.dropdown { | |
position: relative; | |
display: inline-block; | |
} | |
.dropdown-content { | |
display: none; | |
position: absolute; | |
right: 0; | |
background-color: #fff; | |
min-width: 160px; | |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
z-index: 1; | |
border-radius: 0.5rem; | |
overflow: hidden; | |
} | |
.dropdown:hover .dropdown-content { | |
display: block; | |
} | |
.dropdown-item { | |
padding: 0.5rem 1rem; | |
display: block; | |
color: #4b5563; | |
transition: all 0.2s ease; | |
} | |
.dropdown-item:hover { | |
background-color: #f3f4f6; | |
color: #1f2937; | |
} | |
/* Custom switch */ | |
.switch { | |
position: relative; | |
display: inline-block; | |
width: 40px; | |
height: 20px; | |
} | |
.switch input { | |
opacity: 0; | |
width: 0; | |
height: 0; | |
} | |
.slider { | |
position: absolute; | |
cursor: pointer; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background-color: #ccc; | |
transition: .4s; | |
border-radius: 34px; | |
} | |
.slider:before { | |
position: absolute; | |
content: ""; | |
height: 16px; | |
width: 16px; | |
left: 2px; | |
bottom: 2px; | |
background-color: white; | |
transition: .4s; | |
border-radius: 50%; | |
} | |
input:checked + .slider { | |
background-color: #3b82f6; | |
} | |
input:checked + .slider:before { | |
transform: translateX(20px); | |
} | |
</style> | |
</head> | |
<body class="bg-gray-50 min-h-screen text-gray-800"> | |
<div class="container mx-auto px-4 py-8"> | |
<!-- Header --> | |
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8 gap-4"> | |
<div class="flex items-center"> | |
<div class="bg-blue-600 text-white p-3 rounded-xl mr-4"> | |
<i class="fas fa-exchange-alt text-2xl"></i> | |
</div> | |
<div> | |
<h1 class="text-3xl font-bold text-gray-800">Migration Process Tracker</h1> | |
<p class="text-gray-600">Monitor and manage your data migration workflows</p> | |
</div> | |
</div> | |
<div class="flex flex-col sm:flex-row gap-3 w-full md:w-auto"> | |
<button id="refreshBtn" class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg flex items-center justify-center transition duration-200"> | |
<i class="fas fa-sync-alt mr-2"></i> Refresh | |
</button> | |
<button id="newMigrationBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg flex items-center justify-center font-medium transition duration-200 transform hover:scale-[1.02]"> | |
<i class="fas fa-plus mr-2"></i> New Migration | |
</button> | |
</div> | |
</div> | |
<!-- Migration Dashboard --> | |
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> | |
<!-- Stats Card 1 --> | |
<div class="card"> | |
<div class="p-6"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<p class="text-gray-500 text-sm font-medium">Successful Migrations</p> | |
<h3 class="text-3xl font-bold text-gray-800 mt-1" id="successCount">0</h3> | |
</div> | |
<div class="p-3 rounded-full bg-green-100 text-green-600"> | |
<i class="fas fa-check-circle text-2xl"></i> | |
</div> | |
</div> | |
<div class="mt-4"> | |
<div class="flex items-center text-sm text-gray-600"> | |
<span class="text-green-500 mr-1"><i class="fas fa-arrow-up"></i> 12%</span> | |
<span>vs last week</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Stats Card 2 --> | |
<div class="card"> | |
<div class="p-6"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<p class="text-gray-500 text-sm font-medium">Failed Migrations</p> | |
<h3 class="text-3xl font-bold text-gray-800 mt-1" id="errorCount">0</h3> | |
</div> | |
<div class="p-3 rounded-full bg-red-100 text-red-600"> | |
<i class="fas fa-exclamation-circle text-2xl"></i> | |
</div> | |
</div> | |
<div class="mt-4"> | |
<div class="flex items-center text-sm text-gray-600"> | |
<span class="text-red-500 mr-1"><i class="fas fa-arrow-down"></i> 8%</span> | |
<span>vs last week</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Stats Card 3 --> | |
<div class="card"> | |
<div class="p-6"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<p class="text-gray-500 text-sm font-medium">In Progress</p> | |
<h3 class="text-3xl font-bold text-gray-800 mt-1" id="inProgressCount">0</h3> | |
</div> | |
<div class="p-3 rounded-full bg-blue-100 text-blue-600"> | |
<i class="fas fa-sync-alt text-2xl"></i> | |
</div> | |
</div> | |
<div class="mt-4"> | |
<div class="flex items-center text-sm text-gray-600"> | |
<span class="text-blue-500 mr-1"><i class="fas fa-arrow-up"></i> 5%</span> | |
<span>vs last week</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Stats Card 4 --> | |
<div class="card"> | |
<div class="p-6"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<p class="text-gray-500 text-sm font-medium">Avg. Duration</p> | |
<h3 class="text-3xl font-bold text-gray-800 mt-1" id="avgDuration">0s</h3> | |
</div> | |
<div class="p-3 rounded-full bg-purple-100 text-purple-600"> | |
<i class="fas fa-clock text-2xl"></i> | |
</div> | |
</div> | |
<div class="mt-4"> | |
<div class="flex items-center text-sm text-gray-600"> | |
<span class="text-purple-500 mr-1"><i class="fas fa-arrow-down"></i> 15%</span> | |
<span>vs last week</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Current Migration Process --> | |
<div class="card mb-8 overflow-hidden"> | |
<!-- Process Header --> | |
<div class="bg-gray-50 px-6 py-4 border-b flex flex-col sm:flex-row justify-between items-start sm:items-center"> | |
<div class="flex items-center mb-3 sm:mb-0"> | |
<i class="fas fa-project-diagram mr-3 text-blue-600 text-xl"></i> | |
<h2 class="text-xl font-semibold text-gray-800">Current Migration Process</h2> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<div class="flex items-center text-sm text-gray-600"> | |
<span class="mr-2">Last Updated:</span> | |
<span id="lastUpdated" class="font-medium">--:--:--</span> | |
</div> | |
<div class="flex items-center"> | |
<label class="switch mr-2"> | |
<input type="checkbox" id="autoRefreshToggle" checked> | |
<span class="slider"></span> | |
</label> | |
<span class="text-sm text-gray-600">Auto-refresh</span> | |
</div> | |
</div> | |
</div> | |
<!-- Process Stages --> | |
<div class="p-6"> | |
<div class="stage-container"> | |
<div class="stage-progress-line" id="stageProgressLine" style="width: 0%;"></div> | |
<div class="stage-indicator" data-stage="HubSpot Lookup"> | |
<div class="progress-dot"></div> | |
<p class="stage-text">HubSpot Lookup</p> | |
</div> | |
<div class="stage-indicator" data-stage="PICS Init"> | |
<div class="progress-dot"></div> | |
<p class="stage-text">PICS Init</p> | |
</div> | |
<div class="stage-indicator" data-stage="Applicant"> | |
<div class="progress-dot"></div> | |
<p class="stage-text">Applicant</p> | |
</div> | |
<div class="stage-indicator" data-stage="Opportunity"> | |
<div class="progress-dot"></div> | |
<p class="stage-text">Opportunity</p> | |
</div> | |
<div class="stage-indicator" data-stage="Complete"> | |
<div class="progress-dot"></div> | |
<p class="stage-text">Complete</p> | |
</div> | |
</div> | |
<!-- Process Details --> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6"> | |
<div class="bg-gray-50 rounded-lg p-5"> | |
<h3 class="font-semibold text-gray-700 mb-4 flex items-center text-lg"> | |
<i class="fas fa-info-circle mr-3 text-blue-600"></i> | |
Migration Details | |
</h3> | |
<div class="space-y-3 text-gray-700"> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Object ID:</span> | |
<span id="objectId" class="font-medium">--</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Event ID:</span> | |
<span id="eventId" class="font-medium">--</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Current Stage:</span> | |
<span id="currentStage" class="font-medium">--</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Current Step:</span> | |
<span id="currentStep" class="font-medium">--</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Started:</span> | |
<span id="startTime" class="font-medium">--</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Duration:</span> | |
<span id="duration" class="font-medium">--</span> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-50 rounded-lg p-5"> | |
<h3 class="font-semibold text-gray-700 mb-4 flex items-center text-lg"> | |
<i class="fas fa-cog mr-3 text-blue-600"></i> | |
System Info | |
</h3> | |
<div class="space-y-3 text-gray-700"> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">API Status:</span> | |
<span class="font-medium text-green-600 flex items-center"> | |
<span class="w-2 h-2 rounded-full bg-green-500 mr-2"></span> | |
Connected | |
</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Database:</span> | |
<span class="font-medium">MySQL 8.0</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Last Sync:</span> | |
<span class="font-medium">2 minutes ago</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Next Sync:</span> | |
<span class="font-medium">In 5 minutes</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Memory Usage:</span> | |
<div class="w-24 bg-gray-200 rounded-full h-2"> | |
<div class="bg-blue-600 h-2 rounded-full" style="width: 45%"></div> | |
</div> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">CPU Load:</span> | |
<div class="w-24 bg-gray-200 rounded-full h-2"> | |
<div class="bg-blue-600 h-2 rounded-full" style="width: 28%"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-50 rounded-lg p-5"> | |
<h3 class="font-semibold text-gray-700 mb-4 flex items-center text-lg"> | |
<i class="fas fa-chart-line mr-3 text-blue-600"></i> | |
Performance Metrics | |
</h3> | |
<div class="space-y-3 text-gray-700"> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Records Processed:</span> | |
<span id="recordsProcessed" class="font-medium">0</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">API Calls:</span> | |
<span id="apiCalls" class="font-medium">0</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Avg. API Latency:</span> | |
<span id="apiLatency" class="font-medium">0ms</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Data Volume:</span> | |
<span id="dataVolume" class="font-medium">0 MB</span> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Success Rate:</span> | |
<div class="w-24 bg-gray-200 rounded-full h-2"> | |
<div class="bg-green-500 h-2 rounded-full" style="width: 92%"></div> | |
</div> | |
</div> | |
<div class="flex justify-between"> | |
<span class="text-gray-500">Error Rate:</span> | |
<div class="w-24 bg-gray-200 rounded-full h-2"> | |
<div class="bg-red-500 h-2 rounded-full" style="width: 8%"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Tabs for additional details --> | |
<div class="border-b border-gray-200 mb-6"> | |
<div class="flex space-x-6"> | |
<div class="tab active" data-tab="mappings"> | |
<i class="fas fa-map-marked-alt mr-2"></i> Property Mappings | |
</div> | |
<div class="tab" data-tab="data"> | |
<i class="fas fa-database mr-2"></i> Sample Data | |
</div> | |
<div class="tab" data-tab="errors"> | |
<i class="fas fa-exclamation-triangle mr-2"></i> Errors & Warnings | |
</div> | |
<div class="tab" data-tab="logs"> | |
<i class="fas fa-scroll mr-2"></i> Process Logs | |
</div> | |
</div> | |
</div> | |
<!-- Tab Content --> | |
<div id="mappingsContent" class="tab-content active"> | |
<div class="overflow-x-auto"> | |
<table class="min-w-full divide-y divide-gray-200"> | |
<thead class="bg-gray-50"> | |
<tr> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Source Property</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Target Property</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Transformation</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th> | |
</tr> | |
</thead> | |
<tbody class="bg-white divide-y divide-gray-200"> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">contact_id</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">externalId</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">String</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Direct</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> | |
Mapped | |
</span> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">firstname</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">firstName</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">String</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Direct</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> | |
Mapped | |
</span> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">lastname</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">lastName</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">String</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Direct</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> | |
Mapped | |
</span> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">email</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">email</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">String</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Direct</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> | |
Mapped | |
</span> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">createdate</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">createdDate</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">DateTime</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Format conversion</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800"> | |
Pending | |
</span> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
<div id="dataContent" class="tab-content hidden"> | |
<div class="bg-gray-50 rounded-lg p-5"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="text-lg font-medium text-gray-800">Sample Source Data</h3> | |
<div class="relative"> | |
<button id="sampleDataDropdownBtn" class="flex items-center text-gray-600 hover:text-gray-900"> | |
<span>JSON</span> | |
<i class="fas fa-chevron-down ml-2 text-sm"></i> | |
</button> | |
<div id="sampleDataDropdown" class="hidden absolute right-0 mt-2 w-32 bg-white rounded-md shadow-lg z-10"> | |
<div class="py-1"> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-format="json">JSON</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-format="xml">XML</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-format="csv">CSV</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-800 rounded-lg p-4 overflow-x-auto"> | |
<pre class="text-green-400 text-sm"><code id="sampleDataJson">{ | |
"contact_id": "12345", | |
"firstname": "John", | |
"lastname": "Doe", | |
"email": "[email protected]", | |
"createdate": "2023-01-15T08:30:00Z", | |
"status": "active", | |
"company": "Acme Inc", | |
"phone": "+1 (555) 123-4567" | |
}</code></pre> | |
<pre class="text-green-400 text-sm hidden" id="sampleDataXml"><code><contact> | |
<contact_id>12345</contact_id> | |
<firstname>John</firstname> | |
<lastname>Doe</lastname> | |
<email>[email protected]</email> | |
<createdate>2023-01-15T08:30:00Z</createdate> | |
<status>active</status> | |
<company>Acme Inc</company> | |
<phone>+1 (555) 123-4567</phone> | |
</contact></code></pre> | |
<pre class="text-green-400 text-sm hidden" id="sampleDataCsv"><code>contact_id,firstname,lastname,email,createdate,status,company,phone | |
12345,John,Doe,[email protected],2023-01-15T08:30:00Z,active,Acme Inc,"+1 (555) 123-4567"</code></pre> | |
</div> | |
</div> | |
</div> | |
<div id="errorsContent" class="tab-content hidden"> | |
<div class="bg-gray-50 rounded-lg p-5"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="text-lg font-medium text-gray-800">Errors & Warnings</h3> | |
<div class="flex space-x-2"> | |
<button class="px-3 py-1 text-xs font-medium rounded-full bg-red-100 text-red-800">Errors (2)</button> | |
<button class="px-3 py-1 text-xs font-medium rounded-full bg-yellow-100 text-yellow-800">Warnings (4)</button> | |
<button class="px-3 py-1 text-xs font-medium rounded-full bg-blue-100 text-blue-800">All (6)</button> | |
</div> | |
</div> | |
<div class="space-y-4"> | |
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-red-500"> | |
<div class="flex justify-between items-start"> | |
<div> | |
<h4 class="font-medium text-gray-800">Missing required field: email</h4> | |
<p class="text-sm text-gray-600 mt-1">Record ID: 12345, Stage: HubSpot Lookup</p> | |
</div> | |
<span class="text-xs font-medium text-red-500">Error</span> | |
</div> | |
<div class="mt-3 text-sm text-gray-700 bg-gray-50 p-3 rounded"> | |
<p>Cannot proceed with migration as the email field is required but missing in the source data.</p> | |
</div> | |
</div> | |
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-yellow-500"> | |
<div class="flex justify-between items-start"> | |
<div> | |
<h4 class="font-medium text-gray-800">Date format mismatch</h4> | |
<p class="text-sm text-gray-600 mt-1">Record ID: 67890, Stage: PICS Init</p> | |
</div> | |
<span class="text-xs font-medium text-yellow-500">Warning</span> | |
</div> | |
<div class="mt-3 text-sm text-gray-700 bg-gray-50 p-3 rounded"> | |
<p>The createdate field contains an unexpected format (MM/DD/YYYY instead of YYYY-MM-DD). Attempting to auto-convert.</p> | |
</div> | |
</div> | |
<div class="bg-white rounded-lg shadow-sm p-4 border-l-4 border-yellow-500"> | |
<div class="flex justify-between items-start"> | |
<div> | |
<h4 class="font-medium text-gray-800">Duplicate record detected</h4> | |
<p class="text-sm text-gray-600 mt-1">Record ID: 54321, Stage: Applicant</p> | |
</div> | |
<span class="text-xs font-medium text-yellow-500">Warning</span> | |
</div> | |
<div class="mt-3 text-sm text-gray-700 bg-gray-50 p-3 rounded"> | |
<p>A record with the same email ([email protected]) already exists in the target system. Will update existing record instead of creating new one.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div id="logsContent" class="tab-content hidden"> | |
<div class="bg-gray-50 rounded-lg p-5"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="text-lg font-medium text-gray-800">Process Logs</h3> | |
<div class="flex items-center space-x-2"> | |
<div class="relative"> | |
<button id="logLevelDropdownBtn" class="flex items-center text-gray-600 hover:text-gray-900"> | |
<span>All Levels</span> | |
<i class="fas fa-chevron-down ml-2 text-sm"></i> | |
</button> | |
<div id="logLevelDropdown" class="hidden absolute right-0 mt-2 w-40 bg-white rounded-md shadow-lg z-10"> | |
<div class="py-1"> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-level="all">All Levels</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-level="info">Info</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-level="warning">Warning</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-level="error">Error</a> | |
</div> | |
</div> | |
</div> | |
<button class="text-blue-600 hover:text-blue-800 text-sm font-medium"> | |
<i class="fas fa-download mr-1"></i> Export | |
</button> | |
</div> | |
</div> | |
<div class="bg-gray-800 rounded-lg p-4 overflow-y-auto max-h-96"> | |
<div class="space-y-2"> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:23]</span> INFO: Migration process started | |
</div> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:25]</span> INFO: Connected to source system (HubSpot) | |
</div> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:27]</span> INFO: Connected to target system (PICS) | |
</div> | |
<div class="log-entry text-yellow-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:30]</span> WARNING: Date format mismatch in record 67890 (createdate) | |
</div> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:35]</span> INFO: Processing batch 1 of 5 (20 records) | |
</div> | |
<div class="log-entry text-red-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:38]</span> ERROR: Missing required field: email in record 12345 | |
</div> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:40]</span> INFO: Batch 1 completed (19/20 records) | |
</div> | |
<div class="log-entry text-yellow-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:45]</span> WARNING: Duplicate record detected (email: [email protected]) | |
</div> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:50]</span> INFO: Processing batch 2 of 5 (20 records) | |
</div> | |
<div class="log-entry text-green-400 text-sm"> | |
<span class="text-gray-400">[2023-06-15 09:15:55]</span> INFO: Batch 2 completed (20/20 records) | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Recent Migrations --> | |
<div class="card mb-8"> | |
<div class="bg-gray-50 px-6 py-4 border-b"> | |
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-2 sm:mb-0"> | |
<i class="fas fa-history mr-3 text-blue-600"></i> Recent Migrations | |
</h2> | |
<div class="flex items-center space-x-4"> | |
<div class="relative"> | |
<button id="timeRangeDropdownBtn" class="flex items-center text-gray-600 hover:text-gray-900"> | |
<span>Last 24 hours</span> | |
<i class="fas fa-chevron-down ml-2 text-sm"></i> | |
</button> | |
<div id="timeRangeDropdown" class="hidden absolute right-0 mt-2 w-40 bg-white rounded-md shadow-lg z-10"> | |
<div class="py-1"> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-range="1">Last hour</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-range="24">Last 24 hours</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-range="168">Last 7 days</a> | |
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" data-range="720">Last 30 days</a> | |
</div> | |
</div> | |
</div> | |
<button class="text-blue-600 hover:text-blue-800 text-sm font-medium"> | |
<i class="fas fa-filter mr-1"></i> Filter | |
</button> | |
</div> | |
</div> | |
</div> | |
<div class="overflow-x-auto"> | |
<table class="min-w-full divide-y divide-gray-200"> | |
<thead class="bg-gray-50"> | |
<tr> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Migration ID</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Object Type</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Records</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Started</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Duration</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> | |
</tr> | |
</thead> | |
<tbody class="bg-white divide-y divide-gray-200"> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">MIG-2023-06-15-001</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Contact</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> | |
Completed | |
</span> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">125</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">2023-06-15 09:15</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">2m 45s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> | |
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a> | |
<a href="#" class="text-gray-600 hover:text-gray-900">Logs</a> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">MIG-2023-06-15-002</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Company</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"> | |
In Progress | |
</span> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">42/87</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">2023-06-15 10:30</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">1m 12s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> | |
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a> | |
<a href="#" class="text-gray-600 hover:text-gray-900">Logs</a> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">MIG-2023-06-14-005</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Deal</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"> | |
Failed | |
</span> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">0/63</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">2023-06-14 16:45</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">0m 23s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> | |
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a> | |
<a href="#" class="text-gray-600 hover:text-gray-900">Logs</a> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">MIG-2023-06-14-004</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Contact</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> | |
Completed | |
</span> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">98</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">2023-06-14 14:20</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">1m 58s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> | |
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a> | |
<a href="#" class="text-gray-600 hover:text-gray-900">Logs</a> | |
</td> | |
</tr> | |
<tr> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">MIG-2023-06-14-003</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Contact</td> | |
<td class="px-6 py-4 whitespace-nowrap"> | |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800"> | |
Partial | |
</span> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">87/120</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">2023-06-14 11:05</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">3m 12s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> | |
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a> | |
<a href="#" class="text-gray-600 hover:text-gray-900">Logs</a> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
<div class="bg-gray-50 px-6 py-3 border-t"> | |
<div class="flex flex-col sm:flex-row justify-between items-center"> | |
<div class="text-sm text-gray-500 mb-2 sm:mb-0"> | |
Showing <span class="font-medium">1</span> to <span class="font-medium">5</span> of <span class="font-medium">24</span> migrations | |
</div> | |
<div class="flex space-x-1"> | |
<button class="px-3 py-1 rounded-md bg-white border border-gray-300 text-sm font-medium text-gray-700 hover:bg-gray-50"> | |
Previous | |
</button> | |
<button class="px-3 py-1 rounded-md bg-blue-600 text-white text-sm font-medium hover:bg-blue-700"> | |
1 | |
</button> | |
<button class="px-3 py-1 rounded-md bg-white border border-gray-300 text-sm font-medium text-gray-700 hover:bg-gray-50"> | |
2 | |
</button> | |
<button class="px-3 py-1 rounded-md bg-white border border-gray-300 text-sm font-medium text-gray-700 hover:bg-gray-50"> | |
3 | |
</button> | |
<button class="px-3 py-1 rounded-md bg-white border border-gray-300 text-sm font-medium text-gray-700 hover:bg-gray-50"> | |
Next | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Tab switching functionality | |
document.addEventListener('DOMContentLoaded', function() { | |
// Tab switching | |
const tabs = document.querySelectorAll('.tab'); | |
tabs.forEach(tab => { | |
tab.addEventListener('click', function() { | |
// Remove active class from all tabs and content | |
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); | |
document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden')); | |
// Add active class to clicked tab | |
this.classList.add('active'); | |
// Show corresponding content | |
const tabName = this.getAttribute('data-tab'); | |
document.getElementById(tabName + 'Content').classList.remove('hidden'); | |
}); | |
}); | |
// Sample data format dropdown | |
const sampleDataDropdownBtn = document.getElementById('sampleDataDropdownBtn'); | |
const sampleDataDropdown = document.getElementById('sampleDataDropdown'); | |
sampleDataDropdownBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
sampleDataDropdown.classList.toggle('hidden'); | |
}); | |
document.addEventListener('click', function() { | |
sampleDataDropdown.classList.add('hidden'); | |
}); | |
// Sample data format switching | |
document.querySelectorAll('#sampleDataDropdown a').forEach(link => { | |
link.addEventListener('click', function(e) { | |
e.preventDefault(); | |
const format = this.getAttribute('data-format'); | |
sampleDataDropdownBtn.querySelector('span').textContent = format.toUpperCase(); | |
// Hide all format previews | |
document.getElementById('sampleDataJson').classList.add('hidden'); | |
document.getElementById('sampleDataXml').classList.add('hidden'); | |
document.getElementById('sampleDataCsv').classList.add('hidden'); | |
// Show selected format | |
document.getElementById('sampleData' + format.charAt(0).toUpperCase() + format.slice(1)).classList.remove('hidden'); | |
sampleDataDropdown.classList.add('hidden'); | |
}); | |
}); | |
// Log level dropdown | |
const logLevelDropdownBtn = document.getElementById('logLevelDropdownBtn'); | |
const logLevelDropdown = document.getElementById('logLevelDropdown'); | |
logLevelDropdownBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
logLevelDropdown.classList.toggle('hidden'); | |
}); | |
document.addEventListener('click', function() { | |
logLevelDropdown.classList.add('hidden'); | |
}); | |
// Time range dropdown | |
const timeRangeDropdownBtn = document.getElementById('timeRangeDropdownBtn'); | |
const timeRangeDropdown = document.getElementById('timeRangeDropdown'); | |
timeRangeDropdownBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
timeRangeDropdown.classList.toggle('hidden'); | |
}); | |
document.addEventListener('click', function() { | |
timeRangeDropdown.classList.add('hidden'); | |
}); | |
// Simulate migration progress | |
simulateMigrationProgress(); | |
// Update stats | |
updateStats(); | |
// Auto-refresh toggle | |
const autoRefreshToggle = document.getElementById('autoRefreshToggle'); | |
let refreshInterval; | |
function startAutoRefresh() { | |
refreshInterval = setInterval(() => { | |
simulateMigrationProgress(); | |
updateStats(); | |
}, 5000); | |
} | |
function stopAutoRefresh() { | |
clearInterval(refreshInterval); | |
} | |
autoRefreshToggle.addEventListener('change', function() { | |
if (this.checked) { | |
startAutoRefresh(); | |
} else { | |
stopAutoRefresh(); | |
} | |
}); | |
// Start auto-refresh initially | |
startAutoRefresh(); | |
// Manual refresh button | |
document.getElementById('refreshBtn').addEventListener('click', function() { | |
simulateMigrationProgress(); | |
updateStats(); | |
}); | |
// New migration button | |
document.getElementById('newMigrationBtn').addEventListener('click', function() { | |
alert('New migration workflow will start here!'); | |
}); | |
}); | |
function simulateMigrationProgress() { | |
const stages = ['HubSpot Lookup', 'PICS Init', 'Applicant', 'Opportunity', 'Complete']; | |
const randomStageIndex = Math.floor(Math.random() * stages.length); | |
const currentStage = stages[randomStageIndex]; | |
// Update progress line | |
const progressPercentage = (randomStageIndex / (stages.length - 1)) * 100; | |
document.getElementById('stageProgressLine').style.width = progressPercentage + '%'; | |
// Update stage indicators | |
document.querySelectorAll('.stage-indicator').forEach((indicator, index) => { | |
const dot = indicator.querySelector('.progress-dot'); | |
const text = indicator.querySelector('.stage-text'); | |
indicator.classList.remove('active', 'completed', 'failed', 'pending'); | |
dot.classList.remove('active', 'completed', 'failed', 'pending'); | |
if (index < randomStageIndex) { | |
indicator.classList.add('completed'); | |
dot.classList.add('completed'); | |
dot.innerHTML = '<i class="fas fa-check"></i>'; | |
} else if (index === randomStageIndex) { | |
indicator.classList.add('active'); | |
dot.classList.add('active'); | |
// Randomly set some stages to failed or pending | |
if (Math.random() < 0.2 && currentStage !== 'Complete') { | |
indicator.classList.add('failed'); | |
dot.classList.add('failed'); | |
dot.innerHTML = '<i class="fas fa-times"></i>'; | |
} else if (Math.random() < 0.3 && currentStage !== 'Complete') { | |
indicator.classList.add('pending'); | |
dot.classList.add('pending'); | |
dot.innerHTML = '<i class="fas fa-clock"></i>'; | |
} | |
} | |
}); | |
// Update details | |
document.getElementById('currentStage').textContent = currentStage; | |
document.getElementById('currentStep').textContent = getRandomStep(currentStage); | |
document.getElementById('objectId').textContent = 'OBJ-' + Math.floor(Math.random() * 10000); | |
document.getElementById('eventId').textContent = 'EVT-' + Math.floor(Math.random() * 10000); | |
const now = new Date(); | |
const startTime = new Date(now.getTime() - Math.floor(Math.random() * 30 + 5) * 1000); | |
document.getElementById('startTime').textContent = formatTime(startTime); | |
document.getElementById('lastUpdated').textContent = formatTime(now); | |
const durationSeconds = Math.floor((now - startTime) / 1000); | |
document.getElementById('duration').textContent = durationSeconds + 's'; | |
// Update performance metrics | |
document.getElementById('recordsProcessed').textContent = Math.floor(Math.random() * 100); | |
document.getElementById('apiCalls').textContent = Math.floor(Math.random() * 50); | |
document.getElementById('apiLatency').textContent = Math.floor(Math.random() * 500) + 'ms'; | |
document.getElementById('dataVolume').textContent = (Math.random() * 10).toFixed(2) + ' MB'; | |
} | |
function updateStats() { | |
document.getElementById('successCount').textContent = Math.floor(Math.random() * 50); | |
document.getElementById('errorCount').textContent = Math.floor(Math.random() * 10); | |
document.getElementById('inProgressCount').textContent = Math.floor(Math.random() * 5); | |
document.getElementById('avgDuration').textContent = Math.floor(Math.random() * 120) + 's'; | |
} | |
function formatTime(date) { | |
return date.toLocaleTimeString() + ' ' + date.toLocaleDateString(); | |
} | |
function getRandomStep(stage) { | |
const steps = { | |
'HubSpot Lookup': ['Fetching contacts', 'Validating data', 'Preparing for transfer'], | |
'PICS Init': ['Establishing connection', 'Creating records', 'Mapping fields'], | |
'Applicant': ['Processing applications', 'Verifying details', 'Updating status'], | |
'Opportunity': ['Calculating values', 'Syncing deals', 'Finalizing records'], | |
'Complete': ['Finalizing', 'Generating report', 'Cleaning up'] | |
}; | |
const stageSteps = steps[stage] || ['Processing']; | |
return stageSteps[Math.floor(Math.random() * stageSteps.length)]; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment