| 1 | <% content_for :title, "Importing #{@import.target_name}" %> |
| 2 | |
| 3 | <%# Live progress: poll every few seconds until the import reaches a terminal |
| 4 | state. A meta refresh keeps this dependency-free (no JS needed) and stops |
| 5 | once done/failed. %> |
| 6 | <% unless @import.terminal? %> |
| 7 | <% content_for :head do %> |
| 8 | <meta http-equiv="refresh" content="4"> |
| 9 | <% end %> |
| 10 | <% end %> |
| 11 | |
| 12 | <div class="max-w-2xl mx-auto px-4 sm:px-6 py-12"> |
| 13 | <div class="flex items-center justify-between mb-6"> |
| 14 | <div> |
| 15 | <h1 class="text-xl font-semibold text-gray-100"><%= @import.target_name %></h1> |
| 16 | <p class="text-sm text-gray-400"> |
| 17 | <%= @import.mirror? ? "Mirror" : "Migrate" %> · from <%= @import.source_url %> |
| 18 | </p> |
| 19 | </div> |
| 20 | <%= render "imports/status_badge", import: @import %> |
| 21 | </div> |
| 22 | |
| 23 | <%# Ordered phase checklist. %> |
| 24 | <% phases = [ |
| 25 | ["queued", "Queued"], |
| 26 | ["cloning", "Cloning source"], |
| 27 | ["pushing", "Pushing to siGit"], |
| 28 | ["fetching_lfs", "Fetching LFS objects"], |
| 29 | ["finalizing", "Finalizing"], |
| 30 | ["done", "Done"] |
| 31 | ] |
| 32 | order = RepositoryImport::STATUSES |
| 33 | current_idx = order.index(@import.status) || 0 %> |
| 34 | |
| 35 | <div class="card divide-y divide-surface-600"> |
| 36 | <% phases.each do |key, label| |
| 37 | idx = order.index(key) |
| 38 | done = !@import.failed? && idx && idx < current_idx |
| 39 | active = @import.status == key %> |
| 40 | <div class="flex items-center gap-3 px-4 py-3"> |
| 41 | <% if done || (@import.done? && key == "done") %> |
| 42 | <svg class="w-4 h-4 text-green-400" viewBox="0 0 16 16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L1.72 8.84a.75.75 0 1 1 1.06-1.06l3.22 3.22 6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg> |
| 43 | <% elsif active && !@import.terminal? %> |
| 44 | <svg class="w-4 h-4 text-amber-400 animate-spin" viewBox="0 0 24 24" fill="none"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.4 0 0 5.4 0 12h4z"></path></svg> |
| 45 | <% else %> |
| 46 | <span class="w-4 h-4 rounded-full border border-surface-500 inline-block"></span> |
| 47 | <% end %> |
| 48 | <span class="text-sm <%= done || active ? 'text-gray-100' : 'text-gray-500' %>"><%= label %></span> |
| 49 | </div> |
| 50 | <% end %> |
| 51 | </div> |
| 52 | |
| 53 | <% if @import.failed? %> |
| 54 | <div class="border border-red-800/40 bg-red-900/20 rounded px-4 py-3 mt-6"> |
| 55 | <p class="text-sm font-medium text-red-300 mb-1">Import failed</p> |
| 56 | <p class="text-sm text-red-400"><%= @import.error_message %></p> |
| 57 | <div class="mt-3"> |
| 58 | <%= button_to "Retry import", retry_import_path(@import), method: :post, class: "btn-secondary cursor-pointer" %> |
| 59 | </div> |
| 60 | </div> |
| 61 | <% end %> |
| 62 | |
| 63 | <% if @import.done? && @import.repository %> |
| 64 | <div class="mt-6 space-y-3"> |
| 65 | <div class="flex items-center gap-3"> |
| 66 | <%= link_to "View repository", repository_path(@import.user.username, @import.repository.name), class: "btn-primary" %> |
| 67 | <% if @import.mirror? %> |
| 68 | <span class="badge-gray">Read-only mirror</span> |
| 69 | <% end %> |
| 70 | </div> |
| 71 | <% if @import.lfs_detected %> |
| 72 | <p class="text-xs <%= @import.lfs_skipped ? 'text-amber-400' : 'text-gray-400' %>"> |
| 73 | <% if @import.lfs_skipped %> |
| 74 | Git LFS was detected but its large objects were <strong>not fetched</strong> (LFS unavailable on this server). |
| 75 | Pointer files and full history were imported. |
| 76 | <% else %> |
| 77 | Git LFS objects were fetched and imported. |
| 78 | <% end %> |
| 79 | </p> |
| 80 | <% end %> |
| 81 | <p class="text-xs text-gray-500">Issues, pull requests, and releases were not imported.</p> |
| 82 | </div> |
| 83 | <% end %> |
| 84 | </div> |