Working fairly well

Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
James Ketr 2023-01-28 21:33:49 -08:00
parent e5a55de73c
commit a71fb177e9
4 changed files with 64 additions and 39 deletions

View File

@ -19,12 +19,19 @@ div {
height: 100%; height: 100%;
} }
.Resizer { .Explorer .Resizer {
width: 0.5rem; width: 0.5rem;
background-color: #ccc; background-color: #ccc;
border: 1px solid black; border: 1px solid black;
} }
.ExplorerVertical .Resizer {
height: 0.5rem;
width: 100%;
background-color: #ccc;
border: 1px solid black;
}
.Explorer { .Explorer {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -35,6 +42,16 @@ div {
flex-grow: 1; flex-grow: 1;
} }
.ExplorerVertical {
display: flex;
flex-direction: column;
justify-self: stretch;
align-self: stretch;
width: 100%;
height: auto !important;
flex-grow: 1;
}
.Actions { .Actions {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -48,7 +65,6 @@ div {
.Identities { .Identities {
display: grid; display: grid;
user-select: none; user-select: none;
overflow-y: scroll;
overflow-x: clip; overflow-x: clip;
width: 100%; width: 100%;
max-height: 100%; /* scroll if too large */ max-height: 100%; /* scroll if too large */
@ -61,6 +77,7 @@ div {
.Identities { .Identities {
grid-template-columns: repeat(auto-fill, minmax(4.25rem, auto)); grid-template-columns: repeat(auto-fill, minmax(4.25rem, auto));
overflow-y: scroll;
} }
.Face { .Face {
@ -81,18 +98,26 @@ div {
flex-direction: column; flex-direction: column;
} }
.Viewer {
display: flex;
flex-direction: column;
position: relative;
height: 100%;
}
.PhotoPanel { .PhotoPanel {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
max-height: 100%; max-height: 100%;
overflow-y: auto;
}
.PhotoPanel .FaceInfo {
padding: 0.25rem;
background-color: #444;
color: white;
margin-top: 0.25rem;
}
.PhotoPanel .ImageInfo {
padding: 0.25rem;
background-color: #222;
color: white;
margin-top: 0.25rem;
} }
.Guess { .Guess {
@ -130,19 +155,7 @@ button {
.Photo { .Photo {
display: flex; display: flex;
position: relative; position: relative;
} flex-direction: column;
.PhotoPanel .FaceInfo {
padding: 0.25rem;
background-color: #444;
color: white;
margin-top: 0.25rem;}
.PhotoPanel .ImageInfo {
padding: 0.25rem;
background-color: #222;
color: white;
margin-top: 0.25rem;
} }
.PhotoFaces .UnknownFace, .PhotoFaces .UnknownFace,

View File

@ -118,7 +118,6 @@ const Photo = ({ photoId, onFaceClick }: any) => {
} }
}, [setDimensions, dimensions]); }, [setDimensions, dimensions]);
useEffect(() => { useEffect(() => {
let timer = setInterval(() => checkResize(), 250); let timer = setInterval(() => checkResize(), 250);
return () => { clearInterval(timer); } return () => { clearInterval(timer); }
@ -152,6 +151,9 @@ const Photo = ({ photoId, onFaceClick }: any) => {
}); });
await res.json(); await res.json();
setPhotoSelected([]); setPhotoSelected([]);
photo.faces = photo.faces.filter(
face => photoSelected.findIndex(x => x.faceId === face.faceId) === -1
);
setPhoto({...photo}); setPhoto({...photo});
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -196,7 +198,8 @@ const Photo = ({ photoId, onFaceClick }: any) => {
return <></> return <></>
} }
return (<div className="PhotoPanel"> return (
<div className="PhotoPanel">
<div className="Photo" ref={ref}> <div className="Photo" ref={ref}>
<img <img
alt={photo.filename} alt={photo.filename}
@ -217,7 +220,9 @@ const Photo = ({ photoId, onFaceClick }: any) => {
<Button onClick={selectAll}>Select All</Button> <Button onClick={selectAll}>Select All</Button>
<Button onClick={clearSelection}>Select None</Button> <Button onClick={clearSelection}>Select None</Button>
</div> </div>
{ photoSelected.length !== 0 && <div>Selected faces (CTRL-CLICK to remove):</div> } { photoSelected.length !== 0 && <div style={{ display: 'flex' }}>
Selected faces (CTRL-CLICK to remove):
</div> }
<div className="PhotoFaces"> <div className="PhotoFaces">
{ photoSelected.map(face => { photoSelected.map(face =>
<Face <Face
@ -1046,10 +1051,13 @@ const App = () => {
</div> </div>
</Panel> </Panel>
<PanelResizeHandle className="Resizer"/> <PanelResizeHandle className="Resizer"/>
<Panel> <Panel><>
<div className="Viewer"> { image === 0 &&
{image === 0 && <div style={{ margin: '1rem' }}>Select image to view</div>} <div style={{ margin: '1rem' }}>Select image to view</div>
{image !== 0 && <Photo onFaceClick={onFaceClick} photoId={image}/> } }
{ image !== 0 &&
<Photo onFaceClick={onFaceClick} photoId={image}/>
}
{ guess !== undefined && guess.identity && <div { guess !== undefined && guess.identity && <div
className="Guess"> className="Guess">
<Face <Face
@ -1057,8 +1065,7 @@ const App = () => {
onFaceClick={guessOnFaceClick} onFaceClick={guessOnFaceClick}
title={`${guess.identity.displayName} (${guess.distance})`}/> title={`${guess.identity.displayName} (${guess.distance})`}/>
</div> } </div> }
</div> </></Panel>
</Panel>
<PanelResizeHandle className="Resizer" /> <PanelResizeHandle className="Resizer" />
<Panel defaultSize={8.5} minSize={8.5} className="IdentitiesList"> <Panel defaultSize={8.5} minSize={8.5} className="IdentitiesList">
{ !loaded && <div style={{ margin: '1rem' }}> { !loaded && <div style={{ margin: '1rem' }}>

View File

@ -448,6 +448,10 @@ router.put("/faces/add/:id", async (req, res) => {
/* Do not block on this call finishing -- update can occur /* Do not block on this call finishing -- update can occur
* in the background */ * in the background */
Promise.map([identity, ...tuples], (x, i) => { Promise.map([identity, ...tuples], (x, i) => {
if (x.identityId === null) {
/* Moving from the Unknown group */
return;
}
try { try {
updateIdentityFaces(x); updateIdentityFaces(x);
} catch (error) { } catch (error) {

View File

@ -1109,6 +1109,7 @@ router.get("/:id", async (req, res) => {
` `
SELECT faces.* FROM faces SELECT faces.* FROM faces
WHERE faces.photoId=:id WHERE faces.photoId=:id
AND faces.classifiedBy NOT IN ('not-a-face', 'forget' )
`, { `, {
replacements: { id }, replacements: { id },
type: photoDB.Sequelize.QueryTypes.SELECT type: photoDB.Sequelize.QueryTypes.SELECT