diff --git a/frontend/identities.html b/frontend/identities.html index 138d14d..27fd6f1 100755 --- a/frontend/identities.html +++ b/frontend/identities.html @@ -9,7 +9,7 @@ 3. Put a UI that let's the user pick from existing identities. 4. Select / Deselect all faces that match 5. "Match" to bind the faces to the identity -6 Create new Identity +6. Create new Identity */ @@ -53,6 +53,8 @@ function shuffle(array) { document.addEventListener("DOMContentLoaded", (event) => { loadFace(); + const newIdentity = document.getElementById("new-identity"); + newIdentity.appendChild(createNewIdenityEditor()); }); function loadFace(id) { @@ -71,36 +73,43 @@ function loadFace(id) { const editor = document.createElement("div"); editor.classList.add("editor"); editor.appendChild(createFace(face.id, face.photoId)); - for (let key in face) { - const row = document.createElement("div"), - left = document.createElement("div"); - row.classList.add("editor-row"); - left.classList.add("key"); - left.textContent = key; - - let right; - - if (key == "relatedFaces") { - right = document.createElement("div"); - right.classList.add("related-faces"); - for (let i = 0; i < face.relatedFaces.length && i < 20; i++) { - let relation = face.relatedFaces[i]; - const distance = document.createElement("div"), - facePhoto = createFace(relation.faceId, relation.photoId, true); - distance.classList.add("distance"); - distance.textContent = relation.distance.toFixed(2); - facePhoto.appendChild(distance); - right.appendChild(facePhoto); - } - } else { - right = document.createElement("input"); - right.value = face[key]; - } - - row.appendChild(left); - row.appendChild(right); - editor.appendChild(row); + let row = document.createElement("div"), + label = document.createElement("div"), + a = document.createElement("a"); + row.classList.add("editor-row"); + label.textContent = "View photo: "; + row.appendChild(label); + a.setAttribute("target", "photo-" + face.photoId); + a.href = "face-explorer.html?" + face.photoId; + a.textContent = "photo " + face.photoId; + row.appendChild(a); + editor.appendChild(row); + row = document.createElement("div"); + row.classList.add("editor-row"); + let message = "Related faces: ", + max = Math.min(face.relatedFaces.length, 9); + if (max > 0) { + message += face.relatedFaces.length + " related. Showing top " + max + ". (tap to deselect)"; + } else { + message += "No matches found."; } + row.textContent = message; + editor.appendChild(row); + + row = document.createElement("div"); + row.classList.add("editor-row"); + row.classList.add("related-faces"); + for (let i = 0; i < max; i++) { + let relation = face.relatedFaces[i]; + const distance = document.createElement("div"), + facePhoto = createFace(relation.faceId, relation.photoId, true); + distance.classList.add("distance"); + distance.textContent = relation.distance.toFixed(2); + facePhoto.appendChild(distance); + row.appendChild(facePhoto); + } + + editor.appendChild(row); faceEditorBlock.appendChild(editor); }); @@ -112,8 +121,6 @@ function getIdentities(id) { const search = id ? "?withScore=" + id : ""; window.fetch("api/v1/identities" + search).then(res => res.json()).then((identities) => { - identitiesBlock.appendChild(createNewIdenityEditor()); - identities.sort((a, b) => { if (a.lastName == b.lastName) { return a.firstName.localeCompare(b.firstName); @@ -163,15 +170,41 @@ function getIdentities(id) { }); div = document.createElement("div"); div.classList.add("face-block"); + let minDistance = { + distance: 1 + }; + for (let i = 0; i < identity.relatedFaces.length && i < 4; i++) { - const facePhoto = createFace(identity.relatedFaces[i].faceId, identity.relatedFaces[i].photoId), + const target = identity.relatedFaces[i]; + const facePhoto = createFace(target.faceId, target.photoId), distance = document.createElement("div"); + + if (target.distance < minDistance.distance) { + minDistance.distance = target.distance; + minDistance.photoId = target.photoId; + minDistance.faceId = target.faceId; + } distance.classList.add("distance"); - distance.textContent = identity.relatedFaces[i].distance.toFixed(2); + distance.textContent = target.distance.toFixed(2); facePhoto.appendChild(distance); div.appendChild(facePhoto); } + if (minDistance.distance < 0.4) { + const bestMatch = document.getElementById("best-match"); + const distance = document.createElement("div"), + facePhoto = createFace(minDistance.faceId, minDistance.photoId); + distance.classList.add("distance"); + distance.textContent = minDistance.distance.toFixed(2); + facePhoto.appendChild(distance); + + bestMatch.innerHTML = ""; + bestMatch.appendChild(facePhoto); + } else { + const bestMatch = document.getElementById("best-match"); + bestMatch.innerHTML = "No best guess for match."; + } + block.appendChild(div); identitiesBlock.appendChild(block); }); @@ -183,6 +216,11 @@ function createNewIdenityEditor() { block.classList.add("block"); const editor = document.createElement("div"); editor.classList.add("editor"); + + const button = document.createElement("button"); + button.textContent = "New Identity"; + editor.appendChild(button); + [ "lastName", "firstName", "middleName", "name" ].forEach((key) => { const row = document.createElement("div"), left = document.createElement("div"), @@ -194,8 +232,7 @@ function createNewIdenityEditor() { row.appendChild(right); editor.appendChild(row); }); - const button = document.createElement("button"); - button.textContent = "New Identity"; + button.addEventListener("click", (event) => { const rows = event.currentTarget.parentElement.querySelectorAll(".editor-row"), object = {}; @@ -222,7 +259,6 @@ function createNewIdenityEditor() { loadFace(parseInt(face.getAttribute("face-id"))); }); }); - editor.appendChild(button); block.appendChild(editor); return block; @@ -243,6 +279,19 @@ body { cursor: pointer; } +#face-editor { + max-width: calc(128px * 4); +} + +#face-editor .related-faces { + display: flex; + flex-wrap: wrap; +} + +#new-identity { + padding: 0.5em; +} + #identities { display: flex; flex-wrap: wrap; @@ -290,6 +339,7 @@ body { height: 128px; background-size: contain; background-position: center center; + background-repeat: no-repeat; display: inline-block; border: 1px solid black; margin: 0.5em; @@ -323,6 +373,12 @@ body {
- - +