From 7f20ba3ffa59f0cd42727e97ceb0371548c1859b Mon Sep 17 00:00:00 2001 From: mbrucedogs Date: Sat, 26 Jul 2025 19:52:31 -0500 Subject: [PATCH] Signed-off-by: mbrucedogs --- PRD.md | 4 + web/app.py | 86 ++++++ web/templates/index.html | 14 + web/templates/remaining_songs.html | 402 +++++++++++++++++++++++++++++ 4 files changed, 506 insertions(+) create mode 100644 web/templates/remaining_songs.html diff --git a/PRD.md b/PRD.md index bc0af63..4934a4a 100644 --- a/PRD.md +++ b/PRD.md @@ -255,6 +255,7 @@ KaraokeMerge/ - **Search & Filter**: Real-time search across artists, titles, and paths - **Responsive Design**: Mobile-friendly interface - **Easy Startup**: Automated dependency checking and browser launch +- **Remaining Songs View**: Separate page to browse all songs that remain after cleanup #### **Media Preview & Playback** - **Video Playback**: Direct MP4 video playback in modal popup for previewing karaoke videos @@ -308,6 +309,7 @@ KaraokeMerge/ #### **Key Components** - **`web/app.py`**: Flask application with API endpoints - **`web/templates/index.html`**: Main web interface template +- **`web/templates/remaining_songs.html`**: Remaining songs browsing interface - **`start_web_ui.py`**: Startup script with dependency management ### 7.3 API Endpoints @@ -317,6 +319,7 @@ KaraokeMerge/ - **`/api/stats`**: Get statistical analysis of the song collection - **`/api/artists`**: Get list of artists for filtering - **`/api/mp3-songs`**: Get MP3 songs that remain after cleanup +- **`/api/remaining-songs`**: Get all remaining songs with pagination and filtering - **`/api/config`**: Get current configuration settings #### **Priority Management Endpoints** @@ -412,6 +415,7 @@ data/preferences/ - [x] Create responsive design with Bootstrap 5 - [x] Add file path normalization for corrupted paths - [x] Implement change tracking and save button management +- [x] Create remaining songs browsing page with filtering and video preview #### **Advanced Features** - [x] Multi-format support (MP3, CDG, MP4) diff --git a/web/app.py b/web/app.py index 0d6b4c0..5330d85 100644 --- a/web/app.py +++ b/web/app.py @@ -191,6 +191,11 @@ def index(): """Main dashboard page.""" return render_template('index.html') +@app.route('/remaining-songs') +def remaining_songs(): + """Page showing remaining songs after cleanup.""" + return render_template('remaining_songs.html') + @app.route('/api/duplicates') def get_duplicates(): """API endpoint to get duplicate data.""" @@ -435,6 +440,87 @@ def get_mp3_songs(): return jsonify(mp3_song_list) +@app.route('/api/remaining-songs') +def get_remaining_songs(): + """Get all remaining songs (MP4 and MP3) after cleanup with pagination.""" + try: + all_songs = load_json_file(os.path.join(DATA_DIR, 'allSongs.json')) + skip_songs = load_json_file(os.path.join(DATA_DIR, 'reports', 'skip_songs_detailed.json')) + + if not all_songs: + return jsonify({'error': 'No all songs data found'}), 404 + + if not skip_songs: + skip_songs = [] + + # Get pagination parameters + page = request.args.get('page', 1, type=int) + per_page = request.args.get('per_page', 50, type=int) + search = request.args.get('search', '').lower() + file_type_filter = request.args.get('file_type', 'all') + artist_filter = request.args.get('artist', '') + + # Create a set of paths that are being skipped + skip_paths = {song['path'] for song in skip_songs} + + # Filter for songs that are NOT being skipped + remaining_songs = [] + for song in all_songs: + path = song.get('path', '') + if path not in skip_paths: + # Apply file type filter + if file_type_filter != 'all': + if file_type_filter == 'mp4' and not path.lower().endswith('.mp4'): + continue + elif file_type_filter == 'mp3' and not path.lower().endswith(('.mp3', '.cdg')): + continue + + # Apply search filter + if search: + title = song.get('title', '').lower() + artist = song.get('artist', '').lower() + if search not in title and search not in artist: + continue + + # Apply artist filter + if artist_filter: + artist = song.get('artist', '').lower() + if artist_filter.lower() not in artist: + continue + + remaining_songs.append({ + 'title': song.get('title', 'Unknown'), + 'artist': song.get('artist', 'Unknown'), + 'path': song.get('path', ''), + 'file_type': get_file_type(song.get('path', '')), + 'channel': extract_channel(song.get('path', '')) + }) + + # Sort by artist, then by title + remaining_songs.sort(key=lambda x: (x['artist'].lower(), x['title'].lower())) + + # Calculate pagination + total_songs = len(remaining_songs) + total_pages = (total_songs + per_page - 1) // per_page + start_idx = (page - 1) * per_page + end_idx = start_idx + per_page + + # Get songs for current page + page_songs = remaining_songs[start_idx:end_idx] + + return jsonify({ + 'songs': page_songs, + 'pagination': { + 'current_page': page, + 'per_page': per_page, + 'total_songs': total_songs, + 'total_pages': total_pages + } + }) + + except Exception as e: + return jsonify({'error': str(e)}), 500 + @app.route('/api/download/mp3-songs') def download_mp3_songs(): diff --git a/web/templates/index.html b/web/templates/index.html index 886dbc9..6823548 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -478,6 +478,20 @@ +
+ +
+ + + Browse all remaining songs (MP4 and MP3) after cleanup with filtering, + search, and video preview capabilities. + +
+
diff --git a/web/templates/remaining_songs.html b/web/templates/remaining_songs.html new file mode 100644 index 0000000..4896444 --- /dev/null +++ b/web/templates/remaining_songs.html @@ -0,0 +1,402 @@ + + + + + + Remaining Songs After Cleanup - Karaoke Library + + + + + +
+ +
+
+
+
+ + Back to Duplicates + +

Remaining Songs After Cleanup

+
+
+ All songs that remain after duplicate removal +
+
+
+
+ + +
+
+
+
+

-

+

Total Songs

+
+
+
+
+
+
+

-

+

MP4 Videos

+
+
+
+
+
+
+

-

+

MP3/CDG Files

+
+
+
+
+
+
+

-

+

Unique Artists

+
+
+
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ +

Loading remaining songs...

+
+
+ + +
+
+ +
+
+
+ + + + + + + + \ No newline at end of file