Files
DanceVideos/app/views/label_views.py

108 lines
4.2 KiB
Python

import streamlit as st
import db
from models import Video
from views.video_views import show_video_row
from controllers.label_controller import label_widget
def video_filter_sidebar(unlabeled=False):
"""Affiche les filtres dans la barre latérale et renvoie les paramètres de recherche."""
st.sidebar.header("⚙️ Filtres et affichage")
max_height = st.sidebar.slider("Hauteur max (px)", 100, 800, 300, 50)
all_labels = db.load_labels()
unique_days = db.get_unique_days()
unique_difficulties = db.get_unique_difficulties()
unique_addresses = db.get_unique_addresses()
selected_labels = st.sidebar.multiselect("Filtrer par labels", all_labels)
label_logic = st.sidebar.radio(
"Logique entre labels",
["OR", "AND"],
help="Détermine si la vidéo doit contenir tous les labels sélectionnés (AND) ou au moins un (OR)"
)
day_filter = st.sidebar.selectbox("Jour de la semaine", ["Tous"] + unique_days)
difficulty_filter = st.sidebar.selectbox("Niveau de difficulté", ["Tous"] + unique_difficulties)
address_keyword = st.sidebar.selectbox("Adresse (mot-clé)", [""] + unique_addresses)
start_date = st.sidebar.date_input("Date de début", value=None)
end_date = st.sidebar.date_input("Date de fin", value=None)
show_unlabeled_only = st.sidebar.checkbox("Afficher uniquement les vidéos sans labels", value=unlabeled)
return dict(
max_height=max_height,
selected_labels=selected_labels,
label_logic=label_logic,
day_filter=None if day_filter == "Tous" else day_filter,
difficulty_filter=difficulty_filter,
address_keyword=address_keyword if address_keyword else None,
start_date=start_date.isoformat() if start_date else None,
end_date=end_date.isoformat() if end_date else None,
show_unlabeled_only=show_unlabeled_only
)
def video_list_view(filters: dict, editable_labels=True, editable_difficulty=True, editable_alias=True, playlist=None):
"""Affiche les vidéos selon les filtres fournis."""
st.markdown(f"""
<style>
img, video {{
max-height: {filters["max_height"]}px !important;
object-fit: contain;
border-radius: 8px;
transition: all 0.3s ease-in-out;
}}
.unlabeled {{
border: 3px solid #f39c12;
box-shadow: 0 0 10px #f39c12;
border-radius: 10px;
padding: 5px;
margin-bottom: 10px;
}}
</style>
""", unsafe_allow_html=True)
df_videos = db.search_videos(
label_names=filters["selected_labels"],
label_logic=filters["label_logic"],
day_of_week=filters["day_filter"],
address_keyword=filters["address_keyword"],
start_date=filters["start_date"],
end_date=filters["end_date"],
difficulty=filters["difficulty_filter"]
)
if df_videos.empty:
st.warning("Aucune vidéo trouvée avec ces critères.")
return []
# préchargement des labels
video_labels_map = {row["file_name"]: db.load_video_labels(row["file_name"]) for _, row in df_videos.iterrows()}
if filters["show_unlabeled_only"]:
df_videos = df_videos[df_videos["file_name"].apply(lambda fn: not video_labels_map.get(fn))]
videos = [Video(**row) for _, row in df_videos.iterrows()]
# lazy loading
page_size = 20
st.session_state.setdefault("video_page", 1)
start = 0
end = st.session_state.video_page * page_size
subset = videos[start:end]
# affichage
for video in subset:
preselected = video_labels_map.get(video.file_name, [])
css_class = "unlabeled" if not preselected else ""
with st.container():
st.markdown(f"<div class='{css_class}'>", unsafe_allow_html=True)
show_video_row(video, preselected, editable_labels, editable_difficulty, editable_alias, playlist)
st.markdown("</div>", unsafe_allow_html=True)
# lazy loading bouton
if end < len(videos):
if st.button("📦 Charger plus de vidéos"):
st.session_state.video_page += 1
st.rerun()
else:
st.info("✅ Toutes les vidéos sont affichées.")
return subset