main
erb 155 lines 7.97 KB
Raw
1 <% content_for :title, "Import from GitHub" %>
2
3 <div class="max-w-3xl mx-auto px-4 sm:px-6 py-10">
4 <h1 class="text-xl font-semibold text-gray-100 mb-1">Import a repository</h1>
5 <p class="text-sm text-gray-400 mb-8">
6 Bring a repo to siGit with its full history — every branch and tag, no rewrites.
7 </p>
8
9 <%# ── MIGRATE vs MIRROR explainer ─────────────────────────────────────── %>
10 <div class="grid grid-cols-1 sm:grid-cols-2 gap-3 mb-8">
11 <div class="card px-4 py-3">
12 <div class="text-sm font-medium text-gray-100 mb-0.5">Migrate</div>
13 <p class="text-xs text-gray-400">Copy the repo once. siGit becomes the source of truth and you can push here.</p>
14 </div>
15 <div class="card px-4 py-3">
16 <div class="text-sm font-medium text-gray-100 mb-0.5">Mirror <span class="badge-gray ml-1">risk-free</span></div>
17 <p class="text-xs text-gray-400">Keep GitHub as upstream. siGit auto-syncs and stays read-only until you detach.</p>
18 </div>
19 </div>
20
21 <%# ── GitHub section ───────────────────────────────────────────────────── %>
22 <section class="mb-10">
23 <div class="flex items-center justify-between mb-3">
24 <h2 class="text-base font-semibold text-gray-100">From GitHub</h2>
25 <% if @connection %>
26 <div class="flex items-center gap-3 text-xs text-gray-400">
27 <span>Connected<%= " as @#{@connection.github_login}" if @connection.github_login %></span>
28 <%= button_to "Disconnect", github_import_disconnect_path, method: :delete,
29 class: "text-red-400 hover:underline", form: { class: "inline" } %>
30 </div>
31 <% end %>
32 </div>
33
34 <% unless GithubOauthService.configured? %>
35 <div class="card px-4 py-3 text-sm text-amber-300 bg-amber-900/10 border-amber-800/40">
36 GitHub import isn't configured on this server. You can still import any public repo by URL below.
37 </div>
38 <% end %>
39
40 <% if @connection.nil? %>
41 <div class="card px-6 py-8 text-center">
42 <p class="text-sm text-gray-400 mb-4">Connect GitHub to see and pick your repositories.</p>
43 <div class="flex flex-col sm:flex-row items-center justify-center gap-3">
44 <%= link_to github_import_connect_path, class: "btn-primary" do %>
45 Connect GitHub (incl. private)
46 <% end %>
47 <%= link_to github_import_connect_path(visibility: "public"), class: "btn-ghost" do %>
48 Public repos only
49 <% end %>
50 </div>
51 <p class="text-xs text-gray-500 mt-3">We request the narrowest scope for what you choose. Your token is stored encrypted and never shown.</p>
52 </div>
53 <% elsif @github_repos.nil? %>
54 <div class="card px-4 py-3 text-sm text-amber-300">
55 Couldn't load your GitHub repositories right now (rate limit or a hiccup). Try again shortly.
56 </div>
57 <% elsif @github_repos.empty? %>
58 <div class="card px-4 py-3 text-sm text-gray-400">No repositories found on your GitHub account.</div>
59 <% else %>
60 <%= form_with url: imports_path, method: :post, data: { turbo: false }, class: "space-y-4" do %>
61 <input type="hidden" name="source" value="github">
62
63 <div class="flex items-center gap-4">
64 <span class="form-label mb-0">Mode</span>
65 <label class="flex items-center gap-1.5 text-sm text-gray-200">
66 <input type="radio" name="mode" value="migrate" checked> Migrate
67 </label>
68 <label class="flex items-center gap-1.5 text-sm text-gray-200">
69 <input type="radio" name="mode" value="mirror"> Mirror
70 </label>
71 </div>
72
73 <div class="card divide-y divide-surface-600 max-h-96 overflow-y-auto">
74 <% @github_repos.each do |repo| %>
75 <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-surface-600 cursor-pointer">
76 <input type="checkbox" name="repos[]" value="<%= repo[:full_name] %>" class="shrink-0">
77 <div class="min-w-0 flex-1">
78 <div class="flex items-center gap-2">
79 <span class="text-sm font-medium text-gray-100 truncate"><%= repo[:full_name] %></span>
80 <% if repo[:private] %><span class="badge-gray">Private</span><% end %>
81 <% if repo[:archived] %><span class="badge-gray">Archived</span><% end %>
82 </div>
83 <% if repo[:description].present? %>
84 <p class="text-xs text-gray-400 truncate"><%= repo[:description] %></p>
85 <% end %>
86 </div>
87 <div class="shrink-0 text-right text-xs text-gray-500">
88 <div><%= number_to_human_size((repo[:size_kb] || 0) * 1024) %></div>
89 <% if repo[:pushed_at].present? %>
90 <div>pushed <%= time_ago_in_words(Time.parse(repo[:pushed_at])) rescue "—" %> ago</div>
91 <% end %>
92 </div>
93 </label>
94 <% end %>
95 </div>
96
97 <div class="flex items-center gap-3">
98 <%= submit_tag "Import selected", class: "btn-primary cursor-pointer" %>
99 <span class="text-xs text-gray-500">Select multiple to queue a bulk import.</span>
100 </div>
101 <% end %>
102 <% end %>
103 </section>
104
105 <%# ── Import by URL ────────────────────────────────────────────────────── %>
106 <section class="mb-10">
107 <h2 class="text-base font-semibold text-gray-100 mb-3">Or import by URL</h2>
108 <%= form_with url: imports_path, method: :post, data: { turbo: false }, class: "space-y-4" do %>
109 <input type="hidden" name="source" value="url">
110 <div>
111 <label class="form-label">Public git URL</label>
112 <input type="url" name="url" class="form-input" placeholder="https://github.com/owner/repo.git" required>
113 <p class="text-xs text-gray-500 mt-1">Any public http(s) git URL. Private URLs need the GitHub connection above.</p>
114 </div>
115 <div class="flex items-end gap-3">
116 <div class="flex-1">
117 <label class="form-label">Repository name <span class="text-gray-500">(optional)</span></label>
118 <input type="text" name="name" class="form-input" placeholder="derived from the URL">
119 </div>
120 <div class="flex items-center gap-3 pb-2.5">
121 <label class="flex items-center gap-1.5 text-sm text-gray-200">
122 <input type="radio" name="mode" value="migrate" checked> Migrate
123 </label>
124 <label class="flex items-center gap-1.5 text-sm text-gray-200">
125 <input type="radio" name="mode" value="mirror"> Mirror
126 </label>
127 </div>
128 </div>
129 <%= submit_tag "Import from URL", class: "btn-secondary cursor-pointer" %>
130 <% end %>
131 </section>
132
133 <p class="text-xs text-gray-500 mb-8">
134 Issues, pull requests, wikis, and releases are <strong>not imported</strong> in this version — only the
135 git repository, its history, branches, and tags.
136 </p>
137
138 <%# ── Recent imports ───────────────────────────────────────────────────── %>
139 <% if @recent_imports.present? %>
140 <section>
141 <h2 class="text-base font-semibold text-gray-100 mb-3">Recent imports</h2>
142 <div class="card divide-y divide-surface-600">
143 <% @recent_imports.each do |import| %>
144 <%= link_to import_path(import), class: "flex items-center justify-between px-4 py-2.5 hover:bg-surface-600" do %>
145 <div class="min-w-0">
146 <span class="text-sm text-gray-100"><%= import.target_name %></span>
147 <span class="text-xs text-gray-500 ml-2"><%= import.mirror? ? "mirror" : "migrate" %></span>
148 </div>
149 <%= render "imports/status_badge", import: import %>
150 <% end %>
151 <% end %>
152 </div>
153 </section>
154 <% end %>
155 </div>