web/src/shared/components/annotator/links-layer.tsx (101 lines of code) (raw):
// temporary_disabled_rules
/* eslint-disable @typescript-eslint/no-unused-vars, react-hooks/exhaustive-deps */
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Annotation } from './typings';
import { Link } from '../../../api/typings';
import { useTaskAnnotatorContext } from '../../../connectors/task-annotator-connector/task-annotator-context';
import { getPointsForLinks, PointSet } from './utils/get-points-for-link';
import { LinkAnnotation } from './components/link-annotation';
import { linksOffsets } from 'shared/constants/annotations';
interface LinksLayerProps {
scale: number;
pageNum: number;
annotations: Annotation[];
}
export const LinksLayer = ({ annotations, pageNum, scale }: LinksLayerProps) => {
const { onLinkDeleted, onSplitLinkSelected, categories } = useTaskAnnotatorContext();
const [pointSets, setPointSets] = useState<PointSet[]>([]);
const [linksSets, setLinksSets] = useState<PointSet[]>([]);
const annotationsById = useMemo(
() =>
annotations.reduce((acc: Record<string, Annotation>, annotation) => {
acc[annotation.id] = annotation;
return acc;
}, {}),
[annotations]
);
const onDeleteLink = useCallback(
(pageNum: number, annotationId: string | number, link: Link) => (e: Event) => {
e.stopPropagation();
onLinkDeleted(pageNum, annotationId, link);
},
[onLinkDeleted]
);
const onLinkSelect = useCallback(
(from: string | number, link: Link, annotations: Annotation[]) => () => {
onSplitLinkSelected(from, link, annotations);
},
[onSplitLinkSelected]
);
const addXBoundtoPointSet = (points: any[]) => {
let k = 0;
const func = (points: any[]) => {
return points.map((set) => {
if (k > linksOffsets.length - 1) {
k = 0;
}
const obj = {
xBound: linksOffsets[k],
...set
};
++k;
return obj;
});
};
return func(points);
};
useEffect(() => {
const newPointSets: PointSet[] = [];
for (let ann of annotations) {
if (!ann.links?.length) continue;
newPointSets.push(
...getPointsForLinks(
ann.id,
ann.boundType,
ann.links,
pageNum,
annotationsById,
categories,
ann.color
)
);
}
setPointSets(newPointSets);
}, [annotations, pageNum, categories, scale]);
useEffect(() => {
if (pointSets) {
const newPointSets = addXBoundtoPointSet(pointSets);
setLinksSets(newPointSets);
}
}, [pointSets]);
return (
<div>
{linksSets.map(
({ from, start, finish, category, type, link, color, xBound, annotationId }) => {
return (
<LinkAnnotation
key={`${from}${link.to}`}
pointStart={start}
pointFinish={finish}
category={category}
linkType={type}
reversed={finish.id === from}
onDeleteLink={onDeleteLink(pageNum, annotationId, link)}
onLinkSelect={onLinkSelect(from, link, annotations)}
color={color}
xBound={xBound}
/>
);
}
)}
</div>
);
};