224 lines
9.5 KiB
Plaintext
224 lines
9.5 KiB
Plaintext
<%# Helper methods %>
|
|
<% def status_badge(status) %>
|
|
<% case status %>
|
|
<% when 'pending' %>
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
|
<%= status.capitalize %>
|
|
</span>
|
|
<% when 'processing' %>
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
|
<%= status.capitalize %>
|
|
</span>
|
|
<% when 'completed' %>
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
|
|
<%= status.capitalize %>
|
|
</span>
|
|
<% when 'failed' %>
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
|
<%= status.capitalize %>
|
|
</span>
|
|
<% else %>
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
|
<%= status.capitalize %>
|
|
</span>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<div class="max-w-4xl mx-auto">
|
|
<!-- Header -->
|
|
<div class="bg-white shadow-sm rounded-lg mb-6">
|
|
<div class="px-6 py-4 border-b border-gray-200">
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-2xl font-semibold text-gray-900">Import Details</h1>
|
|
<p class="mt-1 text-sm text-gray-600">
|
|
<%= @data_import.filename %>
|
|
</p>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<%= link_to "← Back to Imports", data_imports_path, class: "inline-flex items-center px-3 py-2 border border-gray-300 shadow-sm text-sm leading-4 font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" %>
|
|
<% unless @data_import.processing? %>
|
|
<%= link_to "Delete", @data_import,
|
|
data: {
|
|
turbo_method: :delete,
|
|
turbo_confirm: "Are you sure you want to delete this import record?"
|
|
},
|
|
class: "inline-flex items-center px-3 py-2 border border-red-300 shadow-sm text-sm leading-4 font-medium rounded-md text-red-700 bg-white hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500" %>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Progress Card -->
|
|
<div data-controller="data-import-progress"
|
|
data-data-import-progress-import-id-value="<%= @data_import.id %>"
|
|
class="bg-white shadow-sm rounded-lg mb-6">
|
|
<div class="px-6 py-4">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-lg font-medium text-gray-900">Import Progress</h2>
|
|
<%= status_badge(@data_import.status) %>
|
|
</div>
|
|
|
|
<!-- Progress Bar -->
|
|
<div class="mb-4">
|
|
<div class="flex items-center justify-between text-sm text-gray-600 mb-1">
|
|
<span>
|
|
<% if @data_import.total_records > 0 && @data_import.processed_records >= @data_import.total_records %>
|
|
<%= number_with_delimiter(@data_import.processed_records) %> total records
|
|
<% elsif @data_import.total_records > 0 %>
|
|
<%= number_with_delimiter(@data_import.processed_records) %> records processed
|
|
<% else %>
|
|
Initializing...
|
|
<% end %>
|
|
</span>
|
|
<span><%= @data_import.progress_percentage %>%</span>
|
|
</div>
|
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
|
<div data-data-import-progress-target="progressBar"
|
|
class="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
|
style="width: <%= @data_import.progress_percentage %>%"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stats Grid -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<div class="bg-gray-50 rounded-lg p-4">
|
|
<div class="text-2xl font-semibold text-gray-900" data-data-import-progress-target="totalRecords">
|
|
<%= number_with_delimiter(@data_import.total_records) %>
|
|
</div>
|
|
<div class="text-sm text-gray-600">Total Records</div>
|
|
</div>
|
|
<div class="bg-green-50 rounded-lg p-4">
|
|
<div class="text-2xl font-semibold text-green-900" data-data-import-progress-target="processedRecords">
|
|
<%= number_with_delimiter(@data_import.processed_records) %>
|
|
</div>
|
|
<div class="text-sm text-green-600">Processed</div>
|
|
</div>
|
|
<div class="bg-red-50 rounded-lg p-4">
|
|
<div class="text-2xl font-semibold text-red-900" data-data-import-progress-target="failedRecords">
|
|
<%= number_with_delimiter(@data_import.failed_records) %>
|
|
</div>
|
|
<div class="text-sm text-red-600">Failed</div>
|
|
</div>
|
|
<div class="bg-blue-50 rounded-lg p-4">
|
|
<div class="text-2xl font-semibold text-blue-900" data-data-import-progress-target="recordsPerSecond">
|
|
<%= number_with_delimiter(@data_import.records_per_second) %>
|
|
</div>
|
|
<div class="text-sm text-blue-600">Records/Sec</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Import Details -->
|
|
<div class="bg-white shadow-sm rounded-lg mb-6">
|
|
<div class="px-6 py-4 border-b border-gray-200">
|
|
<h2 class="text-lg font-medium text-gray-900">Import Information</h2>
|
|
</div>
|
|
<div class="px-6 py-4">
|
|
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
|
|
<div>
|
|
<dt class="text-sm font-medium text-gray-500">Import Type</dt>
|
|
<dd class="mt-1 text-sm text-gray-900 capitalize"><%= @data_import.import_type %></dd>
|
|
</div>
|
|
<div>
|
|
<dt class="text-sm font-medium text-gray-500">Filename</dt>
|
|
<dd class="mt-1 text-sm text-gray-900"><%= @data_import.filename %></dd>
|
|
</div>
|
|
<div>
|
|
<dt class="text-sm font-medium text-gray-500">Started</dt>
|
|
<dd class="mt-1 text-sm text-gray-900">
|
|
<% if @data_import.processing? && @data_import.started_at %>
|
|
<%= time_ago_in_words(@data_import.started_at) %> ago
|
|
(<%= @data_import.started_at.strftime('%Y-%m-%d %H:%M:%S') %>)
|
|
<% elsif @data_import.processing? %>
|
|
Initializing...
|
|
<% elsif @data_import.started_at %>
|
|
<%= time_ago_in_words(@data_import.started_at) %> ago
|
|
(<%= @data_import.started_at.strftime('%Y-%m-%d %H:%M:%S') %>)
|
|
<% else %>
|
|
Not started
|
|
<% end %>
|
|
</dd>
|
|
</div>
|
|
<div>
|
|
<dt class="text-sm font-medium text-gray-500">Duration</dt>
|
|
<dd class="mt-1 text-sm text-gray-900">
|
|
<% if @data_import.duration > 0 %>
|
|
<%= distance_of_time_in_words(@data_import.duration) %>
|
|
<% else %>
|
|
N/A
|
|
<% end %>
|
|
</dd>
|
|
</div>
|
|
<div>
|
|
<dt class="text-sm font-medium text-gray-500">Completed</dt>
|
|
<dd class="mt-1 text-sm text-gray-900">
|
|
<% if @data_import.completed? && @data_import.completed_at %>
|
|
<%= time_ago_in_words(@data_import.completed_at) %> ago
|
|
(<%= @data_import.completed_at.strftime('%Y-%m-%d %H:%M:%S') %>)
|
|
<% elsif @data_import.completed? %>
|
|
Just now
|
|
<% elsif @data_import.processing? %>
|
|
In progress...
|
|
<% else %>
|
|
Not completed
|
|
<% end %>
|
|
</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error Details (if any) -->
|
|
<% if @data_import.error_message.present? || @data_import.import_stats['errors']&.any? %>
|
|
<div class="bg-red-50 border border-red-200 rounded-lg mb-6">
|
|
<div class="px-6 py-4 border-b border-red-200">
|
|
<h2 class="text-lg font-medium text-red-900">Error Details</h2>
|
|
</div>
|
|
<div class="px-6 py-4">
|
|
<% if @data_import.error_message.present? %>
|
|
<div class="mb-4">
|
|
<h3 class="text-sm font-medium text-red-800 mb-2">General Error</h3>
|
|
<p class="text-sm text-red-700"><%= @data_import.error_message %></p>
|
|
</div>
|
|
<% end %>
|
|
|
|
<% if @data_import.import_stats['errors']&.any? %>
|
|
<div>
|
|
<h3 class="text-sm font-medium text-red-800 mb-2">Recent Errors (<%= @data_import.import_stats['errors'].size %>)</h3>
|
|
<div class="bg-white rounded border border-red-200 p-3 max-h-48 overflow-y-auto">
|
|
<ul class="space-y-2">
|
|
<% @data_import.import_stats['errors'].each do |error| %>
|
|
<li class="text-xs text-red-700 font-mono"><%= error %></li>
|
|
<% end %>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
|
|
<!-- Additional Stats (if available) -->
|
|
<% if @data_import.import_stats&.any? && (@data_import.import_stats.except('errors', 'completed_at')).any? %>
|
|
<div class="bg-white shadow-sm rounded-lg">
|
|
<div class="px-6 py-4 border-b border-gray-200">
|
|
<h2 class="text-lg font-medium text-gray-900">Additional Statistics</h2>
|
|
</div>
|
|
<div class="px-6 py-4">
|
|
<dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
|
|
<% @data_import.import_stats.except('errors', 'completed_at').each do |key, value| %>
|
|
<div>
|
|
<dt class="text-sm font-medium text-gray-500"><%= key.to_s.humanize %></dt>
|
|
<dd class="mt-1 text-sm text-gray-900"><%= value.is_a?(Hash) ? value.inspect : value %></dd>
|
|
</div>
|
|
<% end %>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|