mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
* Delete recording with transcript * Delete confirmation dialog * Use aws storage abstraction for recording deletion * Test recording deleted with transcript * Use get transcript storage * Fix the test * Add env vars for recording storage
228 lines
6.6 KiB
TypeScript
228 lines
6.6 KiB
TypeScript
"use client";
|
|
import React, { useState, useEffect } from "react";
|
|
import { Flex, Spinner, Heading, Text, Link } from "@chakra-ui/react";
|
|
import useTranscriptList from "../transcripts/useTranscriptList";
|
|
import useSessionUser from "../../lib/useSessionUser";
|
|
import { Room } from "../../api";
|
|
import Pagination from "./_components/Pagination";
|
|
import useApi from "../../lib/useApi";
|
|
import { useError } from "../../(errors)/errorContext";
|
|
import { SourceKind } from "../../api";
|
|
import FilterSidebar from "./_components/FilterSidebar";
|
|
import SearchBar from "./_components/SearchBar";
|
|
import TranscriptTable from "./_components/TranscriptTable";
|
|
import TranscriptCards from "./_components/TranscriptCards";
|
|
import DeleteTranscriptDialog from "./_components/DeleteTranscriptDialog";
|
|
import { formatLocalDate } from "../../lib/time";
|
|
|
|
export default function TranscriptBrowser() {
|
|
const [selectedSourceKind, setSelectedSourceKind] =
|
|
useState<SourceKind | null>(null);
|
|
const [selectedRoomId, setSelectedRoomId] = useState("");
|
|
const [rooms, setRooms] = useState<Room[]>([]);
|
|
const [page, setPage] = useState(1);
|
|
const [searchTerm, setSearchTerm] = useState("");
|
|
const { loading, response, refetch } = useTranscriptList(
|
|
page,
|
|
selectedSourceKind,
|
|
selectedRoomId,
|
|
searchTerm
|
|
);
|
|
const userName = useSessionUser().name;
|
|
const [deletionLoading, setDeletionLoading] = useState(false);
|
|
const api = useApi();
|
|
const { setError } = useError();
|
|
const cancelRef = React.useRef(null);
|
|
const [transcriptToDeleteId, setTranscriptToDeleteId] =
|
|
React.useState<string>();
|
|
const [deletedItemIds, setDeletedItemIds] = React.useState<string[]>();
|
|
|
|
useEffect(() => {
|
|
setDeletedItemIds([]);
|
|
}, [page, response]);
|
|
|
|
useEffect(() => {
|
|
if (!api) return;
|
|
api
|
|
.v1RoomsList({ page: 1 })
|
|
.then((rooms) => setRooms(rooms.items))
|
|
.catch((err) => setError(err, "There was an error fetching the rooms"));
|
|
}, [api]);
|
|
|
|
const handleFilterTranscripts = (
|
|
sourceKind: SourceKind | null,
|
|
roomId: string
|
|
) => {
|
|
setSelectedSourceKind(sourceKind);
|
|
setSelectedRoomId(roomId);
|
|
setPage(1);
|
|
};
|
|
|
|
const handleSearch = (searchTerm: string) => {
|
|
setPage(1);
|
|
setSearchTerm(searchTerm);
|
|
setSelectedSourceKind(null);
|
|
setSelectedRoomId("");
|
|
};
|
|
|
|
if (loading && !response)
|
|
return (
|
|
<Flex
|
|
flexDir="column"
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
h="100%"
|
|
>
|
|
<Spinner size="xl" />
|
|
</Flex>
|
|
);
|
|
|
|
if (!loading && !response)
|
|
return (
|
|
<Flex
|
|
flexDir="column"
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
h="100%"
|
|
>
|
|
<Text>
|
|
No transcripts found, but you can
|
|
<Link href="/transcripts/new" className="underline">
|
|
record a meeting
|
|
</Link>
|
|
to get started.
|
|
</Text>
|
|
</Flex>
|
|
);
|
|
|
|
const onCloseDeletion = () => setTranscriptToDeleteId(undefined);
|
|
|
|
const confirmDeleteTranscript = (transcriptId: string) => {
|
|
if (!api || deletionLoading) return;
|
|
setDeletionLoading(true);
|
|
api
|
|
.v1TranscriptDelete({ transcriptId })
|
|
.then(() => {
|
|
refetch();
|
|
setDeletionLoading(false);
|
|
onCloseDeletion();
|
|
setDeletedItemIds((prev) =>
|
|
prev ? [...prev, transcriptId] : [transcriptId]
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
setDeletionLoading(false);
|
|
setError(err, "There was an error deleting the transcript");
|
|
});
|
|
};
|
|
|
|
const handleDeleteTranscript = (transcriptId: string) => (e: any) => {
|
|
e?.stopPropagation?.();
|
|
setTranscriptToDeleteId(transcriptId);
|
|
};
|
|
|
|
const handleProcessTranscript = (transcriptId) => (e) => {
|
|
if (api) {
|
|
api
|
|
.v1TranscriptProcess({ transcriptId })
|
|
.then((result) => {
|
|
const status = (result as any).status;
|
|
if (status === "already running") {
|
|
setError(
|
|
new Error("Processing is already running, please wait"),
|
|
"Processing is already running, please wait"
|
|
);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
setError(err, "There was an error processing the transcript");
|
|
});
|
|
}
|
|
};
|
|
|
|
const transcriptToDelete = response?.items?.find(
|
|
(i) => i.id === transcriptToDeleteId
|
|
);
|
|
const dialogTitle = transcriptToDelete?.title || "Unnamed Transcript";
|
|
const dialogDate = transcriptToDelete?.created_at
|
|
? formatLocalDate(transcriptToDelete.created_at)
|
|
: undefined;
|
|
const dialogSource = transcriptToDelete
|
|
? transcriptToDelete.source_kind === "room"
|
|
? transcriptToDelete.room_name || undefined
|
|
: transcriptToDelete.source_kind
|
|
: undefined;
|
|
|
|
return (
|
|
<Flex
|
|
flexDir="column"
|
|
w={{ base: "full", md: "container.xl" }}
|
|
mx="auto"
|
|
pt={4}
|
|
>
|
|
<Flex
|
|
flexDir="row"
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
mb={4}
|
|
>
|
|
<Heading size="lg">
|
|
{userName ? `${userName}'s Transcriptions` : "Your Transcriptions"}{" "}
|
|
{loading || (deletionLoading && <Spinner size="sm" />)}
|
|
</Heading>
|
|
</Flex>
|
|
|
|
<Flex flexDir={{ base: "column", md: "row" }}>
|
|
<FilterSidebar
|
|
rooms={rooms}
|
|
selectedSourceKind={selectedSourceKind}
|
|
selectedRoomId={selectedRoomId}
|
|
onFilterChange={handleFilterTranscripts}
|
|
/>
|
|
|
|
<Flex
|
|
flexDir="column"
|
|
flex="1"
|
|
pt={{ base: 4, md: 0 }}
|
|
pb={4}
|
|
gap={4}
|
|
px={{ base: 0, md: 4 }}
|
|
>
|
|
<SearchBar onSearch={handleSearch} />
|
|
<Pagination
|
|
page={page}
|
|
setPage={setPage}
|
|
total={response?.total || 0}
|
|
size={response?.size || 0}
|
|
/>
|
|
<TranscriptTable
|
|
transcripts={response?.items || []}
|
|
onDelete={handleDeleteTranscript}
|
|
onReprocess={handleProcessTranscript}
|
|
loading={loading}
|
|
/>
|
|
<TranscriptCards
|
|
transcripts={response?.items || []}
|
|
onDelete={handleDeleteTranscript}
|
|
onReprocess={handleProcessTranscript}
|
|
loading={loading}
|
|
/>
|
|
</Flex>
|
|
</Flex>
|
|
|
|
<DeleteTranscriptDialog
|
|
isOpen={!!transcriptToDeleteId}
|
|
onClose={onCloseDeletion}
|
|
onConfirm={() =>
|
|
transcriptToDeleteId && confirmDeleteTranscript(transcriptToDeleteId)
|
|
}
|
|
cancelRef={cancelRef}
|
|
isLoading={deletionLoading}
|
|
title={dialogTitle}
|
|
date={dialogDate}
|
|
source={dialogSource}
|
|
/>
|
|
</Flex>
|
|
);
|
|
}
|