Skip to content

feat: auto-select processed meeting to show transcript immediately#79

Merged
NotYuSheng merged 16 commits intomainfrom
feat/auto-select-processed-meeting
Aug 7, 2025
Merged

feat: auto-select processed meeting to show transcript immediately#79
NotYuSheng merged 16 commits intomainfrom
feat/auto-select-processed-meeting

Conversation

@NotYuSheng
Copy link
Copy Markdown
Owner

Summary

This PR enhances user experience by automatically selecting a meeting after successful audio processing, ensuring the transcript appears immediately without requiring manual selection.


Changes Made

  • Automatically set selectedMeetingId in both uploadFile and processAudio functions
  • Meeting is selected immediately after successful processing completion
  • Eliminates the need for users to manually click on the meeting button
  • Transcript and summary appear automatically upon processing completion

Context / Rationale

Previously, users had to manually click on a meeting button after audio processing to view the transcript. This created an unnecessary friction point in the user experience. This enhancement:

  1. Streamlines the workflow by automatically showing results
  2. Reduces user interaction steps from processing to viewing
  3. Provides immediate feedback that processing completed successfully
  4. Improves overall application usability

Related Docs or References

  • UX improvement focused on reducing user friction
  • No breaking changes, purely additive enhancement

General Checklist

  • I have tested these changes locally
  • I have updated relevant documentation or added comments where needed
  • I have linked relevant issues and tagged reviewers
  • I have followed coding conventions and naming standards

NotYuSheng and others added 16 commits August 6, 2025 09:07
- Add CSS shadow variables for light and dark modes
- Apply shadows to header card, main cards, and buttons
- Add subtle hover animations with lift effect on buttons
- Style transcript entries with shadows and rounded corners
- Enhance visual hierarchy and modern design aesthetics

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add subtle opacity reduction (50%) for disabled buttons
- Include not-allowed cursor for better UX indication
- Prevent hover animations on disabled state
- Clean, minimal approach without color changes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Slow down particle movement speed from 6 to 2 for subtler motion
- Add organizational color variety to particles using brand palette
- Keep original white connecting lines with full opacity unchanged
- Particles now use: #2998D5, #265289, #75797C, #bba88e, #c42030, #FFFFFF

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed sun icon visibility in light mode (☀️)
- Corrected CSS logic for checked/unchecked states
- Light mode: sun icon on left with blue gradient
- Dark mode: moon icon on right with gray gradient
- Smooth transitions between states with proper icon positioning

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace flat colors with subtle linear gradients for visual depth
- Add gradient backgrounds to app container, cards, and components
- Enhance button styling with gradient backgrounds and hover effects
- Improve transcript entries with gradient backgrounds
- Maintain organizational color palette while adding modern visual appeal
- Keep accessibility and contrast standards intact

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add professional styling to model selector dropdown
- Implement proper focus and hover states with organizational colors
- Use solid backgrounds for better cross-browser compatibility
- Improve responsive layout with better spacing and alignment
- Add consistent typography using Barlow font family
- Support both light and dark theme modes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace plain #bba88e borders with subtle gradient border effects
- Use CSS pseudo-elements for sophisticated gradient border technique
- Fix rectangular shadow issue by moving shadows to pseudo-elements
- Apply proper border-radius calculations for clean rounded corners
- Add theme-aware gradient variations for light and dark modes
- Improve visual depth and premium appearance of all cards

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove ugly red color (#c42030) from particle palette
- Increase particle opacity from 1.0 to 0.9 for much sharper appearance
- Make connecting lines more prominent (opacity 0.8, width 2.5px)
- Use darker shade of #bba88e (#8a7c6b) for connecting lines
- Reduce app background opacity to 50-60% so particles show through
- Improve particle backgrounds with more contrasting gradients
- Clean color palette: #2998D5, #265289, #75797C, #bba88e, #FFFFFF

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Convert recording, upload, and transcription buttons to discrete red design
- Use #F4393B for discrete buttons with icon-only interface and tooltips
- Implement prominent transcription button (#D32F2F) when file is uploaded
- Add "Process Audio" text to transcription button for better UX clarity
- Fix CSS specificity issues with \!important to override gradient backgrounds
- Ensure consistent button sizing (2.5rem width) across all states
- Support both light and dark mode themes with proper red color scheme

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace confusing MicOff icon with Square icon for stop recording
- Fix recording timer vertical alignment with action buttons
- Move recording indicator inside button group for better layout
- Add smooth hover effects to transcript/summary tabs
- Implement tab-like appearance with rounded top corners
- Add subtle blue background and border hints on tab hover
- Improve overall controls container alignment and spacing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Implement pause/resume recording functionality with MediaRecorder API
- Add professional HTML5 audio player with timeline scrubbing and volume control
- Enable manual control over when to process recorded audio (no auto-processing)
- Add discard recording option for better user control
- Improve button state management for different recording phases:
  * Default: [Mic] [Upload] [Process Audio]
  * Recording: [Pause] [Stop] [Process Audio]
  * Preview: [Trash] [Upload] [Process Audio] + Audio Player
- Add visual feedback for paused recording state (orange dot, timer shows "(Paused)")
- Style audio player to match app theme with custom controls
- Handle proper cleanup of audio URLs to prevent memory leaks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Refactored Dockerfile to use multi-stage build with nginx
- Added nginx.conf with production-ready configuration including gzip, security headers, and API proxying
- Updated docker-compose.yml port mapping from 3000:3000 to 80:80
- Removed unnecessary volume mounts for frontend container
- This addresses HTTPS requirements for getUserMedia API and improves production deployment

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove invalid 'must-revalidate' value from gzip_proxied directive
- Change frontend port mapping from 80:80 to 3000:80
- Comment out GPU deployment configuration

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add audio player that displays when file is uploaded
- Allow users to preview uploaded audio before processing
- Add discard functionality for uploaded files
- Integrate same audio controls as recording feature
- Auto-clear uploaded file after processing
- Update button states to handle upload workflow

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace emoji trash icon with Trash2 React icon component
- Change button style from btn-danger to btn-discrete for consistency
- Add tooltip for better user experience
- Use btn-icon class for consistent icon styling
- Match visual style of other action buttons (mic, upload)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Automatically select meeting after successful audio processing
- Set selectedMeetingId in both uploadFile and processAudio functions
- Ensures transcript appears immediately without manual selection
- Improves user experience by eliminating extra click step

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @NotYuSheng, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

I've implemented a significant user experience enhancement that automatically selects a meeting after its audio has been successfully processed. This change ensures that the transcript and summary are displayed immediately, eliminating the need for manual selection and streamlining the workflow from audio upload/recording to viewing results. Additionally, I've refined the audio handling UI, optimized the Docker deployment for the frontend with Nginx, and updated the overall visual styling of the application.

Highlights

  • User Experience Enhancement: I've implemented automatic selection of processed meetings to immediately display transcripts and summaries, significantly improving user workflow by removing the need for manual selection after audio processing.
  • Enhanced Audio Handling UI/UX: The frontend's audio recording and upload interface has been overhauled, introducing pause/resume functionality for recordings, audio previews for both recorded and uploaded files, and clear options to discard audio, making the interaction more intuitive.
  • Docker and Deployment Optimization: The frontend Docker setup has been migrated to a multi-stage build utilizing Nginx, which improves serving efficiency, reduces image size, and incorporates robust Nginx configurations for security headers, gzip compression, caching, and API proxying.
  • Styling and Dependency Updates: Core frontend dependencies, including react-router-dom, have been updated, and the application's visual styling has been refined with new linear gradients, subtle box shadows, and redesigned button components for a more modern look and feel.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant improvements to the frontend, including a major UI overhaul, a move to a production-ready multi-stage Docker build with Nginx, and the implementation of the core feature to auto-select a meeting after processing. The changes greatly enhance user experience and the application's architecture. My review includes feedback on a potential security issue in the Nginx configuration, CSS maintainability, and several opportunities to improve the robustness and readability of the React component's logic.

Comment thread frontend/nginx.conf

# Handle preflight requests for CORS
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using * for Access-Control-Allow-Origin is insecure as it allows any website to make requests to your API. In a production environment, you should restrict this to the specific domain of your frontend application to prevent Cross-Site Request Forgery (CSRF) and other attacks.

Comment thread docker-compose.yml
Comment on lines +21 to +27
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all
# capabilities: [gpu]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The GPU resource allocation for the backend service has been commented out. If this service relies on a GPU for performance (e.g., for Whisper model inference), this change could significantly degrade performance in a production environment. Please clarify if this is an intentional change for all environments or just for local development without a GPU.

Comment on lines +179 to +190
.btn.btn-discrete {
background: var(--btn-discrete) !important;
color: #fff;
padding: 0.5rem;
width: 2.5rem;
justify-content: center;
flex-shrink: 0;
}

.btn.btn-discrete:hover {
background: var(--btn-discrete-hover) !important;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of !important can make CSS difficult to debug and maintain, as it breaks the natural cascading of styles. It's better to increase selector specificity if you need to override styles. For example, you could use a more specific selector for these discrete buttons to avoid needing !important.

Comment on lines +46 to +49
// eslint-disable-next-line no-unused-vars
const [isPlayingRecording, setIsPlayingRecording] = useState(false);
// eslint-disable-next-line no-unused-vars
const [isPlayingUpload, setIsPlayingUpload] = useState(false);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The state variables isPlayingRecording and isPlayingUpload are set but their values are never used. The eslint-disable-next-line comments indicate this is known. If these are not needed for any logic, they and their corresponding onPlay/onPause/onEnded handlers on the <audio> elements (lines 818-820 and 832-834) should be removed to avoid dead code and simplify the component's state.

Comment on lines 703 to 801
<div className="button-group">
<button
onClick={isRecording ? stopRecording : startRecording}
className={`btn ${isRecording ? "btn-danger" : "btn-primary"}`}
>
{isRecording ? (
<MicOff className="btn-icon" />
) : (
<Mic className="btn-icon" />
)}
{isRecording ? "Stop Recording" : "Start Recording"}
</button>
{!isRecording && !recordedAudio && !selectedFile ? (
<>
<button
onClick={startRecording}
className="btn btn-discrete"
title="Start Recording"
>
<Mic className="btn-icon" />
</button>

<button
onClick={() => fileInputRef.current?.click()}
className="btn btn-secondary"
>
<Upload className="btn-icon" />
{selectedFile ? "Change Audio File" : "Upload Audio File"}
</button>
<button
onClick={() => fileInputRef.current?.click()}
className="btn btn-discrete"
title="Upload Audio File"
>
<Upload className="btn-icon" />
</button>
</>
) : isRecording ? (
<>
<button
onClick={isPaused ? resumeRecording : pauseRecording}
className="btn btn-discrete"
title={isPaused ? "Resume Recording" : "Pause Recording"}
>
{isPaused ? (
<Play className="btn-icon" />
) : (
<Pause className="btn-icon" />
)}
</button>

<button
onClick={stopRecording}
className="btn btn-discrete"
title="Stop Recording"
>
<Square className="btn-icon" />
</button>
</>
) : recordedAudio ? (
<>
<button
onClick={discardRecording}
className="btn btn-discrete"
title="Discard Recording"
>
<Trash2 className="btn-icon" />
</button>

<button
onClick={() => fileInputRef.current?.click()}
className="btn btn-discrete"
title="Upload Audio File"
>
<Upload className="btn-icon" />
</button>
</>
) : selectedFile ? (
<>
<button
onClick={discardUpload}
className="btn btn-discrete"
title="Discard Upload"
>
<Trash2 className="btn-icon" />
</button>

<button
onClick={startRecording}
className="btn btn-discrete"
title="Start Recording"
>
<Mic className="btn-icon" />
</button>
</>
) : null}

<button
onClick={uploadFile}
disabled={!selectedFile || loading}
className={`btn ${selectedFile ? "btn-primary" : "btn-disabled"}`}
onClick={recordedAudio ? processRecordedAudio : uploadFile}
disabled={(!selectedFile && !recordedAudio) || loading}
className={`btn ${(selectedFile || recordedAudio) && !loading ? "btn-discrete-prominent" : "btn-discrete"}`}
title={loading ? "Processing..." : "Process Audio"}
>
<Send className="btn-icon" />
{loading ? "Transcribing..." : "Start Transcription"}
{((selectedFile || recordedAudio) && !loading) ? "Process Audio" : ""}
</button>
</div>

{isRecording && (
<div className="recording-indicator">
<div className="recording-dot"></div>
<span className="recording-time">
{formatTime(recordingTime)}
</span>
</div>
)}
{isRecording && (
<div className="recording-indicator">
<div className={`recording-dot ${isPaused ? 'paused' : ''}`}></div>
<span className="recording-time">
{formatTime(recordingTime)} {isPaused ? '(Paused)' : ''}
</span>
</div>
)}
</div>
</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for rendering the control buttons is complex and can lead to a confusing user experience. For instance, both recording and upload options are available simultaneously after an action, which could lead to accidental data loss (e.g., starting a new recording when a file is staged for upload). Consider simplifying this into a more linear workflow. Refactoring the large conditional rendering block into smaller, state-specific components (e.g., <InitialControls />, <RecordingControls />) would also greatly improve the code's readability and maintainability.

@NotYuSheng NotYuSheng merged commit 7d641ba into main Aug 7, 2025
1 check failed
@NotYuSheng NotYuSheng deleted the feat/auto-select-processed-meeting branch August 7, 2025 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant