diff options
| author | Ken D'Ambrosio <ken@jots.org> | 2026-06-08 21:09:47 +0000 |
|---|---|---|
| committer | Ken D'Ambrosio <ken@jots.org> | 2026-06-08 21:09:47 +0000 |
| commit | 7f6325fe213ed46ff5479ffd34b0e212426d48f2 (patch) | |
| tree | 46430a22dc791ce5c8018eeb7bce2c857fd17cd6 /views/admin/people.erb | |
| parent | 00f63c03b7c5de68aea6a2305886bc1953a722b6 (diff) | |
Add people cluster detail page with face move/merge and hover preview
Each cluster in /admin/people now links to a detail page showing all
faces in a grid. From there you can rename the cluster, move individual
faces to another named person (or spin off a new cluster), or merge the
entire cluster into another. Hovering any face crop shows the original
full photo for context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'views/admin/people.erb')
| -rw-r--r-- | views/admin/people.erb | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/views/admin/people.erb b/views/admin/people.erb index 6b7a4d0..c17e847 100644 --- a/views/admin/people.erb +++ b/views/admin/people.erb @@ -37,10 +37,14 @@ <div class="face-samples"> <% c[:samples].each do |s| %> <img src="/face/<%= ERB::Util.html_escape(s[:rel]) %>?box=<%= ERB::Util.html_escape(s[:box].join(',')) %>" - width="72" height="72" loading="lazy"> + width="72" height="72" loading="lazy" + class="face-list-thumb" + data-thumb="/thumb/<%= ERB::Util.html_escape(s[:rel]) %>"> <% end %> <% if c[:count] > c[:samples].length %> - <span class="face-more">+<%= c[:count] - c[:samples].length %></span> + <a href="/admin/people/<%= ERB::Util.url_encode(c[:uuid]) %>" class="face-more"> + +<%= c[:count] - c[:samples].length %> more + </a> <% end %> </div> <div class="people-admin-meta"> @@ -54,6 +58,7 @@ <a href="/people/<%= ERB::Util.url_encode(c[:slug]) %>" class="btn btn-sm" target="_blank">↗</a> <% end %> </form> + <a href="/admin/people/<%= ERB::Util.url_encode(c[:uuid]) %>" class="btn btn-sm">View all</a> </div> </div> <% end %> @@ -66,7 +71,29 @@ <% end %> </div> +<div id="face-hover-preview"><img alt=""></div> + <script> +(function () { + const preview = document.getElementById('face-hover-preview'); + const pimg = preview.querySelector('img'); + function reposition(e) { + const pw = 312, ph = 312; + let x = e.clientX + 18, y = e.clientY + 18; + if (x + pw > window.innerWidth) x = e.clientX - pw - 8; + if (y + ph > window.innerHeight) y = e.clientY - ph - 8; + preview.style.left = x + 'px'; preview.style.top = y + 'px'; + } + document.querySelectorAll('.face-list-thumb').forEach(function (img) { + img.style.cursor = 'zoom-in'; + img.addEventListener('mouseenter', function (e) { + pimg.src = img.dataset.thumb; preview.style.display = 'block'; reposition(e); + }); + img.addEventListener('mousemove', reposition); + img.addEventListener('mouseleave', function () { preview.style.display = 'none'; }); + }); +})(); + async function startRecluster() { const btn = document.getElementById('cluster-btn'); const panel = document.getElementById('cluster-panel'); |
