Face removal working
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
1ead088eb8
commit
0043480ff8
@ -56,6 +56,11 @@ div {
|
||||
border: 0.25rem solid transparent;
|
||||
}
|
||||
|
||||
.ClusterEditor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.Image .FaceBox {
|
||||
border: 1px solid red;
|
||||
/* border-radius: 0.25rem;*/
|
||||
|
@ -89,10 +89,10 @@ const Photo = ({ photoId }: any) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Face = ({ faceId, onClick, title }: any) => {
|
||||
const Face = ({ faceId, onClick, title, ...rest }: any) => {
|
||||
const idPath = String(faceId % 100).padStart(2, '0');
|
||||
return (
|
||||
<div onClick={(e) => { onClick(e, faceId) }}
|
||||
<div {...rest} onClick={(e) => { onClick(e, faceId) }}
|
||||
className='Face'>
|
||||
<div className='Image'
|
||||
style={{
|
||||
@ -105,26 +105,13 @@ const Face = ({ faceId, onClick, title }: any) => {
|
||||
};
|
||||
|
||||
type ClusterProps = {
|
||||
id: number,
|
||||
setImage(image: number): void
|
||||
identity: Identity,
|
||||
setImage(image: number): void,
|
||||
setSelected(selected: number[]): void,
|
||||
setIdentity(identity: Identity): void
|
||||
};
|
||||
|
||||
const Cluster = ({ id, setImage }: ClusterProps) => {
|
||||
const [identity, setIdentity] = useState<Identity | undefined>(undefined);
|
||||
const { loading, data } = useApi(
|
||||
`../api/v1/identities/${id}`
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
setIdentity(data[0] as Identity);
|
||||
} else {
|
||||
setIdentity(data as Identity);
|
||||
}
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const Cluster = ({ identity, setIdentity, setImage, setSelected }: ClusterProps) => {
|
||||
const relatedFacesJSX = useMemo(() => {
|
||||
const faceClicked = async (e: any, id: any) => {
|
||||
if (!identity) {
|
||||
@ -142,18 +129,25 @@ const Cluster = ({ id, setImage }: ClusterProps) => {
|
||||
return;
|
||||
}
|
||||
el.classList.toggle('Selected');
|
||||
const selected = [...el.parentElement
|
||||
.querySelectorAll('.Selected')]
|
||||
.map((face: any) => face.getAttribute('data-face-id'));
|
||||
setSelected(selected);
|
||||
console.log(face);
|
||||
}
|
||||
if (identity === undefined) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return identity.relatedFaces.map(face =>
|
||||
<Face key={face.faceId}
|
||||
<Face
|
||||
data-face-id={face.faceId}
|
||||
key={face.faceId}
|
||||
faceId={face.faceId}
|
||||
onClick={faceClicked}
|
||||
title={face.distance}/>
|
||||
);
|
||||
}, [identity, setImage]);
|
||||
}, [identity, setImage, setSelected]);
|
||||
|
||||
const lastNameChanged = (e: any) => {
|
||||
setIdentity(Object.assign(
|
||||
@ -188,12 +182,6 @@ const Cluster = ({ id, setImage }: ClusterProps) => {
|
||||
));
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (<div className='Cluster'>
|
||||
{loading && `Loading ${id}...`}
|
||||
</div>);
|
||||
}
|
||||
|
||||
if (identity === undefined) {
|
||||
return (<div className='Cluster'>
|
||||
Select identity to load.
|
||||
@ -257,21 +245,23 @@ type Identity = {
|
||||
};
|
||||
|
||||
interface IdentitiesProps {
|
||||
setIdentity?(id: number): void,
|
||||
setIdentity(identity: Identity): void,
|
||||
identities: Identity[]
|
||||
};
|
||||
|
||||
const Identities = ({ identities, setIdentity } : IdentitiesProps) => {
|
||||
const identitiesJSX = useMemo(() => {
|
||||
const loadIdentity = (id: number): void => {
|
||||
if (setIdentity) {
|
||||
setIdentity(id)
|
||||
}
|
||||
const loadIdentity = async (id: number) => {
|
||||
const res = await window.fetch(`../api/v1/identities/${id}`);
|
||||
const data = await res.json();
|
||||
setIdentity(data[0]);
|
||||
};
|
||||
return identities.map((identity) => {
|
||||
|
||||
return identities.map((identity) => {
|
||||
const face = identity.relatedFaces[0];
|
||||
return (
|
||||
<Face key={face.faceId}
|
||||
data-face-id={face.faceId}
|
||||
faceId={face.faceId}
|
||||
onClick={() => loadIdentity(identity.id)}
|
||||
title={identity.displayName}/>
|
||||
@ -286,13 +276,22 @@ const Identities = ({ identities, setIdentity } : IdentitiesProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Button = ({ onClick, children }: any) => {
|
||||
return (
|
||||
<button type="button" onClick={onClick}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const App = () => {
|
||||
const [identities, setIdentities] = useState<Identity[]>([]);
|
||||
const [identity, setIdentity] = useState<number>(0);
|
||||
const [identity, setIdentity] = useState<any>(undefined);
|
||||
const [image, setImage] = useState<number>(0);
|
||||
const { loading, data } = useApi(
|
||||
'../api/v1/identities'
|
||||
);
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (data && data.length) {
|
||||
@ -300,17 +299,49 @@ const App = () => {
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const removeSelected = async () => {
|
||||
try {
|
||||
const res = await window.fetch(
|
||||
`../api/v1/identities/faces/remove/${identity.id}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ faces: selected })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
const pre = identity.relatedFaces.length;
|
||||
/* Remove all relatedFaces which are part of the set of removed
|
||||
* faces */
|
||||
identity.relatedFaces = identity.relatedFaces.filter(
|
||||
(face: FaceData) => data.faces.indexOf(face.faceId) === -1);
|
||||
if (pre !== identity.relatedFaces.length) {
|
||||
setIdentity({...identity})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<div className="Worksheet">
|
||||
<PanelGroup className="Explorer"
|
||||
autoSaveId="persistence" direction="horizontal">
|
||||
<Panel defaultSize={50}>
|
||||
<Panel defaultSize={50} className="ClusterEditor">
|
||||
{loading && <div style={{ margin: '1rem' }}>Loading...</div>}
|
||||
{!loading && identity !== 0 && <Cluster id={identity} {...{ setImage, }} />}
|
||||
{!loading && identity !== 0 &&
|
||||
<Cluster {...{
|
||||
identity,
|
||||
setIdentity,
|
||||
setImage,
|
||||
setSelected
|
||||
}} />}
|
||||
{!loading && identity === 0 && <div className="Cluster">
|
||||
Select identity to edit
|
||||
</div>}
|
||||
<div className="Actions">
|
||||
{ selected.length !== 0 && <Button onClick={removeSelected}>Remove</Button> }
|
||||
</div>
|
||||
</Panel>
|
||||
<PanelResizeHandle className="Resizer"/>
|
||||
<Panel>
|
||||
|
@ -172,6 +172,11 @@ function init() {
|
||||
key: 'id',
|
||||
}
|
||||
},
|
||||
|
||||
expertAssignment: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
|
||||
lastComparedId: {
|
||||
type: Sequelize.INTEGER,
|
||||
|
@ -11,6 +11,42 @@ require("../db/photos").then(function(db) {
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
router.put("/faces/remove/:id", (req, res) => {
|
||||
console.log(`PUT ${req.url}`)
|
||||
if (!req.user.maintainer) {
|
||||
console.warn(`${req.user.name} attempted to modify photos.`);
|
||||
return res.status(401).send({ message: "Unauthorized to modify photos." });
|
||||
}
|
||||
|
||||
const id = parseInt(req.params.id);
|
||||
if (id != req.params.id) {
|
||||
return res.status(400).send({ message: "Invalid identity id." });
|
||||
}
|
||||
|
||||
if (!Array.isArray(req.body.faces) || req.body.faces.length == 0) {
|
||||
return res.status(400).send({ message: "No faces supplied." });
|
||||
}
|
||||
|
||||
return photoDB.sequelize.query(
|
||||
"UPDATE faces SET identityId=null " +
|
||||
"WHERE id IN (:faceIds)", {
|
||||
replacements: {
|
||||
identityId: id,
|
||||
faceIds: req.body.faces
|
||||
}
|
||||
}).then(() => {
|
||||
const identity = {
|
||||
id: id,
|
||||
faces: req.body.faces
|
||||
};
|
||||
return res.status(200).json(identity);
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
return res.status(500).send({message: "Error processing request." });
|
||||
});
|
||||
});
|
||||
|
||||
router.put("/faces/add/:id", (req, res) => {
|
||||
if (!req.user.maintainer) {
|
||||
console.warn(`${req.user.name} attempted to modify photos.`);
|
||||
@ -182,6 +218,7 @@ router.get("/:id?", async (req, res) => {
|
||||
delete identity.descriptors;
|
||||
delete identity.relatedFaceIds;
|
||||
delete identity.relatedFacePhotoIds;
|
||||
delete identity.relatedFaceDescriptorIds;
|
||||
delete identity.relatedIdentityDescriptors;
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user