Conversation
- Add PREDEFINED_QUERIES with 18 filters across 4 categories - Implement global filter persistence via localStorage - Convert /random to full page with configurable game grid - Add comprehensive test suite (69 tests, 100% passing) - Optimize performance with indexes and query caching - Document complete filter system architecture - Remove 'apply globally' checkbox for simpler UX
- Add .github/ and openspec/ to .gitignore - Remove tracked files from these directories - These folders contain local workflow configurations
This reverts commit 7c2aff9.
…est case) Based on this review: > SQL errors on collection detail page The .replace() chain in collections.py for prefixing column names with g. only covers 5 columns (playtime_hours, total_rating, added_at, release_date, nsfw). Filters like "community-favorites" (igdb_rating, igdb_rating_count), "critic-favorites" (aggregated_rating), and "recently-updated" (last_modified) will throw SQL errors when used on collection pages.
Based on this review:
Genre LIKE pattern missing closing quote
In discover.py, library.py (random route), and collections.py:
params.append(f'%"{genre.lower()}%')
Should be:
params.append(f'%"{genre.lower()}"%')
Without the closing ", the pattern %"action% could match unintended substrings.
Based on this review: > Duplicate import in discover.py get_query_filter_counts is imported twice on the same line.
- corrected json import in loop - made bare exception handling less bare Based on these reviews: > Bare except: clauses In collections.py and discover.py, the genre parsing uses bare except: which swallows all exceptions including KeyboardInterrupt and SystemExit. Please use except Exception: at minimum, or better yet except (json.JSONDecodeError, TypeError):. > import json inside a loop In collections.py, import json is inside the genre-parsing loop — should be at the top of the file.
Based on this review:
> TemplateResponse signature change
All TemplateResponse calls were changed from TemplateResponse("template.html", {"request": request, ...}) to TemplateResponse(request, "template.html", {...}). This requires a newer Starlette version. Since we don't pin versions in requirements.txt, this could break depending on the installed version. Can you either pin the minimum required version or keep the old signature?
… button) Based on this review: > Auto-apply conflicts with Apply button The store/genre dropdowns have explicit "Apply" buttons, but filters.js also auto-applies after a 300ms debounce on checkbox changes. Users could get redirected before they finish selecting multiple options. I'd suggest picking one approach — either auto-apply (and remove the button) or manual apply (and remove the debounce).
… button) ; also, changed the filters logic (see filter-system.md) to combine filters with ORs in the same category and with ANDs between categories. Based on this review: > Auto-apply conflicts with Apply button The store/genre dropdowns have explicit "Apply" buttons, but filters.js also auto-applies after a 300ms debounce on checkbox changes. Users could get redirected before they finish selecting multiple options. I'd suggest picking one approach — either auto-apply (and remove the button) or manual apply (and remove the debounce).
Based on this review: > Mobile regression The old index.html had mobile-specific styles transforming dropdowns into bottom sheets. The new filters.css responsive section only does flex-direction: column — the bottom-sheet behavior appears to be lost. Could you verify the filter bar works well on mobile?
Based on these reviews:
> query_filter_counts is always {} for discover, collection detail, and random pages — the Quick Filters dropdown won't show counts on those pages (intentional?)
> Dead .games-grid CSS rule with flex properties in index.html (overridden by the grid definition later — looks like a copy-paste artifact)
…ters Changes the /random endpoint to redirect to a single random game (instead of showing a grid of 12 games), while applying global filters before selection. Changes: - Modified /random route to apply filters then redirect to one game - Added filters.js to all pages with Random links to ensure filter persistence - Removed random.html template and shared-game-cards.css (no longer needed) - Updated documentation to reflect new behavior This addresses PR review feedback requesting the original "surprise me with one game" behavior while maintaining global filter support. > /random endpoint behavior change This currently redirects to a single random game detail page. The PR changes it to render a full grid of 12 games. I'd like to discuss this — I'm not sure I want to lose the "surprise me with one game" behavior. Could we keep the old redirect as the default and add the grid as a separate route (e.g. /random?grid=true) or a different path?
Phase 1 & 2: Backend implementation for unified labels system - Migrate collections to labels with new fields (type, color, icon, system) - Add priority (high/medium/low) and personal_rating (0-10) columns to games - Create system_labels service with 5 auto playtime tags - Add API endpoints for priority and personal rating (single + bulk) - Add manual playtime tag endpoint for non-Steam games - Update delete endpoints to use game_labels instead of collection_games Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 3 (partial): Frontend UI for priority and personal rating - Add Priority and Personal Rating buttons to floating action bar - Add dropdown menus for selecting priority (high/medium/low) and rating (0-10) - Add JavaScript functions for bulk operations (bulkSetPriority, bulkSetPersonalRating) - Add CSS styling for new buttons and dropdown menus - Auto-close dropdowns when clicking outside Next: Add badges display on game cards, update filters, add sync hooks Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added visual badges on game cards to display: - Priority indicators (high/medium/low) with colored circles - Personal rating badges with star icons and numeric value Badges are positioned in top-left corner of card covers with: - Backdrop blur for readability - Responsive sizing for different grid sizes - Proper z-index layering above cover images Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Migrated all collections endpoints to use the new unified labels system: - Changed table references from collections/collection_games to labels/game_labels - Added type='collection' filters to all queries - Updated column references (c.* to l.*, cg.* to gl.*) - Maintained all existing API endpoints and functionality Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added "Playtime Tag" button to action bar with dropdown menu: - 5 manual playtime tags: never-launched, just-tried, played, well-played, heavily-played - Remove tag option - Styled with blue color scheme to differentiate from priority/rating - JavaScript function calls individual game endpoint for each selected game - Auto-reloads page after applying tags Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed JavaScript parameter from tag_name to label_name to match the Pydantic model definition in api_metadata.py Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes: - Changed all system label names from French to English - Added migration logic in ensure_system_labels() to update existing labels - Fixed manual playtime tag endpoint to handle null (remove tag) - Updated template dropdown to use English label names - All 5 playtime tags now visible in UI Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Show dropdown first with visibility:hidden to get actual height - Position dropdown above button using calculated height - Close other dropdowns when opening playtime menu - Prevents menu from being cut off at bottom of screen Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added toast notification system with slide-in animations - Toasts appear in top-right corner without interrupting workflow - Success (green), error (red), and info (blue) variants - Auto-dismiss after 3 seconds or click to close manually - Replaced all alert() calls with showToast() - More elegant and less disruptive UX Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Hold Shift and click to select all games between two selections - More efficient for selecting multiple consecutive games - Tracks last selected card for range calculation - Works seamlessly with normal click selection Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added inline action buttons on game detail page for: - Set Priority (high/medium/low/none) - Personal Rating (0-10) - Playtime Tag (5 system tags + remove) Features: - Compact button design integrated in hero section - Dropdown menus for each action - Toast notifications for feedback - Auto-reload after changes - No need to go to library for tagging single games Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
Hi @sam1am! |
Merge MAIN branch into feat-global-filters (11 conflicted files resolved). Integrate 7 major features from both branches: From MAIN branch: - Add 2-tier caching system (memory + database with 15min/24h TTL) - Add 4 advanced filters (collection, ProtonDB tier, exclude streaming, no IGDB) - Add Xbox integration with secure authentication system - Refactor CSS architecture (shared game cards, filter styles, discover hero) - Add PWA meta tags and manifest for mobile support - Add system labels auto-tagging for Steam playtime - Add Docker environment detection From feat-global-filters branch: - Add 18 predefined filters with OR/AND logic - Add global filter persistence (localStorage + URL fusion) - Add random page with filter support - Add comprehensive filter UI with counts Post-merge quality assurance: - Add test_advanced_filters.py (15 tests for advanced filters) - Add test_caching_system.py (19 tests for 2-tier cache) - Update CHANGELOG.md with comprehensive merge documentation - Run ruff check --fix (16 style issues auto-fixed) - All 121 tests passing - Split requirements: production (requirements.txt) vs dev (requirements-dev.txt) Technical details: - New files: test_advanced_filters.py, test_caching_system.py, requirements-dev.txt, web/routes/app_auth.py, web/services/auth_service.py, and more - Modified files: library.py, discover.py, collections.py, filters.js, database.py, requirements.txt, and more - Database schema: Add auth tables, cache tables, system labels support - Documentation: merge_MAIN_to_FEAT_GLOBAL_FILTERS.md (temporary, will be removed post-PR) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ctions Combine labels/metadata system with global filters and 2-tier caching. Merged features from both branches: - Labels system: 62 tests, API endpoints, complete documentation (HEAD) - Global filters: 18 predefined queries + 4 advanced filters (feat-global-filters) - 2-tier caching: Memory (15min) + DB (24h) for IGDB data (feat-global-filters) - Xbox integration + auth system + Docker detection (feat-global-filters) - CSS refactoring: Externalized 2000+ lines inline CSS (feat-global-filters) Conflict resolution: - web/main.py: Merged labels DB setup + auth config imports - web/routes/library.py: Combined personal_rating/priority sorting + advanced filters (collection, ProtonDB, noIGDB) + PRAGMA validation - CHANGELOG.md: Unified Added sections from both branches UI improvements: - Improved button visibility on game detail page (tag-pill.unset, edit-more-btn, edit-action-btn) - Better contrast with background images (darker backgrounds + backdrop blur) Test results: 211 tests passing (121 + 90) - 121 from feat-global-filters (filters, caching, performance) - 90 from feat-multiple-edit-tags-and-actions (labels, metadata, migrations) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Augmente l'opacité et ajoute un effet de flou pour les boutons d'édition sur la page de détail des jeux, améliorant leur visibilité sur les images de fond. Modifications CSS: - tag-pill.unset: rgba(13,13,26,0.75) + backdrop-filter blur(4px) - edit-more-btn: rgba(13,13,26,0.75) + backdrop-filter blur(4px) - États hover améliorés avec meilleur contraste
|
Hi @sam1am! Hope you like these changes! |
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive user-editable metadata and filtering capabilities to the game library. It introduces priority levels, personal ratings (0-10), automatic gameplay tagging based on playtime, and extensive predefined query filters organized into categories. The PR also includes a complete migration from the old collections system to a unified labels system.
Changes:
- New labels/metadata system with priority, personal ratings, and manual playtime tags
- 18 predefined query filters with OR/AND logic across 4 categories (Gameplay, Ratings, Dates, Content)
- Automatic gameplay tagging for Steam games based on playtime thresholds
- Bulk operations API for managing multiple games simultaneously
- Comprehensive test coverage (177 tests) and documentation
Reviewed changes
Copilot reviewed 54 out of 57 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| web/utils/filters.py | New filter system with SQL query building and prefix handling |
| web/utils/helpers.py | Query filter count aggregation function |
| web/routes/library.py | Integration of filters, priority/rating sorting, random game with filters |
| web/routes/collections.py | Migration to labels system, filter support in collections |
| web/routes/api_metadata.py | REST API endpoints for metadata operations |
| web/routes/settings.py | Template response signature update |
| web/routes/sync.py | Auto-tagging integration after Steam sync |
| web/services/system_labels.py | System labels management and auto-tagging logic |
| web/main.py | Database initialization with migrations |
| web/database.py | Collections→labels migration, metadata columns, indexes |
| web/templates/* | UI updates for filters, collections, navigation |
| web/static/css/* | Extracted CSS to external files |
| tests/* | Comprehensive test suite for new features |
| docs/* | API documentation and user guides |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _apply_prefix(sql, table_prefix): | ||
| """Apply table prefix to column names and table references in SQL.""" | ||
| if not table_prefix: | ||
| return sql | ||
| # Replace explicit table references first | ||
| sql = sql.replace("games.id", f"{table_prefix}id") | ||
| sql = sql.replace("games.store", f"{table_prefix}store") | ||
| sql = sql.replace("games.priority", f"{table_prefix}priority") | ||
| sql = sql.replace("games.personal_rating", f"{table_prefix}personal_rating") | ||
| # Replace bare column names | ||
| for col in _PREFIXABLE_COLUMNS: | ||
| sql = sql.replace(col, f'{table_prefix}{col}') | ||
| return sql |
There was a problem hiding this comment.
The _apply_prefix function uses simple string replacement which could cause issues if column names appear as substrings in other contexts. For example, sql.replace("id", f"{table_prefix}id") would incorrectly replace "id" in words like "invalid" or "identity". Consider using word boundary matching or regex to ensure only complete column names are replaced.
| return templates.TemplateResponse( | ||
| request, | ||
| "settings.html", | ||
| { | ||
| "request": request, | ||
| "settings": settings, | ||
| "success": success_flag, | ||
| "hidden_count": hidden_count, | ||
| "is_docker": is_docker, | ||
| "auth_enabled": ENABLE_AUTH | ||
| } | ||
| ) |
There was a problem hiding this comment.
The change from templates.TemplateResponse("settings.html", {"request": request, ...}) to templates.TemplateResponse(request, "settings.html", {...}) changes the function signature. Verify this is compatible with the version of FastAPI specified in requirements.txt (>=0.89.0). The new signature is correct for FastAPI 0.100+, but may cause issues with older versions.
📋 Overview
This PR adds editable tags for the games.
Tags are grouped by categories:
The tags are visible in both the library and the details pages.
In addition, the user is able to select multiple games in the library view (either by individually clicking on them after started the selection mode, or by shift and/or control clicking to select an interval).
I've also added "hide", "mark NSFW" and "delete" actions to the edit bar.
✅ Test Coverage: 177/177 passing
New Test Files (65 tests)
tests/test_api_metadata_endpoints.py- 35 testsComplete API integration tests covering all metadata endpoints:
tests/test_database_migrations.py- 12 testsDatabase schema migrations and constraints:
tests/test_edge_cases_labels.py- 13 testsEdge cases and performance tests:
tests/test_system_labels_auto_tagging.py- +5 testsManual tag persistence tests added to existing suite:
📚 Documentation
New Files
docs/api-metadata-endpoints.md(~700 lines)Complete API reference with:
docs/contributing-labels-system.md(~600 lines)Developer contribution guide:
Enhanced Files
docs/system-labels-auto-tagging.md(+~400 lines)User documentation enriched with:
🔧 Technical Fixes
get_dbimport in test fixtures (useweb.dependenciesinstead ofweb.database)check_same_thread=Falseto SQLite test connections for FastAPI compatibility📊 CHANGELOG
Updated
CHANGELOG.mdwith complete documentation of:🎯 Testing
All tests pass successfully:
pytest tests/ -v # 177 passed in ~15sTest coverage includes:
🔍 Code Quality
📝 Checklist
🚀 Ready for Review
This PR completes the test and documentation requirements for the labels/metadata system. All functionality is thoroughly tested and documented for both users and developers.