Skip to content

Commit 6b80ba6

Browse files
author
anmarhindi
committed
Fixes: Extraction labels are added multiple times with hotkeys
1 parent a1c408e commit 6b80ba6

File tree

2 files changed

+64
-24
lines changed

2 files changed

+64
-24
lines changed

src/components/projects/projectId/labeling/sessionId/sub-components/LabelSelectionBox.tsx

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,74 @@ import { UserRole } from "@/src/types/shared/sidebar";
66
import { TOOLTIPS_DICT } from "@/src/util/tooltip-constants";
77
import { Tooltip } from "@nextui-org/react";
88
import { IconCirclePlus } from "@tabler/icons-react";
9-
import { Fragment, useEffect, useState } from "react";
9+
import { Fragment, useEffect, useState, useCallback } from "react";
1010
import { useSelector } from "react-redux";
1111

12+
const eventListenersMap = new Map();
13+
1214
export default function LabelSelectionBox(props: LabelSelectionBoxProps) {
1315
const user = useSelector(selectUser);
1416
const settings = useSelector(selectSettings);
1517

1618
const [newLabelDict, setNewLabelDict] = useState({});
1719
const [taskFilteredDict, setTaskFilteredDict] = useState({});
20+
const [currentLabelHotkeys, setCurrentLabelHotkeys] = useState<any>({});
21+
const [currentActiveTasks, setCurrentActiveTasks] = useState([]);
1822

1923
useEffect(() => {
20-
if (!props.labelHotkeys) return;
21-
document.addEventListener('keyup', handleKeyboardEvent);
22-
return () => {
23-
document.removeEventListener('keyup', handleKeyboardEvent);
24-
};
25-
}, [props.labelHotkeys, props.activeTasks]);
24+
if (props.activeTasks && props.activeTasks.length > 0) {
25+
setCurrentActiveTasks(props.activeTasks);
26+
}
27+
}, [props.activeTasks]);
28+
29+
useEffect(() => {
30+
let missingValues = 0;
31+
for (let key in props.labelHotkeys) {
32+
if (('taskId' in props.labelHotkeys[key] && 'labelId' in props.labelHotkeys[key]) === false) {
33+
missingValues++;
34+
}
35+
}
36+
37+
if (missingValues == 0) {
38+
setCurrentLabelHotkeys(props.labelHotkeys);
39+
}
40+
}, [currentActiveTasks]);
2641

27-
function handleKeyboardEvent(event) {
42+
const handleKeyboardEvent = useCallback((event) => {
2843
const labelSelection = document.getElementById('label-selection-box');
2944
if (!labelSelection || labelSelection.classList.contains('hidden')) return;
30-
for (const key in props.labelHotkeys) {
45+
for (const key in currentLabelHotkeys) {
3146
if (key == event.key) {
32-
const activeTasks = props.activeTasks.map(x => x.task);
33-
const task = activeTasks.find(t => t.id == props.labelHotkeys[key].taskId);
34-
props.addRla(task, props.labelHotkeys[key].labelId);
47+
const activeTasks = currentActiveTasks.map(x => x.task);
48+
const task = activeTasks.find(t => t.id == currentLabelHotkeys[key].taskId);
49+
props.addRla(task, currentLabelHotkeys[key].labelId);
3550
event.preventDefault();
3651
event.stopPropagation();
3752
return;
3853
}
3954
}
55+
}, [currentLabelHotkeys]);
56+
57+
useEffect(() => {
58+
addUniqueEventListener("handleKeyboardEventID", 'keyup', handleKeyboardEvent);
59+
return () => {
60+
removeAllEventListeners('keyup');
61+
};
62+
}, [handleKeyboardEvent]);
63+
64+
function addUniqueEventListener(id, eventType, handler) {
65+
removeAllEventListeners('keyup');
66+
document.addEventListener(eventType, handler);
67+
eventListenersMap.set(id, { eventType, listener: handler });
68+
}
69+
70+
function removeAllEventListeners(eventType) {
71+
for (let [id, handler] of eventListenersMap.entries()) {
72+
if (handler.eventType === eventType) {
73+
document.removeEventListener(eventType, handler.listener);
74+
eventListenersMap.delete(id);
75+
}
76+
}
4077
}
4178

4279
useEffect(() => {

src/components/projects/projectId/labeling/sessionId/sub-components/LabelingSuiteLabeling.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -624,19 +624,22 @@ export default function LabelingSuiteLabeling() {
624624
</div>}
625625
</>}
626626
</div>
627-
<LabelSelectionBox activeTasks={activeTasks} position={position} labelLookup={labelLookup} labelAddButtonDisabledDict={labelAddButtonDisabledDict}
628-
addRla={(task, labelId) => {
629-
const tokenLookupCopy = jsonCopy(tokenLookup);
630-
if (saveTokenData && tokenLookupCopy[saveTokenData.attributeIdStart]) {
631-
for (const token of tokenLookupCopy[saveTokenData.attributeIdStart]?.token) {
632-
token.selected = token.idx >= saveTokenData.tokenStart && token.idx <= saveTokenData.tokenEnd;
627+
{activeTasks && activeTasks.length > 0 ? (
628+
<LabelSelectionBox activeTasks={activeTasks} position={position} labelLookup={labelLookup} labelAddButtonDisabledDict={labelAddButtonDisabledDict}
629+
addRla={(task, labelId) => {
630+
const tokenLookupCopy = jsonCopy(tokenLookup);
631+
if (saveTokenData && tokenLookupCopy[saveTokenData.attributeIdStart]) {
632+
for (const token of tokenLookupCopy[saveTokenData.attributeIdStart]?.token) {
633+
token.selected = token.idx >= saveTokenData.tokenStart && token.idx <= saveTokenData.tokenEnd;
634+
}
633635
}
634-
}
635-
addRla(task, labelId, tokenLookupCopy);
636-
}}
637-
addNewLabelToTask={(newLabel, task) => addNewLabelToTask(newLabel, task)}
638-
checkLabelVisibleInSearch={(newLabel, task) => checkLabelVisibleInSearch(labelLookup, newLabel, task)}
639-
labelHotkeys={labelHotkeys} />
636+
addRla(task, labelId, tokenLookupCopy);
637+
}}
638+
addNewLabelToTask={(newLabel, task) => addNewLabelToTask(newLabel, task)}
639+
checkLabelVisibleInSearch={(newLabel, task) => checkLabelVisibleInSearch(labelLookup, newLabel, task)}
640+
labelHotkeys={labelHotkeys}
641+
/>)
642+
: null}
640643
</div>}
641644
</Fragment>))}
642645
</Fragment>))}

0 commit comments

Comments
 (0)