From e59dbf2df264d67fd17f575e310a8d5c9f6d30db Mon Sep 17 00:00:00 2001 From: Sara Date: Mon, 18 Sep 2023 16:31:23 +0200 Subject: [PATCH] layout changes --- www/app/layout.tsx | 6 +- www/app/styles/button.css | 26 ++-- www/app/styles/globals.scss | 2 - www/app/transcripts/[transcriptId]/page.tsx | 2 +- www/app/transcripts/audioInputsDropdown.tsx | 36 +++++ www/app/transcripts/dashboard.tsx | 132 +++++++++------- www/app/transcripts/finalSummary.tsx | 4 +- www/app/transcripts/liveTranscription.tsx | 7 +- www/app/transcripts/new/page.tsx | 14 +- www/app/transcripts/recorder.tsx | 160 ++++++++------------ www/tailwind.config.js | 18 ++- 11 files changed, 220 insertions(+), 187 deletions(-) create mode 100644 www/app/transcripts/audioInputsDropdown.tsx diff --git a/www/app/layout.tsx b/www/app/layout.tsx index 3f5a846c..65e9206f 100644 --- a/www/app/layout.tsx +++ b/www/app/layout.tsx @@ -56,16 +56,16 @@ export const metadata: Metadata = { export default function RootLayout({ children }) { return ( - + {/*TODO lvh or svh ? */}
-
+
{/* Logo on the left */}
-
+
{transcript?.loading === true || waveform?.loading == true || topics?.loading == true ? ( diff --git a/www/app/transcripts/audioInputsDropdown.tsx b/www/app/transcripts/audioInputsDropdown.tsx new file mode 100644 index 00000000..f2c8d187 --- /dev/null +++ b/www/app/transcripts/audioInputsDropdown.tsx @@ -0,0 +1,36 @@ +import React, { useRef, useEffect, useState } from "react"; + +import Dropdown, { Option } from "react-dropdown"; +import "react-dropdown/style.css"; + +const AudioInputsDropdown: React.FC<{ + audioDevices?: Option[]; + setDeviceId: React.Dispatch>; + disabled?: boolean; +}> = (props) => { + const [ddOptions, setDdOptions] = useState([]); + + useEffect(() => { + if (props.audioDevices) { + setDdOptions(props.audioDevices); + props.setDeviceId( + props.audioDevices.length > 0 ? props.audioDevices[0].value : null, + ); + } + }, [props.audioDevices]); + + const handleDropdownChange = (option: Option) => { + props.setDeviceId(option.value); + }; + + return ( + + ); +}; + +export default AudioInputsDropdown; diff --git a/www/app/transcripts/dashboard.tsx b/www/app/transcripts/dashboard.tsx index 4f2fdf64..a6b8c783 100644 --- a/www/app/transcripts/dashboard.tsx +++ b/www/app/transcripts/dashboard.tsx @@ -34,6 +34,7 @@ export function Dashboard({ useEffect(() => { if (autoscrollEnabled) scrollToBottom(); + console.log(topics); }, [topics.length]); const scrollToBottom = () => { @@ -54,69 +55,86 @@ export function Dashboard({ } }; + const faketopic = { + id: "641fbc68-dc2e-4c9d-aafd-89bdbf8cfc26", + summary: + "Explore the history of hypnotica music, a genre that has been deeply influential on modern music. From its origins in the 60s to its current status, this music has a unique and hypnotic quality that can be felt in the gut. Dive into the canon of modern hypnotica and discover its impact on music today.", + timestamp: 0, + title: "The Origins and Influence of Hypnotica Music", + transcript: + " vertically oriented music ultimately hypnotic So, that's what we're talking about. Uh, when does it start? I mean, technically, I think... It's always been here but Hypnotica, much like Exotica, which is also sort of a fraught genre. a sort of a western interpretive genre, a fetishizing genre. I would say, uh, it starts in the 60s when all these wh- weird things started, you know, and I started fucking around and... You can go into Woodstock or whatever, that's usually when these things start. Anything that ends with a at the end of a word usually started in By some dirty hippie. Yeah. By some dirty hippie. Yeah. It was like, uh. Okay. So. That's hypnotica, I don't care to explain it to be honest I think everyone can feel it in their gut. We're mostly gonna ex- Explore this kind of the canon of the modern canon of what what I might call hypnotic It's been deeply influential on me and, uh...", + }; + const faketopics = new Array(10).fill(faketopic); + return ( - <> -
-
-

Meeting Notes

-
+
+ {/* Topic Section */} +
+ {faketopics.length > 0 ? ( + <> + - - -
- {topics.map((item, index) => ( -
-
- setActiveTopic(activeTopic?.id == item.id ? null : item) - } - > -
- - [{formatTime(item.timestamp)}] - {" "} - {item.title} - +
+ {faketopics.map((item, index) => ( +
+ setActiveTopic(activeTopic?.id == item.id ? null : item) + } + > +
+

+ + [{formatTime(item.timestamp)}] + +   + {item.title} +

+ +
+ {activeTopic?.id == item.id && ( +
+ {item.transcript} +
+ )}
-
- {activeTopic?.id == item.id && ( -
- {item.transcript} -
- )} + ))}
- ))} - {topics.length === 0 && ( -
- Discussion topics will appear here after you start recording. It - may take up to 5 minutes of conversation for the first topic to - appear. -
- )} -
+ + ) : ( +
+ Discussion topics will appear here after you start recording. It may + take up to 5 minutes of conversation for the first topic to appear. +
+ )} +
- {finalSummary.summary && } -
+
+ {finalSummary.summary ? ( + + ) : ( + + )} +
{disconnected && } - - - +
); } diff --git a/www/app/transcripts/finalSummary.tsx b/www/app/transcripts/finalSummary.tsx index d93fb6d4..24ff91c3 100644 --- a/www/app/transcripts/finalSummary.tsx +++ b/www/app/transcripts/finalSummary.tsx @@ -4,8 +4,8 @@ type FinalSummaryProps = { export default function FinalSummary(props: FinalSummaryProps) { return ( -
-

Final Summary

+
+

Final Summary

{props.text}

); diff --git a/www/app/transcripts/liveTranscription.tsx b/www/app/transcripts/liveTranscription.tsx index 6241cdb2..d5ba2373 100644 --- a/www/app/transcripts/liveTranscription.tsx +++ b/www/app/transcripts/liveTranscription.tsx @@ -4,8 +4,11 @@ type LiveTranscriptionProps = { export default function LiveTrancription(props: LiveTranscriptionProps) { return ( -
-  {props.text}  +
+

+ {/* Nous allons prendre quelques appels téléphoniques et répondre à quelques questions */} + {props.text} +

); } diff --git a/www/app/transcripts/new/page.tsx b/www/app/transcripts/new/page.tsx index eef7d411..3c5d2804 100644 --- a/www/app/transcripts/new/page.tsx +++ b/www/app/transcripts/new/page.tsx @@ -9,6 +9,7 @@ import useAudioDevice from "../useAudioDevice"; import "../../styles/button.css"; import { Topic } from "../webSocketTypes"; import getApi from "../../lib/getApi"; +import AudioInputsDropdown from "../audioInputsDropdown"; const TranscriptCreate = () => { const [stream, setStream] = useState(null); @@ -38,8 +39,14 @@ const TranscriptCreate = () => { getAudioStream, } = useAudioDevice(); + const getCurrentStream = async () => { + return audioDevices.length + ? await getAudioStream(audioDevices[0].value) + : null; + }; + return ( -
+
{permissionOk ? ( <> { setStream(null); }} topics={webSockets.topics} - getAudioStream={getAudioStream} - audioDevices={audioDevices} + getAudioStream={getCurrentStream} useActiveTopic={useActiveTopic} isPastMeeting={false} /> @@ -65,7 +71,7 @@ const TranscriptCreate = () => { ) : ( <> -
+

Audio Permissions

{loading ? (

diff --git a/www/app/transcripts/recorder.tsx b/www/app/transcripts/recorder.tsx index 6c24109e..f235ecaf 100644 --- a/www/app/transcripts/recorder.tsx +++ b/www/app/transcripts/recorder.tsx @@ -7,49 +7,15 @@ import CustomRegionsPlugin from "../lib/custom-plugins/regions"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faDownload } from "@fortawesome/free-solid-svg-icons"; -import Dropdown, { Option } from "react-dropdown"; -import "react-dropdown/style.css"; - import { formatTime } from "../lib/time"; import { Topic } from "./webSocketTypes"; import { AudioWaveform } from "../api"; -const AudioInputsDropdown: React.FC<{ - audioDevices?: Option[]; - setDeviceId: React.Dispatch>; - disabled: boolean; -}> = (props) => { - const [ddOptions, setDdOptions] = useState([]); - - useEffect(() => { - if (props.audioDevices) { - setDdOptions(props.audioDevices); - props.setDeviceId( - props.audioDevices.length > 0 ? props.audioDevices[0].value : null, - ); - } - }, [props.audioDevices]); - - const handleDropdownChange = (option: Option) => { - props.setDeviceId(option.value); - }; - - return ( - - ); -}; - type RecorderProps = { setStream?: React.Dispatch>; onStop?: () => void; topics: Topic[]; - getAudioStream?: (deviceId: string | null) => Promise; - audioDevices?: Option[]; + getAudioStream?: () => Promise; useActiveTopic: [ Topic | null, React.Dispatch>, @@ -66,7 +32,6 @@ export default function Recorder(props: RecorderProps) { const [isRecording, setIsRecording] = useState(false); const [hasRecorded, setHasRecorded] = useState(props.isPastMeeting); const [isPlaying, setIsPlaying] = useState(false); - const [deviceId, setDeviceId] = useState(null); const [currentTime, setCurrentTime] = useState(0); const [timeInterval, setTimeInterval] = useState(null); const [duration, setDuration] = useState(0); @@ -88,7 +53,7 @@ export default function Recorder(props: RecorderProps) { hideScrollbar: true, autoCenter: true, barWidth: 2, - height: 90, + height: "auto", url: props.transcriptId ? `${process.env.NEXT_PUBLIC_API_URL}/v1/transcripts/${props.transcriptId}/audio/mp3` : undefined, @@ -222,7 +187,7 @@ export default function Recorder(props: RecorderProps) { setIsRecording(false); setHasRecorded(true); } else if (props.getAudioStream) { - const stream = await props.getAudioStream(deviceId); + const stream = await props.getAudioStream(); if (props.setStream) props.setStream(stream); waveRegions?.clearRegions(); @@ -246,68 +211,65 @@ export default function Recorder(props: RecorderProps) { }; return ( -

-
- {!hasRecorded && ( - <> - -   - -   - - )} - - {hasRecorded && ( - <> - - - {props.transcriptId && ( - - - - )} - - {!props.transcriptId && ( - - - - )} - - )} -
-
-
- {isRecording && ( -
- )} - {timeLabel()} +
+
+
+
+ {isRecording && ( +
+ )} + {timeLabel()} +
+ + {hasRecorded && ( + <> + + + {props.transcriptId && ( + + + + )} + + {!props.transcriptId && ( + + + + )} + + )} + {!hasRecorded && ( + + )}
); } diff --git a/www/tailwind.config.js b/www/tailwind.config.js index 78ebc4e7..690437d8 100644 --- a/www/tailwind.config.js +++ b/www/tailwind.config.js @@ -1,4 +1,14 @@ /** @type {import('tailwindcss').Config} */ + +// 8 margin main container Top + 40 height header + 16 margin bottom header + 80 recorder +const dashboardStart = 144; + +// 8 margin main container Top + 40 height header + 16 margin bottom header + 80 recorder +const dashboardStartMd = 144; + +// 16 margin main container Top + 64 height header + 16 margin bottom header + 80 recorder +const dashboardStartLg = 176; + module.exports = { content: [ "./pages/**/*.{js,ts,jsx,tsx,mdx}", @@ -7,10 +17,10 @@ module.exports = { ], theme: { extend: { - backgroundImage: { - "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", - "gradient-conic": - "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", + height: { + "outer-dashboard": `calc(100svh - ${dashboardStart}px)`, + "outer-dashboard-md": `calc(100svh - ${dashboardStartMd + 34}px)`, + "outer-dashboard-lg": `calc(100svh - ${dashboardStartLg}px)`, }, }, },