mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-23 05:39:05 +00:00
player and share
This commit is contained in:
@@ -2,41 +2,50 @@ import { useEffect, useRef, useState } from "react";
|
||||
import React from "react";
|
||||
import Markdown from "react-markdown";
|
||||
import "../../../styles/markdown.css";
|
||||
import { UpdateTranscript } from "../../../api";
|
||||
import {
|
||||
GetTranscript,
|
||||
GetTranscriptTopic,
|
||||
UpdateTranscript,
|
||||
} from "../../../api";
|
||||
import useApi from "../../../lib/useApi";
|
||||
import useTranscript from "../useTranscript";
|
||||
import useTopics from "../useTopics";
|
||||
import { Box, Flex, IconButton, Modal, ModalContent } from "@chakra-ui/react";
|
||||
import { FaShare } from "react-icons/fa";
|
||||
import ShareTranscript from "../shareTranscript";
|
||||
import {
|
||||
Flex,
|
||||
Heading,
|
||||
IconButton,
|
||||
Button,
|
||||
Textarea,
|
||||
Spacer,
|
||||
} from "@chakra-ui/react";
|
||||
import { FaPen } from "react-icons/fa";
|
||||
import { useError } from "../../../(errors)/errorContext";
|
||||
import ShareAndPrivacy from "../shareAndPrivacy";
|
||||
|
||||
type FinalSummaryProps = {
|
||||
transcriptId: string;
|
||||
transcriptResponse: GetTranscript;
|
||||
topicsResponse: GetTranscriptTopic[];
|
||||
};
|
||||
|
||||
export default function FinalSummary(props: FinalSummaryProps) {
|
||||
const transcript = useTranscript(props.transcriptId);
|
||||
const topics = useTopics(props.transcriptId);
|
||||
|
||||
const finalSummaryRef = useRef<HTMLParagraphElement>(null);
|
||||
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
const [preEditSummary, setPreEditSummary] = useState("");
|
||||
const [editedSummary, setEditedSummary] = useState("");
|
||||
|
||||
const [showShareModal, setShowShareModal] = useState(false);
|
||||
const api = useApi();
|
||||
|
||||
const { setError } = useError();
|
||||
|
||||
useEffect(() => {
|
||||
setEditedSummary(transcript.response?.long_summary || "");
|
||||
}, [transcript.response?.long_summary]);
|
||||
setEditedSummary(props.transcriptResponse?.long_summary || "");
|
||||
}, [props.transcriptResponse?.long_summary]);
|
||||
|
||||
if (!topics.topics || !transcript.response) {
|
||||
if (!props.topicsResponse || !props.transcriptResponse) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const updateSummary = async (newSummary: string, transcriptId: string) => {
|
||||
try {
|
||||
const api = useApi();
|
||||
const requestBody: UpdateTranscript = {
|
||||
long_summary: newSummary,
|
||||
};
|
||||
@@ -47,6 +56,7 @@ export default function FinalSummary(props: FinalSummaryProps) {
|
||||
console.log("Updated long summary:", updatedTranscript);
|
||||
} catch (err) {
|
||||
console.error("Failed to update long summary:", err);
|
||||
setError(err, "Failed to update long summary.");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -61,7 +71,7 @@ export default function FinalSummary(props: FinalSummaryProps) {
|
||||
};
|
||||
|
||||
const onSaveClick = () => {
|
||||
updateSummary(editedSummary, props.transcriptId);
|
||||
updateSummary(editedSummary, props.transcriptResponse.id);
|
||||
setIsEditMode(false);
|
||||
};
|
||||
|
||||
@@ -77,86 +87,64 @@ export default function FinalSummary(props: FinalSummaryProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
(isEditMode ? "overflow-y-none" : "overflow-y-auto") +
|
||||
" max-h-full flex flex-col h-full"
|
||||
}
|
||||
<Flex
|
||||
direction="column"
|
||||
maxH={"100%"}
|
||||
h={"100%"}
|
||||
overflowY={isEditMode ? "hidden" : "auto"}
|
||||
pb={4}
|
||||
>
|
||||
<div className="flex flex-row flex-wrap-reverse justify-between items-center">
|
||||
<h2 className="text-lg sm:text-xl md:text-2xl font-bold">
|
||||
Final Summary
|
||||
</h2>
|
||||
<Flex dir="row" justify="start" align="center" wrap={"wrap-reverse"}>
|
||||
<Heading size={{ base: "md" }}>Summary</Heading>
|
||||
|
||||
<div className="ml-auto flex space-x-2 mb-2">
|
||||
{isEditMode && (
|
||||
<>
|
||||
<button
|
||||
onClick={onDiscardClick}
|
||||
className={"text-gray-500 text-sm hover:underline"}
|
||||
>
|
||||
Discard Changes
|
||||
</button>
|
||||
<button
|
||||
onClick={onSaveClick}
|
||||
className={
|
||||
"bg-blue-400 hover:bg-blue-500 focus-visible:bg-blue-500 text-white rounded p-2"
|
||||
}
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{isEditMode && (
|
||||
<>
|
||||
<Spacer />
|
||||
<Button
|
||||
onClick={onDiscardClick}
|
||||
colorScheme="gray"
|
||||
variant={"text"}
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
<Button onClick={onSaveClick} colorScheme="blue">
|
||||
Save
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!isEditMode && (
|
||||
<>
|
||||
<button
|
||||
onClick={onEditClick}
|
||||
className={
|
||||
"bg-blue-400 hover:bg-blue-500 focus-visible:bg-blue-500 text-white rounded p-2 sm:text-base"
|
||||
}
|
||||
>
|
||||
<span className="text-xs">✏️ Summary</span>
|
||||
</button>
|
||||
<IconButton
|
||||
icon={<FaShare />}
|
||||
onClick={() => setShowShareModal(true)}
|
||||
aria-label="Share"
|
||||
/>
|
||||
{showShareModal && (
|
||||
<Modal
|
||||
isOpen={showShareModal}
|
||||
onClose={() => setShowShareModal(false)}
|
||||
size="xl"
|
||||
>
|
||||
<ModalContent>
|
||||
<ShareTranscript
|
||||
finalSummaryRef={finalSummaryRef}
|
||||
transcriptResponse={transcript.response}
|
||||
topicsResponse={topics.topics}
|
||||
/>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{!isEditMode && (
|
||||
<>
|
||||
<IconButton
|
||||
icon={<FaPen />}
|
||||
aria-label="Edit Summary"
|
||||
onClick={onEditClick}
|
||||
/>
|
||||
<Spacer />
|
||||
<ShareAndPrivacy
|
||||
finalSummaryRef={finalSummaryRef}
|
||||
transcriptResponse={props.transcriptResponse}
|
||||
topicsResponse={props.topicsResponse}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{isEditMode ? (
|
||||
<div className="flex-grow overflow-y-none">
|
||||
<textarea
|
||||
value={editedSummary}
|
||||
onChange={(e) => setEditedSummary(e.target.value)}
|
||||
className="markdown w-full h-full d-block p-2 border rounded shadow-sm"
|
||||
onKeyDown={(e) => handleTextAreaKeyDown(e)}
|
||||
/>
|
||||
</div>
|
||||
<Textarea
|
||||
value={editedSummary}
|
||||
onChange={(e) => setEditedSummary(e.target.value)}
|
||||
className="markdown"
|
||||
onKeyDown={(e) => handleTextAreaKeyDown(e)}
|
||||
h={"100%"}
|
||||
resize={"none"}
|
||||
mt={2}
|
||||
/>
|
||||
) : (
|
||||
<div ref={finalSummaryRef} className="markdown">
|
||||
<Markdown>{editedSummary}</Markdown>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,24 +9,11 @@ import { Topic } from "../webSocketTypes";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import "../../../styles/button.css";
|
||||
import FinalSummary from "./finalSummary";
|
||||
import ShareLink from "../shareLink";
|
||||
import QRCode from "react-qr-code";
|
||||
import TranscriptTitle from "../transcriptTitle";
|
||||
import ShareModal from "./shareModal";
|
||||
import Player from "../player";
|
||||
import WaveformLoading from "../waveformLoading";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { featureEnabled } from "../../domainContext";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Grid,
|
||||
GridItem,
|
||||
IconButton,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import { FaPen } from "react-icons/fa";
|
||||
import { Flex, Grid, GridItem, Skeleton, Text } from "@chakra-ui/react";
|
||||
|
||||
type TranscriptDetails = {
|
||||
params: {
|
||||
@@ -82,7 +69,10 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
templateRows="auto minmax(0, 1fr)"
|
||||
gap={2}
|
||||
padding={4}
|
||||
background="gray.100"
|
||||
paddingBottom={0}
|
||||
background="gray.bg"
|
||||
border={"2px solid"}
|
||||
borderColor={"gray.bg"}
|
||||
borderRadius={8}
|
||||
>
|
||||
<GridItem
|
||||
@@ -102,9 +92,12 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
autoscroll={false}
|
||||
transcriptId={transcriptId}
|
||||
/>
|
||||
{transcript.response.long_summary ? (
|
||||
{transcript.response && topics.topics ? (
|
||||
<>
|
||||
<FinalSummary transcriptId={transcript.response.id} />
|
||||
<FinalSummary
|
||||
transcriptResponse={transcript.response}
|
||||
topicsResponse={topics.topics}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Flex justify={"center"} alignItems={"center"} h={"100%"}>
|
||||
@@ -121,9 +114,9 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
</Flex>
|
||||
)}
|
||||
</Grid>
|
||||
{waveform.waveform && mp3.media ? (
|
||||
{waveform.waveform && mp3.media && topics.topics ? (
|
||||
<Player
|
||||
topics={topics?.topics || []}
|
||||
topics={topics?.topics}
|
||||
useActiveTopic={useActiveTopic}
|
||||
waveform={waveform.waveform}
|
||||
media={mp3.media}
|
||||
@@ -132,7 +125,7 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
) : waveform.error ? (
|
||||
<div>"error loading this recording"</div>
|
||||
) : (
|
||||
<WaveformLoading />
|
||||
<Skeleton h={14} />
|
||||
)}
|
||||
</Grid>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user