From 4d5d76fe8fe4b9dd3fddf8b15205f782becd8359 Mon Sep 17 00:00:00 2001 From: Sara Date: Tue, 12 Dec 2023 11:36:40 +0100 Subject: [PATCH] fix selection (for good?) --- .../correct/participantList.tsx | 64 +++++++++++++++---- .../[transcriptId]/correct/topicPlayer.tsx | 1 + .../[transcriptId]/correct/topicWords.tsx | 63 +++++++++++++----- 3 files changed, 98 insertions(+), 30 deletions(-) diff --git a/www/app/[domain]/transcripts/[transcriptId]/correct/participantList.tsx b/www/app/[domain]/transcripts/[transcriptId]/correct/participantList.tsx index 807d2842..54f34603 100644 --- a/www/app/[domain]/transcripts/[transcriptId]/correct/participantList.tsx +++ b/www/app/[domain]/transcripts/[transcriptId]/correct/participantList.tsx @@ -4,7 +4,6 @@ import { useEffect, useRef, useState } from "react"; import { Participant } from "../../../../api"; import getApi from "../../../../lib/getApi"; import { UseParticipants } from "../../useParticipants"; -import { unescapeLeadingUnderscores } from "typescript"; type ParticipantList = { participants: UseParticipants; @@ -27,6 +26,7 @@ const ParticipantList = ({ const [participantInput, setParticipantInput] = useState(""); const inputRef = useRef(null); const [selectedSpeaker, setSelectedSpeaker] = stateSelectedSpeaker; + const [selectedParticipant, setSelectedParticipant] = useState(); const [action, setAction] = useState< "Create" | "Create to rename" | "Create and assign" | "Rename" | null >(null); @@ -47,9 +47,11 @@ const ParticipantList = ({ ); if (participant) { setParticipantInput(participant.name); + setSelectedParticipant(participant); inputRef.current?.focus(); setAction("Rename"); - } else { + } else if (!selectedParticipant) { + setSelectedParticipant(undefined); setParticipantInput(""); inputRef.current?.focus(); setAction("Create to rename"); @@ -59,6 +61,10 @@ const ParticipantList = ({ setParticipantInput(""); inputRef.current?.focus(); setAction("Create and assign"); + setSelectedParticipant(undefined); + } + if (!selectedTime && !selectedSpeaker) { + setAction(null); } } }, [selectedTime, selectedSpeaker]); @@ -78,6 +84,12 @@ const ParticipantList = ({ setOneMatch(undefined); } } + if (participantInput && !action) { + setAction("Create"); + } + if (!participantInput) { + setAction(null); + } }, [participantInput]); useEffect(() => { @@ -88,11 +100,15 @@ const ParticipantList = ({ setOneMatch(undefined); setParticipantInput(""); } + } else if (e.key === "Enter") { + doAction(); } }; }); - const doAction = (e) => { + const doAction = (e?) => { + e?.preventDefault(); + e?.stopPropagation(); if (!participants.response) return; if (action == "Rename") { const participant = participants.response.find( @@ -124,6 +140,7 @@ const ParticipantList = ({ }) .then(() => { participants.refetch(); + setParticipantInput(""); }); } else if (action == "Create and assign") { setLoading(true); @@ -138,11 +155,22 @@ const ParticipantList = ({ .then((participant) => { assignTo(participant)(); participants.refetch(); + setParticipantInput(""); + }); + } else if (action == "Create") { + setLoading(true); + api + ?.v1TranscriptAddParticipant({ + createParticipant: { + name: participantInput, + }, + transcriptId, + }) + .then(() => { + participants.refetch(); + setParticipantInput(""); }); } - e.preventDefault(); - console.log(e); - console.log(action); }; const deleteParticipant = (participantId) => () => { @@ -162,6 +190,7 @@ const ParticipantList = ({ (participant) => (e?: React.MouseEvent) => { e?.preventDefault(); e?.stopPropagation(); + // fix participant that doesnt have a speaker (wait API) if (selectedTime?.start == undefined || selectedTime?.end == undefined) return; api @@ -179,22 +208,29 @@ const ParticipantList = ({ }; const selectParticipant = (participant) => (e) => { - console.log(participant, e); + setSelectedParticipant(participant); setSelectedSpeaker(participant.speaker); + setAction("Rename"); + setParticipantInput(participant.name); }; return ( <> -
+
setParticipantInput(e.target.value)} value={participantInput} /> - - + {action && ( + + )} +
{participants.loading && ( { useState<() => void>(); //TODO shortcuts + // TODO if selection changes while playing, don't play useEffect(() => { setEndTopicCallback( diff --git a/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx b/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx index 4806f102..a7e2a587 100644 --- a/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx +++ b/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx @@ -12,7 +12,7 @@ type Word = { type WordBySpeaker = { speaker: number; words: Word[] }[]; -// TODO shortcuts +// TODO shortcuts ? // TODO fix key (using indexes might act up, not sure as we don't re-order per say) type TopicWordsProps = { @@ -63,6 +63,25 @@ const topicWords = ({ } }, [topicWithWords.response]); + const getStartTimeFromFirstNode = (node, offset, reverse) => { + // if the first element is a word + return node.parentElement?.dataset["start"] + ? // but after of the word (like on the blank space right of the word) + node.textContent?.length == offset + ? // if next element is a word, we need the start of it + (node.parentElement?.nextElementSibling as any)?.dataset?.["start"] || + // otherwise we get the start of the first word of the next paragraph + ( + node.parentElement?.parentElement?.nextElementSibling + ?.childNodes[1] as any + )?.dataset?.["start"] || + (reverse ? 0 : 99) + : // otherwise it's just somewhere in the word and we get the start of the word + node.parentElement?.dataset["start"] + : // otherwise selection start is on a name and we get the start of the next word + (node.parentElement?.nextElementSibling as any)?.dataset["start"]; + }; + const onMouseUp = (e) => { let selection = window.getSelection(); if ( @@ -102,35 +121,47 @@ const topicWords = ({ return; } - const anchorStart = anchorIsWord - ? anchorNode.parentElement?.dataset["start"] - : (selection.anchorNode.parentElement?.nextElementSibling as any) - ?.dataset["start"]; + const anchorStart = getStartTimeFromFirstNode( + anchorNode, + selection.anchorOffset, + false, + ); + // if selection end on a word, we get the end time from the span that contains it const focusEnd = selection.focusNode.parentElement?.dataset["end"] || + // otherwise it was a name and we get the end of the last word of the previous paragraph ( selection.focusNode.parentElement?.parentElement ?.previousElementSibling?.lastElementChild as any - )?.dataset["end"]; + )?.dataset["end"] || + 0; + const reverse = parseFloat(anchorStart) > parseFloat(focusEnd); if (!reverse) { - setSelectedTime({ start: anchorStart, end: focusEnd }); + setSelectedTime({ + start: parseFloat(anchorStart), + end: parseFloat(focusEnd), + }); console.log("setting right"); } else { - const anchorEnd = anchorIsWord - ? anchorNode.parentElement?.dataset["end"] - : (selection.anchorNode.parentElement?.nextElementSibling as any) - ?.dataset["end"]; - const focusStart = - selection.focusNode.parentElement?.dataset["start"] || + const anchorEnd = + anchorNode.parentElement?.dataset["end"] || ( - selection.focusNode.parentElement?.parentElement + selection.anchorNode.parentElement?.parentElement ?.previousElementSibling?.lastElementChild as any - )?.dataset["start"]; + )?.dataset["end"]; + + const focusStart = getStartTimeFromFirstNode( + focusNode, + selection.focusOffset, + true, + ); + setSelectedTime({ start: focusStart, end: anchorEnd }); console.log("setting reverse"); } + setSelectedSpeaker(); selection.empty(); } @@ -147,7 +178,7 @@ const topicWords = ({ if (!topicWithWords.loading && wordsBySpeaker && participants.response) { return ( -
console.log(e)}> +
{wordsBySpeaker?.map((speakerWithWords, index) => (