Feature: Sélection multiple d'instruments dans les filtres
Frontend: - FilterPanel: Remplacer select par checkboxes pour instruments - Zone scrollable (max-height 12rem) pour la liste - Affichage des instruments sélectionnés dans résumé filtres actifs Backend: - API tracks: Nouveau paramètre instruments (List[str]) - Backward compatible avec ancien paramètre instrument - CRUD: Filtrage AND (track doit avoir TOUS les instruments) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ async def get_tracks(
|
||||
has_vocals: Optional[bool] = None,
|
||||
key: Optional[str] = None,
|
||||
instrument: Optional[str] = None,
|
||||
instruments: Optional[List[str]] = Query(None),
|
||||
tempo_range: Optional[str] = Query(None, regex="^(slow|medium|fast)$"),
|
||||
sort_by: str = Query("analyzed_at", regex="^(analyzed_at|tempo_bpm|duration_seconds|filename|energy)$"),
|
||||
sort_desc: bool = True,
|
||||
@@ -42,7 +43,8 @@ async def get_tracks(
|
||||
energy_max: Maximum energy
|
||||
has_vocals: Filter by vocal presence
|
||||
key: Filter by musical key
|
||||
instrument: Filter by instrument
|
||||
instrument: Filter by instrument (deprecated, use instruments)
|
||||
instruments: Filter by multiple instruments (must have ALL)
|
||||
tempo_range: Filter by tempo range (slow: <100, medium: 100-140, fast: >140)
|
||||
sort_by: Field to sort by
|
||||
sort_desc: Sort descending
|
||||
@@ -61,6 +63,9 @@ async def get_tracks(
|
||||
elif tempo_range == "fast":
|
||||
bpm_min = 140.0 if bpm_min is None else max(bpm_min, 140.0)
|
||||
|
||||
# Use instruments if provided, otherwise fall back to instrument
|
||||
final_instruments = instruments if instruments else ([instrument] if instrument else None)
|
||||
|
||||
tracks, total = crud.get_tracks(
|
||||
db=db,
|
||||
skip=skip,
|
||||
@@ -73,7 +78,7 @@ async def get_tracks(
|
||||
energy_max=energy_max,
|
||||
has_vocals=has_vocals,
|
||||
key=key,
|
||||
instrument=instrument,
|
||||
instruments=final_instruments,
|
||||
sort_by=sort_by,
|
||||
sort_desc=sort_desc,
|
||||
)
|
||||
|
||||
@@ -104,7 +104,7 @@ def get_tracks(
|
||||
energy_max: Optional[float] = None,
|
||||
has_vocals: Optional[bool] = None,
|
||||
key: Optional[str] = None,
|
||||
instrument: Optional[str] = None,
|
||||
instruments: Optional[List[str]] = None,
|
||||
sort_by: str = "analyzed_at",
|
||||
sort_desc: bool = True,
|
||||
) -> Tuple[List[AudioTrack], int]:
|
||||
@@ -122,7 +122,7 @@ def get_tracks(
|
||||
energy_max: Maximum energy (0-1)
|
||||
has_vocals: Filter by vocal presence
|
||||
key: Filter by musical key
|
||||
instrument: Filter by instrument
|
||||
instruments: Filter by instruments (track must have ALL instruments in the list)
|
||||
sort_by: Field to sort by
|
||||
sort_desc: Sort descending if True
|
||||
|
||||
@@ -168,8 +168,10 @@ def get_tracks(
|
||||
if key:
|
||||
query = query.filter(AudioTrack.key == key)
|
||||
|
||||
if instrument:
|
||||
query = query.filter(AudioTrack.instruments.any(instrument))
|
||||
if instruments:
|
||||
# Track must have ALL specified instruments
|
||||
for instrument in instruments:
|
||||
query = query.filter(AudioTrack.instruments.any(instrument))
|
||||
|
||||
# Get total count before pagination
|
||||
total = query.count()
|
||||
|
||||
Reference in New Issue
Block a user