mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
Merge pull request #245 from Monadical-SAS/sara/design-improvements
UI Improvements
This commit is contained in:
@@ -7,7 +7,7 @@ export default () => (
|
||||
Reflector is a transcription and summarization pipeline that transforms
|
||||
audio into knowledge. The output is meeting minutes and topic summaries
|
||||
enabling topic-specific analyses stored in your systems of record. This is
|
||||
accomplished on your infrastructure - without 3rd parties - keeping your
|
||||
accomplished on your infrastructure – without 3rd parties – keeping your
|
||||
data private, secure, and organized.
|
||||
</Paragraph>
|
||||
<Title>FAQs</Title>
|
||||
@@ -23,7 +23,7 @@ export default () => (
|
||||
Monadical prioritizes safeguarding your data. Reflector operates
|
||||
exclusively on your infrastructure, ensuring guaranteed security.
|
||||
</Paragraph>
|
||||
<Subtitle>3. Any industry-specific use cases?</Subtitle>
|
||||
<Subtitle>3. Are there any industry-specific use cases?</Subtitle>
|
||||
<p>Absolutely! We have two custom deployments pre-built:</p>
|
||||
<ul className="mb-2 md:mb-4">
|
||||
<li>
|
||||
|
||||
@@ -83,9 +83,11 @@ export default function RootLayout({ children }) {
|
||||
alt="Reflector"
|
||||
/>
|
||||
<div className="hidden flex-col ml-2 md:block">
|
||||
<h1 className="text-4xl font-bold">Reflector</h1>
|
||||
<p className="text-gray-500">
|
||||
Capture The Signal, Not The Noise
|
||||
<h1 className="text-[38px] font-bold tracking-wide leading-tight">
|
||||
Reflector
|
||||
</h1>
|
||||
<p className="text-gray-500 text-xs tracking-tighter">
|
||||
Capture the signal, not the noise
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -55,15 +55,14 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
useActiveTopic={useActiveTopic}
|
||||
autoscroll={false}
|
||||
/>
|
||||
<section className="relative w-full h-auto max-h-full bg-blue-400/20 rounded-lg md:rounded-xl px-2 md:px-4 flex flex-col justify-center align-center">
|
||||
<ShareLink />
|
||||
|
||||
<div className="py-2 h-full">
|
||||
<div className="w-full h-full grid grid-rows-layout-one gap-2 lg:gap-4">
|
||||
<section className=" bg-blue-400/20 rounded-lg md:rounded-xl p-2 md:px-4 h-full">
|
||||
{transcript?.response?.longSummary && (
|
||||
<FinalSummary text={transcript?.response?.longSummary} />
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<ShareLink />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -5,7 +5,7 @@ type FinalSummaryProps = {
|
||||
export default function FinalSummary(props: FinalSummaryProps) {
|
||||
return (
|
||||
<div className="overflow-y-auto h-auto max-h-full">
|
||||
<h2 className="text-xl font-bold">Final Summary</h2>
|
||||
<h2 className="text-xl md:text-2xl font-bold">Final Summary</h2>
|
||||
<p>{props.text}</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -45,6 +45,12 @@ const TranscriptCreate = () => {
|
||||
getAudioStream,
|
||||
} = useAudioDevice();
|
||||
const [hasRecorded, setHasRecorded] = useState(false);
|
||||
const [transcriptStarted, setTranscriptStarted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!transcriptStarted && webSockets.transcriptText.length !== 0)
|
||||
setTranscriptStarted(true);
|
||||
}, [webSockets.transcriptText]);
|
||||
|
||||
useEffect(() => {
|
||||
lockWakeState();
|
||||
@@ -77,13 +83,30 @@ const TranscriptCreate = () => {
|
||||
useActiveTopic={useActiveTopic}
|
||||
autoscroll={true}
|
||||
/>
|
||||
<section className="w-full h-full bg-blue-400/20 rounded-lg md:rounded-xl px-2 md:px-4 flex flex-col justify-center align-center">
|
||||
|
||||
<section
|
||||
className={`w-full h-full bg-blue-400/20 rounded-lg md:rounded-xl p-2 md:px-4`}
|
||||
>
|
||||
{!hasRecorded ? (
|
||||
<div className="py-2 h-auto">
|
||||
<LiveTrancription text={webSockets.transcriptText} />
|
||||
</div>
|
||||
<>
|
||||
{transcriptStarted && (
|
||||
<h2 className="md:text-lg font-bold">Transcription</h2>
|
||||
)}
|
||||
<div className="flex flex-col justify-center align center text-center h-full">
|
||||
<div className="py-2 h-auto">
|
||||
{!transcriptStarted ? (
|
||||
<div className="text-center text-gray-500">
|
||||
The conversation transcript will appear here shortly
|
||||
after you start recording.
|
||||
</div>
|
||||
) : (
|
||||
<LiveTrancription text={webSockets.transcriptText} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex flex-col justify-center align center text-center">
|
||||
<div className="flex flex-col justify-center align center text-center h-full text-gray-500">
|
||||
<div className="p-2 md:p-4">
|
||||
<FontAwesomeIcon
|
||||
icon={faGear}
|
||||
@@ -117,7 +140,7 @@ const TranscriptCreate = () => {
|
||||
transforms audio into knowledge. The output is meeting
|
||||
minutes and topic summaries enabling topic-specific analyses
|
||||
stored in your systems of record. This is accomplished on
|
||||
your infrastructure - without 3rd parties - keeping your
|
||||
your infrastructure – without 3rd parties – keeping your
|
||||
data private, secure, and organized.
|
||||
</p>
|
||||
<About buttonText="Learn more" />
|
||||
@@ -125,14 +148,12 @@ const TranscriptCreate = () => {
|
||||
Audio Permissions
|
||||
</h2>
|
||||
{loading ? (
|
||||
<p className="text-gray-500 text-center">
|
||||
Checking permission...
|
||||
</p>
|
||||
<p className="text-center">Checking permission...</p>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-gray-500 text-center">
|
||||
To enable Reflector, we kindly request permission to
|
||||
access your microphone during meetings and events.
|
||||
<p className="text-center">
|
||||
In order to use Reflector, we kindly request permission
|
||||
to access your microphone during meetings and events.
|
||||
<br />
|
||||
<Privacy buttonText="Privacy policy" />
|
||||
<br />
|
||||
|
||||
@@ -109,7 +109,7 @@ export default function Recorder(props: RecorderProps) {
|
||||
|
||||
const wsWrapper = _wavesurfer.getWrapper();
|
||||
wsWrapper.style.cursor = "pointer";
|
||||
wsWrapper.style.backgroundColor = "#e0c3fc42";
|
||||
wsWrapper.style.backgroundColor = "RGB(240 240 240)";
|
||||
wsWrapper.style.borderRadius = "15px";
|
||||
|
||||
_wavesurfer.on("play", () => {
|
||||
@@ -278,7 +278,10 @@ export default function Recorder(props: RecorderProps) {
|
||||
return (
|
||||
<div className="flex items-center w-full relative">
|
||||
<div className="flex-grow items-end relative">
|
||||
<div ref={waveformRef} className="flex-grow rounded-2xl h-20"></div>
|
||||
<div
|
||||
ref={waveformRef}
|
||||
className="flex-grow rounded-lg md:rounded-xl h-20"
|
||||
></div>
|
||||
<div className="absolute right-2 bottom-0">
|
||||
{isRecording && (
|
||||
<div className="inline-block bg-red-500 rounded-full w-2 h-2 my-auto mr-1 animate-ping"></div>
|
||||
@@ -336,7 +339,7 @@ export default function Recorder(props: RecorderProps) {
|
||||
>
|
||||
{isRecording ? "Stop" : "Record"}
|
||||
</button>
|
||||
{props.audioDevices && props.audioDevices?.length > 0 && (
|
||||
{props.audioDevices && props.audioDevices?.length > 1 && (
|
||||
<>
|
||||
<button
|
||||
className="text-center text-blue-400 hover:text-blue-700 ml-2 md:ml:4 p-2 rounded-lg focus-visible:outline outline-blue-400"
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import React, { useState, useRef } from "react";
|
||||
import React, { useState, useRef, useEffect, use } from "react";
|
||||
|
||||
const ShareLink = () => {
|
||||
const [isCopied, setIsCopied] = useState(false);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [currentUrl, setCurrentUrl] = useState<string>("");
|
||||
|
||||
const currentURL = window.location.href;
|
||||
useEffect(() => {
|
||||
setCurrentUrl(window.location.href);
|
||||
}, []);
|
||||
|
||||
const handleCopyClick = () => {
|
||||
if (inputRef.current) {
|
||||
@@ -19,7 +22,7 @@ const ShareLink = () => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="p-2 md:p-4 mt-8 md:mt-4 rounded"
|
||||
className="p-2 md:p-4 rounded"
|
||||
style={{ background: "rgba(96, 165, 250, 0.2)" }}
|
||||
>
|
||||
<p className="text-sm mb-2">
|
||||
@@ -31,9 +34,10 @@ const ShareLink = () => {
|
||||
<input
|
||||
type="text"
|
||||
readOnly
|
||||
value={currentURL}
|
||||
value={currentUrl}
|
||||
ref={inputRef}
|
||||
className="border rounded p-2 flex-grow mr-2 text-sm bg-slate-100 outline-slate-400"
|
||||
onChange={() => {}}
|
||||
className="border rounded-lg md:rounded-xl p-2 flex-grow mr-2 text-sm bg-slate-100 outline-slate-400"
|
||||
/>
|
||||
<button
|
||||
onClick={handleCopyClick}
|
||||
|
||||
@@ -61,9 +61,11 @@ export function TopicList({
|
||||
}, [activeTopic, autoscroll]);
|
||||
|
||||
return (
|
||||
<section className="relative w-full h-full bg-blue-400/20 rounded-lg md:rounded-xl px-2 md:px-4 flex flex-col justify-center align-center">
|
||||
<section className="relative w-full h-full bg-blue-400/20 rounded-lg md:rounded-xl p-2 md:px-4 flex flex-col justify-center align-center">
|
||||
{topics.length > 0 ? (
|
||||
<>
|
||||
<h2 className="md:text-lg font-bold mb-2">Topics</h2>
|
||||
|
||||
{autoscroll && (
|
||||
<ScrollToBottom
|
||||
visible={!autoscrollEnabled}
|
||||
@@ -73,13 +75,13 @@ export function TopicList({
|
||||
|
||||
<div
|
||||
id="topics-div"
|
||||
className="overflow-y-auto py-2 h-full"
|
||||
className="overflow-y-auto h-full"
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{topics.map((topic, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className="rounded-none border-solid border-0 border-b-blue-300 border-b last:border-none last:rounded-b-lg p-2 hover:bg-blue-400/20 focus-visible:bg-blue-400/20 text-left block w-full"
|
||||
className="rounded-none border-solid border-0 border-bluegrey border-b last:border-none last:rounded-b-lg p-2 hover:bg-blue-400/20 focus-visible:bg-blue-400/20 text-left block w-full"
|
||||
onClick={() =>
|
||||
setActiveTopic(activeTopic?.id == topic.id ? null : topic)
|
||||
}
|
||||
@@ -108,9 +110,11 @@ export function TopicList({
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="text-center text-gray-500 p-4">
|
||||
Discussion topics will appear here after you start recording. It may
|
||||
take up to 5 minutes of conversation for the first topic to appear.
|
||||
<div className="text-center text-gray-500">
|
||||
Discussion topics will appear here after you start recording.
|
||||
<br />
|
||||
It may take up to 5 minutes of conversation for the first topic to
|
||||
appear.
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
@@ -11,10 +11,14 @@ module.exports = {
|
||||
gridTemplateRows: {
|
||||
layout: "auto auto minmax(0, 1fr)",
|
||||
"mobile-inner": "minmax(0, 2fr) minmax(0, 1fr)",
|
||||
"layout-one": "minmax(0, 1fr) auto",
|
||||
},
|
||||
animation: {
|
||||
"spin-slow": "spin 3s linear infinite",
|
||||
},
|
||||
colors: {
|
||||
bluegrey: "RGB(90, 122, 158)",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
|
||||
Reference in New Issue
Block a user