Add 'tags' to event model. Add a dataimport system - currently for MaxMind zip files
This commit is contained in:
222
app/views/data_imports/show.html.erb
Normal file
222
app/views/data_imports/show.html.erb
Normal file
@@ -0,0 +1,222 @@
|
||||
<%# 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, method: :delete,
|
||||
data: {
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user