From 0f64d3cf3ac9aeccbaa51ca3baeec79188242aa4 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Tue, 3 Dec 2024 23:43:55 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20introduce=20a=20sidepanel?= =?UTF-8?q?=20for=20AI=20assistant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce the content for the AI assistant panel, which describes the feature, and offers a button to start and stop a recording. --- .../rooms/livekit/components/Transcript.tsx | 94 ++++++++++++++++++- src/frontend/src/locales/de/rooms.json | 12 +++ src/frontend/src/locales/en/rooms.json | 12 +++ src/frontend/src/locales/fr/rooms.json | 12 +++ src/frontend/src/primitives/Text.tsx | 8 ++ 5 files changed, 134 insertions(+), 4 deletions(-) diff --git a/src/frontend/src/features/rooms/livekit/components/Transcript.tsx b/src/frontend/src/features/rooms/livekit/components/Transcript.tsx index cd9443d6..b0f503e7 100644 --- a/src/frontend/src/features/rooms/livekit/components/Transcript.tsx +++ b/src/frontend/src/features/rooms/livekit/components/Transcript.tsx @@ -1,14 +1,100 @@ -import { Div } from '@/primitives' +import { Button, Div, H, Text } from '@/primitives' + +import thirdSlide from '@/assets/intro-slider/3_resume.png' +import { css } from '@/styled-system/css' + +import { useHasTranscriptAccess } from '../hooks/useHasTranscriptAccess' +import { RiRecordCircleLine, RiStopCircleLine } from '@remixicon/react' +import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId' +import { useRoomContext } from '@livekit/components-react' +import { + RecordingMode, + useStartRecording, +} from '@/features/rooms/api/startRecording' +import { useStopRecording } from '@/features/rooms/api/stopRecording' +import { useEffect, useState } from 'react' +import { RoomEvent } from 'livekit-client' +import { useTranslation } from 'react-i18next' export const Transcript = () => { + const [isLoading, setIsLoading] = useState(false) + + const { t } = useTranslation('rooms', { keyPrefix: 'transcript' }) + + const hasTranscriptAccess = useHasTranscriptAccess() + + const roomId = useRoomId() + + const { mutateAsync: startRecordingRoom } = useStartRecording() + const { mutateAsync: stopRecordingRoom } = useStopRecording() + + const room = useRoomContext() + + useEffect(() => { + const handleRecordingStatusChanged = () => { + setIsLoading(false) + } + room.on(RoomEvent.RecordingStatusChanged, handleRecordingStatusChanged) + return () => { + room.off(RoomEvent.RecordingStatusChanged, handleRecordingStatusChanged) + } + }, [room]) + + const handleTranscript = async () => { + if (!roomId) { + console.warn('No room ID found') + return + } + try { + setIsLoading(true) + if (room.isRecording) { + await stopRecordingRoom({ id: roomId }) + } else { + await startRecordingRoom({ id: roomId, mode: RecordingMode.Transcript }) + } + } catch (error) { + console.error('Failed to handle transcript:', error) + setIsLoading(false) + } + } + + if (!hasTranscriptAccess) return + return (
- wip + {'wip'} + {room.isRecording ? ( + <> + {t('stop.heading')} + + {t('stop.body')} + +
+ + + ) : ( + <> + {t('start.heading')} + + {t('start.body')} + +
+ + + )}
) } diff --git a/src/frontend/src/locales/de/rooms.json b/src/frontend/src/locales/de/rooms.json index 0d261ddf..e86c4794 100644 --- a/src/frontend/src/locales/de/rooms.json +++ b/src/frontend/src/locales/de/rooms.json @@ -120,6 +120,18 @@ "chat": { "disclaimer": "" }, + "transcript": { + "start": { + "heading": "", + "body": "", + "button": "" + }, + "stop": { + "heading": "", + "body": "", + "button": "" + } + }, "rating": { "submit": "", "question": "", diff --git a/src/frontend/src/locales/en/rooms.json b/src/frontend/src/locales/en/rooms.json index fa10ebb9..2db4ed33 100644 --- a/src/frontend/src/locales/en/rooms.json +++ b/src/frontend/src/locales/en/rooms.json @@ -119,6 +119,18 @@ "chat": { "disclaimer": "The messages are visible to participants only at the time they are sent. All messages are deleted at the end of the call." }, + "transcript": { + "start": { + "heading": "Start the Assistant!", + "body": "The assistant automatically starts recording your meeting audio (limited to 1 hour). At the end, you'll receive a clear and concise summary of the discussion directly via email.", + "button": "Start" + }, + "stop": { + "heading": "Recording in Progress...", + "body": "Your meeting is currently being recorded. You will receive a summary via email once the meeting ends.", + "button": "Stop Recording" + } + }, "rating": { "submit": "Submit", "question": "What do you think about the quality of your call?", diff --git a/src/frontend/src/locales/fr/rooms.json b/src/frontend/src/locales/fr/rooms.json index 14134b8d..6c2edbda 100644 --- a/src/frontend/src/locales/fr/rooms.json +++ b/src/frontend/src/locales/fr/rooms.json @@ -119,6 +119,18 @@ "chat": { "disclaimer": "Les messages sont visibles par les participants uniquement au moment de\nleur envoi. Tous les messages sont supprimés à la fin de l'appel." }, + "transcript": { + "start": { + "heading": "Démarrer l'assistant !", + "body": "L'assistant démarre automatiquement l'enregistrement sonore de votre réunion (limité à 1h). À la fin, vous recevrez un résumé clair et concis des échanges directement par e-mail.", + "button": "Démarrer" + }, + "stop": { + "heading": "Enregistrement en cours …", + "body": "L'enregistrement de votre réunion est en cours. Vous recevrez un compte-rendu par email une fois la réunion terminée.", + "button": "Arrêter l'enregistrement" + } + }, "rating": { "submit": "Envoyer", "question": "Que pensez-vous de la qualité de votre appel ?", diff --git a/src/frontend/src/primitives/Text.tsx b/src/frontend/src/primitives/Text.tsx index f38c27f9..37c2d576 100644 --- a/src/frontend/src/primitives/Text.tsx +++ b/src/frontend/src/primitives/Text.tsx @@ -55,6 +55,14 @@ export const text = cva({ textAlign: 'inherit', }, }, + wrap: { + balance: { + textWrap: 'balance', + }, + pretty: { + textWrap: 'pretty', + }, + }, bold: { true: { fontWeight: 'bold',