summaryrefslogtreecommitdiffstats
path: root/views/admin/people.erb
diff options
context:
space:
mode:
authorKen D'Ambrosio <ken@jots.org>2026-06-08 21:09:47 +0000
committerKen D'Ambrosio <ken@jots.org>2026-06-08 21:09:47 +0000
commit7f6325fe213ed46ff5479ffd34b0e212426d48f2 (patch)
tree46430a22dc791ce5c8018eeb7bce2c857fd17cd6 /views/admin/people.erb
parent00f63c03b7c5de68aea6a2305886bc1953a722b6 (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.erb31
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');