switch to chackra, bugfixes

This commit is contained in:
Sara
2023-12-21 13:56:37 +01:00
parent 5535f20fab
commit 89dc6ebb01
8 changed files with 384 additions and 201 deletions

View File

@@ -41,6 +41,9 @@ async def transcript_get_participants(
transcript_id, user_id=user_id transcript_id, user_id=user_id
) )
if transcript.participants is None:
return []
return [ return [
Participant.model_validate(participant) Participant.model_validate(participant)
for participant in transcript.participants for participant in transcript.participants
@@ -59,7 +62,7 @@ async def transcript_add_participant(
) )
# ensure the speaker is unique # ensure the speaker is unique
if participant.speaker is not None: if participant.speaker is not None and transcript.participants is not None:
for p in transcript.participants: for p in transcript.participants:
if p.speaker == participant.speaker: if p.speaker == participant.speaker:
raise HTTPException( raise HTTPException(

View File

@@ -91,7 +91,7 @@ export default async function RootLayout({ children, params }: LayoutProps) {
<Providers> <Providers>
<div <div
id="container" id="container"
className="items-center h-[100svh] w-[100svw] p-2 md:p-4 grid grid-rows-layout gap-2 md:gap-4" className="items-center h-[100svh] w-[100svw] p-2 md:p-4 grid grid-rows-layout-topbar gap-2 md:gap-4"
> >
<header className="flex justify-between items-center w-full"> <header className="flex justify-between items-center w-full">
{/* Logo on the left */} {/* Logo on the left */}

View File

@@ -1,5 +1,5 @@
"use client"; "use client";
import { useEffect, useState } from "react"; import { useState } from "react";
import TopicHeader from "./topicHeader"; import TopicHeader from "./topicHeader";
import TopicWords from "./topicWords"; import TopicWords from "./topicWords";
import TopicPlayer from "./topicPlayer"; import TopicPlayer from "./topicPlayer";
@@ -12,6 +12,7 @@ import getApi from "../../../../lib/getApi";
import useTranscript from "../../useTranscript"; import useTranscript from "../../useTranscript";
import { useError } from "../../../../(errors)/errorContext"; import { useError } from "../../../../(errors)/errorContext";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { Box, Grid } from "@chakra-ui/react";
export type TranscriptCorrect = { export type TranscriptCorrect = {
params: { params: {
@@ -50,36 +51,57 @@ export default function TranscriptCorrect({
}; };
return ( return (
<div className="h-full grid grid-cols-2 gap-4"> <Grid
<div className="flex flex-col h-full "> templateRows="auto minmax(0, 1fr)"
h="100%"
maxW={{ lg: "container.lg" }}
mx="auto"
minW={{ base: "100%", lg: "container.lg" }}
>
<Box display="flex" flexDir="column" minW="100%" mb={{ base: 4, lg: 10 }}>
<TopicHeader <TopicHeader
minW="100%"
stateCurrentTopic={stateCurrentTopic} stateCurrentTopic={stateCurrentTopic}
transcriptId={transcriptId} transcriptId={transcriptId}
topicWithWordsLoading={topicWithWords.loading} topicWithWordsLoading={topicWithWords.loading}
/> />
<TopicWords
stateSelectedText={stateSelectedText}
participants={participants}
topicWithWords={topicWithWords}
/>
</div>
<div className="flex flex-col justify-stretch">
{currentTopic ? (
<TopicPlayer <TopicPlayer
transcriptId={transcriptId} transcriptId={transcriptId}
selectedTime={ selectedTime={
selectedTextIsTimeSlice(selectedText) ? selectedText : undefined selectedTextIsTimeSlice(selectedText) ? selectedText : undefined
} }
topicTime={{ topicTime={
currentTopic
? {
start: currentTopic?.timestamp, start: currentTopic?.timestamp,
end: currentTopic?.timestamp + currentTopic?.duration, end: currentTopic?.timestamp + currentTopic?.duration,
}} }
: undefined
}
/>
</Box>
<Grid
templateColumns={{
base: "minmax(0, 1fr)",
md: "4fr 3fr",
lg: "2fr 1fr",
}}
templateRows={{
base: "repeat(2, minmax(0, 1fr)) auto",
md: "minmax(0, 1fr)",
}}
gap={{ base: "2", md: "4", lg: "4" }}
h="100%"
maxH="100%"
w="100%"
>
<TopicWords
stateSelectedText={stateSelectedText}
participants={participants}
topicWithWords={topicWithWords}
mb={{ md: "-3rem" }}
/> />
) : (
<div></div>
)}
{participants.response && (
<div className="h-full flex flex-col justify-between">
<ParticipantList <ParticipantList
{...{ {...{
transcriptId, transcriptId,
@@ -88,7 +110,8 @@ export default function TranscriptCorrect({
stateSelectedText, stateSelectedText,
}} }}
/> />
{!transcript.response?.reviewed && ( </Grid>
{transcript.response && !transcript.response?.reviewed && (
<div className="flex flex-row justify-end"> <div className="flex flex-row justify-end">
<button <button
className="p-2 px-4 rounded bg-green-400" className="p-2 px-4 rounded bg-green-400"
@@ -98,9 +121,6 @@ export default function TranscriptCorrect({
</button> </button>
</div> </div>
)} )}
</div> </Grid>
)}
</div>
</div>
); );
} }

View File

@@ -6,6 +6,18 @@ import getApi from "../../../../lib/getApi";
import { UseParticipants } from "../../useParticipants"; import { UseParticipants } from "../../useParticipants";
import { selectedTextIsSpeaker, selectedTextIsTimeSlice } from "./types"; import { selectedTextIsSpeaker, selectedTextIsTimeSlice } from "./types";
import { useError } from "../../../../(errors)/errorContext"; import { useError } from "../../../../(errors)/errorContext";
import {
Box,
Button,
Flex,
Text,
UnorderedList,
Input,
Kbd,
Spinner,
ListItem,
Grid,
} from "@chakra-ui/react";
type ParticipantList = { type ParticipantList = {
participants: UseParticipants; participants: UseParticipants;
@@ -13,7 +25,6 @@ type ParticipantList = {
topicWithWords: any; topicWithWords: any;
stateSelectedText: any; stateSelectedText: any;
}; };
// NTH re-order list when searching
const ParticipantList = ({ const ParticipantList = ({
transcriptId, transcriptId,
participants, participants,
@@ -58,12 +69,14 @@ const ParticipantList = ({
setAction("Create and assign"); setAction("Create and assign");
setSelectedParticipant(undefined); setSelectedParticipant(undefined);
} }
if (typeof selectedText == undefined) {
if (typeof selectedText == "undefined") {
inputRef.current?.blur(); inputRef.current?.blur();
setSelectedParticipant(undefined);
setAction(null); setAction(null);
} }
} }
}, [selectedText, participants.response]); }, [selectedText, !participants.response]);
useEffect(() => { useEffect(() => {
document.onkeyup = (e) => { document.onkeyup = (e) => {
@@ -250,6 +263,7 @@ const ParticipantList = ({
participants.refetch(); participants.refetch();
setParticipantInput(""); setParticipantInput("");
setLoading(false); setLoading(false);
inputRef.current?.focus();
}) })
.catch((e) => { .catch((e) => {
setError(e, "There was an error creating"); setError(e, "There was an error creating");
@@ -320,48 +334,56 @@ const ParticipantList = ({
} }
}; };
const anyLoading = loading || participants.loading || topicWithWords.loading;
return ( return (
<div className="h-full" onClick={clearSelection}> <Box h="100%" onClick={clearSelection} width="100%">
<div onClick={preventClick}> <Grid
<div className="grid grid-cols-7 gap-2 mb-2"> onClick={preventClick}
<input maxH="100%"
templateRows="auto minmax(0, 1fr)"
min-w="100%"
>
<Flex direction="column" p="2">
<Input
ref={inputRef} ref={inputRef}
onChange={changeParticipantInput} onChange={changeParticipantInput}
value={participantInput} value={participantInput}
className="border col-span-3 border-blue-400 p-1" mb="2"
placeholder="Participant Name"
/> />
{action ? ( <Button
<button
onClick={doAction} onClick={doAction}
className="p-2 bg-blue-200 w-full col-span-3" colorScheme="blue"
disabled={!action || anyLoading}
> >
[ {action || !anyLoading ? (
<>
<Kbd color="blue.500" pt="1" mr="1">
<FontAwesomeIcon <FontAwesomeIcon
icon={faArrowTurnDown} icon={faArrowTurnDown}
className="rotate-90 h-2" className="rotate-90 h-3"
/> />
]{" " + action} </Kbd>
</button> {action || "Create"}
</>
) : ( ) : (
<div className="col-span-3" /> <Spinner />
)} )}
{loading || </Button>
participants.loading || </Flex>
(topicWithWords.loading && (
<FontAwesomeIcon
icon={faSpinner}
className="animate-spin-slow text-gray-300 h-8"
/>
))}
</div>
{participants.response && ( {participants.response && (
<ul> <UnorderedList
mx="0"
mb={{ base: 2, md: 4 }}
maxH="100%"
overflow="scroll"
>
{participants.response.map((participant: Participant) => ( {participants.response.map((participant: Participant) => (
<li <ListItem
onClick={selectParticipant(participant)} onClick={selectParticipant(participant)}
className={ className={
"flex flex-row justify-between border-b last:border-b-0 py-2 " +
(participantInput.length > 0 && (participantInput.length > 0 &&
selectedText && selectedText &&
participant.name.startsWith(participantInput) participant.name.startsWith(participantInput)
@@ -371,69 +393,88 @@ const ParticipantList = ({
? "bg-blue-200 border" ? "bg-blue-200 border"
: "") : "")
} }
key={participant.id} display="flex"
flexDirection="row"
justifyContent="space-between"
alignItems="center"
borderBottom="1px"
borderColor="gray.300"
py="2"
mx="2"
_last={{ borderBottom: "0" }}
key={participant.name}
> >
<span>{participant.name}</span> <Text mt="1">{participant.name}</Text>
<div> <Box>
{selectedTextIsSpeaker(selectedText) && {selectedTextIsSpeaker(selectedText) &&
!selectedParticipant && !selectedParticipant &&
!loading && ( !loading && (
<button <Button
onClick={mergeSpeaker(selectedText, participant)} onClick={mergeSpeaker(selectedText, participant)}
className="bg-blue-400 px-2 ml-2" colorScheme="blue"
ml="2"
size="sm"
> >
{oneMatch?.id == participant.id && {oneMatch?.id == participant.id &&
action == "Create to rename" && ( action == "Create to rename" && (
<> <Kbd
<span className="text-xs"> letterSpacing="-1px"
[CTRL +{" "} color="blue.500"
mr="1"
pt="3px"
>
Ctrl +&nbsp;
<FontAwesomeIcon <FontAwesomeIcon
icon={faArrowTurnDown} icon={faArrowTurnDown}
className="rotate-90 mr-2 h-2" className="rotate-90 h-2"
/> />
] </Kbd>
</span> )}
</>
)}{" "}
Merge Merge
</button> </Button>
)} )}
{selectedTextIsTimeSlice(selectedText) && !loading && ( {selectedTextIsTimeSlice(selectedText) && !loading && (
<button <Button
onClick={assignTo(participant)} onClick={assignTo(participant)}
className="bg-blue-400 px-2 ml-2" colorScheme="blue"
ml="2"
size="sm"
> >
{oneMatch?.id == participant.id && {oneMatch?.id == participant.id &&
action == "Create and assign" && ( action == "Create and assign" && (
<> <Kbd
<span className="text-xs"> letterSpacing="-1px"
[CTRL +{" "} color="blue.500"
mr="1"
pt="3px"
>
Ctrl +&nbsp;
<FontAwesomeIcon <FontAwesomeIcon
icon={faArrowTurnDown} icon={faArrowTurnDown}
className="rotate-90 mr-2 h-2" className="rotate-90 h-2"
/> />
] </Kbd>
</span>
</>
)}{" "} )}{" "}
Assign Assign
</button> </Button>
)} )}
<button <Button
onClick={deleteParticipant(participant.id)} onClick={deleteParticipant(participant.id)}
className="bg-blue-400 px-2 ml-2" colorScheme="blue"
ml="2"
size="sm"
> >
Delete Delete
</button> </Button>
</div> </Box>
</li> </ListItem>
))} ))}
</ul> </UnorderedList>
)} )}
</div> </Grid>
</div> </Box>
); );
}; };

View File

@@ -1,5 +1,5 @@
export default ({ playing }) => ( export default ({ playing }) => (
<div className="flex justify-between w-16 h-8 m-auto"> <div className="flex justify-between w-14 h-6">
<div <div
className={`bg-blue-400 rounded w-2 ${ className={`bg-blue-400 rounded w-2 ${
playing ? "animate-wave-quiet" : "" playing ? "animate-wave-quiet" : ""

View File

@@ -1,8 +1,19 @@
import { faArrowLeft, faArrowRight } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import useTopics from "../../useTopics"; import useTopics from "../../useTopics";
import { Dispatch, SetStateAction, useEffect } from "react"; import { Dispatch, SetStateAction, useEffect } from "react";
import { GetTranscriptTopic } from "../../../../api"; import { GetTranscriptTopic } from "../../../../api";
import {
BoxProps,
Box,
Circle,
Heading,
Kbd,
Skeleton,
SkeletonCircle,
chakra,
Flex,
Center,
} from "@chakra-ui/react";
import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
type TopicHeader = { type TopicHeader = {
stateCurrentTopic: [ stateCurrentTopic: [
@@ -17,7 +28,8 @@ export default function TopicHeader({
stateCurrentTopic, stateCurrentTopic,
transcriptId, transcriptId,
topicWithWordsLoading, topicWithWordsLoading,
}: TopicHeader) { ...chakraProps
}: TopicHeader & BoxProps) {
const [currentTopic, setCurrentTopic] = stateCurrentTopic; const [currentTopic, setCurrentTopic] = stateCurrentTopic;
const topics = useTopics(transcriptId); const topics = useTopics(transcriptId);
@@ -26,17 +38,13 @@ export default function TopicHeader({
const sessionTopic = window.localStorage.getItem( const sessionTopic = window.localStorage.getItem(
transcriptId + "correct", transcriptId + "correct",
); );
console.log(sessionTopic, window.localStorage);
if (sessionTopic && topics?.topics?.find((t) => t.id == sessionTopic)) { if (sessionTopic && topics?.topics?.find((t) => t.id == sessionTopic)) {
setCurrentTopic(topics?.topics?.find((t) => t.id == sessionTopic)); setCurrentTopic(topics?.topics?.find((t) => t.id == sessionTopic));
console.log("he", sessionTopic, !!sessionTopic);
} else { } else {
setCurrentTopic(topics?.topics?.at(0)); setCurrentTopic(topics?.topics?.at(0));
console.log("hi");
} }
} }
}, [topics.loading]); }, [topics.loading]);
// console.log(currentTopic)
const number = topics.topics?.findIndex( const number = topics.topics?.findIndex(
(topic) => topic.id == currentTopic?.id, (topic) => topic.id == currentTopic?.id,
@@ -75,35 +83,85 @@ export default function TopicHeader({
}; };
}); });
if (topics.topics && currentTopic && typeof number == "number") { const isLoaded = !!(
topics.topics &&
currentTopic &&
typeof number == "number"
);
return ( return (
<div className="flex flex-row"> <Box
<button display="flex"
className={`w-10 h-10 rounded-full p-2 border border-gray-300 disabled:bg-white ${ w="100%"
canGoPrevious ? "text-gray-500" : "text-gray-300" justifyContent="space-between"
}`} {...chakraProps}
>
<SkeletonCircle
isLoaded={isLoaded}
h={isLoaded ? "auto" : "40px"}
w={isLoaded ? "auto" : "40px"}
mb="2"
fadeDuration={1}
>
<Circle
as="button"
onClick={onPrev} onClick={onPrev}
disabled={!canGoPrevious} disabled={!canGoPrevious}
size="40px"
border="1px"
color={canGoPrevious ? "inherit" : "gray"}
borderColor={canGoNext ? "body-text" : "gray"}
> >
<FontAwesomeIcon icon={faArrowLeft} /> {canGoPrevious ? (
</button> <Kbd>
<h1 className="flex-grow"> <ChevronLeftIcon />
{currentTopic.title}{" "} </Kbd>
<span> ) : (
{number + 1}/{total} <ChevronLeftIcon />
</span> )}
</h1> </Circle>
<button </SkeletonCircle>
className={`w-10 h-10 rounded-full p-2 border border-gray-300 disabled:bg-white ${ <Skeleton
canGoNext ? "text-gray-500" : "text-gray-300" isLoaded={isLoaded}
}`} h={isLoaded ? "auto" : "40px"}
mb="2"
fadeDuration={1}
flexGrow={1}
mx={6}
>
<Flex wrap="nowrap" justifyContent="center">
<Heading size="lg" textAlign="center" noOfLines={1}>
{currentTopic?.title}{" "}
</Heading>
<Heading size="lg" ml="3">
{(number || 0) + 1}/{total}
</Heading>
</Flex>
</Skeleton>
<SkeletonCircle
isLoaded={isLoaded}
h={isLoaded ? "auto" : "40px"}
w={isLoaded ? "auto" : "40px"}
mb="2"
fadeDuration={1}
>
<Circle
as="button"
onClick={onNext} onClick={onNext}
disabled={!canGoNext} disabled={!canGoNext}
size="40px"
border="1px"
color={canGoNext ? "inherit" : "gray"}
borderColor={canGoNext ? "body-text" : "gray"}
> >
<FontAwesomeIcon icon={faArrowRight} /> {canGoNext ? (
</button> <Kbd>
</div> <ChevronRightIcon />
</Kbd>
) : (
<ChevronRightIcon />
)}
</Circle>
</SkeletonCircle>
</Box>
); );
}
return null;
} }

View File

@@ -3,18 +3,29 @@ import useMp3 from "../../useMp3";
import { formatTime } from "../../../../lib/time"; import { formatTime } from "../../../../lib/time";
import SoundWaveCss from "./soundWaveCss"; import SoundWaveCss from "./soundWaveCss";
import { TimeSlice } from "./types"; import { TimeSlice } from "./types";
import {
BoxProps,
Button,
Wrap,
Text,
WrapItem,
Kbd,
Skeleton,
chakra,
} from "@chakra-ui/react";
type TopicPlayer = { type TopicPlayer = {
transcriptId: string; transcriptId: string;
selectedTime: TimeSlice | undefined; selectedTime: TimeSlice | undefined;
topicTime: TimeSlice; topicTime: TimeSlice | undefined;
}; };
const TopicPlayer = ({ const TopicPlayer = ({
transcriptId, transcriptId,
selectedTime, selectedTime,
topicTime, topicTime,
}: TopicPlayer) => { ...chakraProps
}: TopicPlayer & BoxProps) => {
const mp3 = useMp3(transcriptId); const mp3 = useMp3(transcriptId);
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const [endTopicCallback, setEndTopicCallback] = useState<() => void>(); const [endTopicCallback, setEndTopicCallback] = useState<() => void>();
@@ -46,6 +57,7 @@ const TopicPlayer = ({
}); });
const calcShowTime = () => { const calcShowTime = () => {
if (!topicTime) return;
setShowTime( setShowTime(
`${ `${
mp3.media?.currentTime mp3.media?.currentTime
@@ -67,6 +79,7 @@ const TopicPlayer = ({
setEndTopicCallback( setEndTopicCallback(
() => () =>
function () { function () {
if (!topicTime) return;
if (mp3.media && mp3.media.currentTime >= topicTime.end) { if (mp3.media && mp3.media.currentTime >= topicTime.end) {
mp3.media.pause(); mp3.media.pause();
setIsPlaying(false); setIsPlaying(false);
@@ -81,13 +94,14 @@ const TopicPlayer = ({
// there's no callback on pause but apparently changing the time while palying doesn't work... so here is a timeout // there's no callback on pause but apparently changing the time while palying doesn't work... so here is a timeout
setTimeout(() => { setTimeout(() => {
if (mp3.media) { if (mp3.media) {
if (!topicTime) return;
mp3.media.currentTime = topicTime.start; mp3.media.currentTime = topicTime.start;
setShowTime(`00:00/${formatTime(topicTime.end - topicTime.start)}`); setShowTime(`00:00/${formatTime(topicTime.end - topicTime.start)}`);
} }
}, 10); }, 10);
setIsPlaying(false); setIsPlaying(false);
} }
}, [!mp3.media, topicTime.start, topicTime.end]); }, [!mp3.media, topicTime?.start, topicTime?.end]);
useEffect(() => { useEffect(() => {
endTopicCallback && endTopicCallback &&
@@ -141,6 +155,7 @@ const TopicPlayer = ({
const playTopic = (e) => { const playTopic = (e) => {
e?.preventDefault(); e?.preventDefault();
e?.target?.blur(); e?.target?.blur();
if (!topicTime) return;
if (mp3.media) { if (mp3.media) {
mp3.media.currentTime = topicTime.start; mp3.media.currentTime = topicTime.start;
mp3.media.play(); mp3.media.play();
@@ -165,37 +180,65 @@ const TopicPlayer = ({
mp3.media?.pause(); mp3.media?.pause();
setIsPlaying(false); setIsPlaying(false);
}; };
console.log(topicTime);
if (mp3.media) { const isLoaded = !!(mp3.media && topicTime);
return ( return (
<div className="mb-4 grid grid-cols-3 gap-2"> <Skeleton
isLoaded={isLoaded}
h={isLoaded ? "auto" : "40px"}
fadeDuration={1}
w={isLoaded ? "auto" : "container.md"}
margin="auto"
{...chakraProps}
>
<Wrap spacing="4" justify="center" align="center">
<WrapItem>
<SoundWaveCss playing={isPlaying} /> <SoundWaveCss playing={isPlaying} />
<div className="col-span-2">{showTime}</div> <Text fontSize="sm" pt="1" pl="2">
<button className="p-2 bg-blue-200 w-full" onClick={playTopic}> {showTime}
Play From Start </Text>
</button> </WrapItem>
<WrapItem>
<Button onClick={playTopic} colorScheme="blue">
Play from start
</Button>
</WrapItem>
<WrapItem>
{!isPlaying ? ( {!isPlaying ? (
<button <Button
onClick={playCurrent}
ref={playButton} ref={playButton}
id="playButton" id="playButton"
className="p-2 bg-blue-200 w-full" colorScheme="blue"
onClick={playCurrent} w="120px"
> >
<span className="text-xs">[SPACE]</span> Play <Kbd color="blue.600">Space</Kbd>&nbsp;Play
</button> </Button>
) : ( ) : (
<button className="p-2 bg-blue-200 w-full" onClick={pause}> <Button
<span className="text-xs">[SPACE]</span> Pause onClick={pause}
</button> ref={playButton}
id="playButton"
colorScheme="blue"
w="120px"
>
<Kbd color="blue.600">Space</Kbd>&nbsp;Pause
</Button>
)} )}
{selectedTime && ( </WrapItem>
<button className="p-2 bg-blue-200 w-full" onClick={playSelection}> <WrapItem visibility={selectedTime ? "visible" : "hidden"}>
<span className="text-xs">[,]</span>Play Selection <Button
</button> disabled={!selectedTime}
)} onClick={playSelection}
</div> colorScheme="blue"
>
<Kbd color="blue.600">,</Kbd>&nbsp;Play selection
</Button>
</WrapItem>
</Wrap>
</Skeleton>
); );
}
}; };
export default TopicPlayer; export default TopicPlayer;

View File

@@ -3,6 +3,14 @@ import WaveformLoading from "../../waveformLoading";
import { UseParticipants } from "../../useParticipants"; import { UseParticipants } from "../../useParticipants";
import { UseTopicWithWords } from "../../useTopicWithWords"; import { UseTopicWithWords } from "../../useTopicWithWords";
import { TimeSlice, selectedTextIsTimeSlice } from "./types"; import { TimeSlice, selectedTextIsTimeSlice } from "./types";
import {
BoxProps,
Box,
Container,
Text,
chakra,
Spinner,
} from "@chakra-ui/react";
type TopicWordsProps = { type TopicWordsProps = {
stateSelectedText: [ stateSelectedText: [
@@ -17,7 +25,8 @@ const topicWords = ({
stateSelectedText, stateSelectedText,
participants, participants,
topicWithWords, topicWithWords,
}: TopicWordsProps) => { ...chakraProps
}: TopicWordsProps & BoxProps) => {
const [selectedText, setSelectedText] = stateSelectedText; const [selectedText, setSelectedText] = stateSelectedText;
useEffect(() => { useEffect(() => {
@@ -150,45 +159,54 @@ const topicWords = ({
participants.response participants.response
) { ) {
return ( return (
<div onMouseUp={onMouseUp} className="p-5 h-full w-full overflow-scroll"> <Container
onMouseUp={onMouseUp}
max-h="100%"
width="100%"
overflow="scroll"
maxW={{ lg: "container.md" }}
{...chakraProps}
>
{topicWithWords.response.wordsPerSpeaker.map( {topicWithWords.response.wordsPerSpeaker.map(
(speakerWithWords, index) => ( (speakerWithWords, index) => (
<p key={index} className="mb-2 last:mb-0"> <Text key={index} className="mb-2 last:mb-0">
<span <Box
as="span"
data-speaker={speakerWithWords.speaker} data-speaker={speakerWithWords.speaker}
className={` pt="1"
font-semibold ${ fontWeight="semibold"
selectedText == speakerWithWords.speaker bgColor={
? "bg-yellow-200" selectedText == speakerWithWords.speaker ? "yellow.200" : ""
: "" }
}`}
> >
{getSpeakerName(speakerWithWords.speaker)}&nbsp;:&nbsp; {getSpeakerName(speakerWithWords.speaker)}&nbsp;:&nbsp;
</span> </Box>
{speakerWithWords.words.map((word, index) => ( {speakerWithWords.words.map((word, index) => (
<span <Box
as="span"
data-start={word.start} data-start={word.start}
data-end={word.end} data-end={word.end}
key={index} key={index}
className={ pt="1"
bgColor={
selectedTextIsTimeSlice(selectedText) && selectedTextIsTimeSlice(selectedText) &&
selectedText.start <= word.start && selectedText.start <= word.start &&
selectedText.end >= word.end selectedText.end >= word.end
? "bg-yellow-200" ? "yellow.200"
: "" : ""
} }
> >
{word.text} {word.text}
</span> </Box>
))} ))}
</p> </Text>
), ),
)} )}
</div> </Container>
); );
} }
if (topicWithWords.loading || participants.loading) if (topicWithWords.loading || participants.loading)
return <WaveformLoading />; return <Spinner size="xl" margin="auto" />;
if (topicWithWords.error || participants.error) return <p>error</p>; if (topicWithWords.error || participants.error) return <p>error</p>;
return null; return null;
}; };