engine / page_modules /validation.py
VeuReu's picture
Upload 6 files
d345661 verified
raw
history blame
10.3 kB
"""UI logic for the "Validació" page."""
from __future__ import annotations
from datetime import datetime
from pathlib import Path
from typing import Dict
import streamlit as st
def _build_candidates(runtime_videos: Path) -> Path:
candidates = [
runtime_videos,
Path(__file__).resolve().parent.parent / "videos",
Path.cwd() / "videos",
]
for candidate in candidates:
if candidate.exists():
return candidate
return candidates[0]
def render_validation_page(
compliance_client,
runtime_videos: Path,
permissions: Dict[str, bool],
username: str,
) -> None:
if not permissions.get("validar", False):
st.warning("⚠️ No tens permisos per accedir a aquesta secció de validació.")
st.stop()
st.header("🔍 Validació de Vídeos")
tab_videos, tab_ads = st.tabs(["📹 Validar Vídeos", "🎬 Validar Audiodescripcions"])
base_dir = _build_candidates(runtime_videos)
if not base_dir.exists():
st.info("📝 No s'ha trobat la carpeta **videos**. Crea-la i afegeix-hi subcarpetes amb els teus vídeos.")
st.stop()
with tab_videos:
st.subheader("📹 Validar Vídeos Pujats")
video_folders = []
for folder in sorted(base_dir.iterdir()):
if folder.is_dir() and folder.name != "completed":
video_files = list(folder.glob("*.mp4")) + list(folder.glob("*.avi")) + list(folder.glob("*.mov"))
if video_files:
mod_time = folder.stat().st_mtime
fecha = datetime.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M")
video_folders.append(
{
"name": folder.name,
"path": str(folder),
"created_at": fecha,
"video_files": video_files,
}
)
if not video_folders:
st.info("📝 No hi ha vídeos pujats pendents de validació.")
else:
opciones_video = [f"{video['name']} - {video['created_at']}" for video in video_folders]
seleccion = st.selectbox(
"Selecciona un vídeo per validar:",
opciones_video,
index=0 if opciones_video else None,
)
if seleccion:
indice = opciones_video.index(seleccion)
video_seleccionat = video_folders[indice]
col1, col2 = st.columns([2, 1])
with col1:
st.markdown("### 📹 Informació del Vídeo")
st.markdown(f"**Nom:** {video_seleccionat['name']}")
st.markdown(f"**Data:** {video_seleccionat['created_at']}")
st.markdown(f"**Arxius:** {len(video_seleccionat['video_files'])} vídeos trobats")
if video_seleccionat["video_files"]:
video_path = str(video_seleccionat["video_files"][0])
st.markdown("**Vídeo principal:**")
st.video(video_path)
else:
st.warning("⚠️ No s'han trobat arxius de vídeo.")
with col2:
st.markdown("### 🔍 Accions de Validació")
col_btn1, col_btn2 = st.columns(2)
with col_btn1:
if st.button("✅ Acceptar", type="primary", key=f"accept_video_{video_seleccionat['name']}"):
success = compliance_client.record_validator_decision(
document_id=f"video_{video_seleccionat['name']}",
validator_email=f"{username}@veureu.local",
decision="acceptat",
comments=f"Vídeo validat per {username}",
)
if success:
st.success("✅ Vídeo acceptat i registrat al servei de compliance")
else:
st.error("❌ Error registrant el veredicte")
with col_btn2:
if st.button("❌ Rebutjar", type="secondary", key=f"reject_video_{video_seleccionat['name']}" ):
success = compliance_client.record_validator_decision(
document_id=f"video_{video_seleccionat['name']}",
validator_email=f"{username}@veureu.local",
decision="rebutjat",
comments=f"Vídeo rebutjat per {username}",
)
if success:
st.success("✅ Vídeo rebutjat i registrat al servei de compliance")
else:
st.error("❌ Error registrant el veredicte")
with tab_ads:
st.subheader("🎬 Validar Audiodescripcions")
videos_con_ad = []
if base_dir.exists():
for folder in sorted(base_dir.iterdir()):
if folder.is_dir() and folder.name != "completed":
for subfolder_name in ["MoE", "Salamandra"]:
subfolder = folder / subfolder_name
if subfolder.exists():
ad_files = list(subfolder.glob("*_ad.txt")) + list(subfolder.glob("*_ad.srt"))
if ad_files:
mod_time = folder.stat().st_mtime
fecha = datetime.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M")
videos_con_ad.append(
{
"name": folder.name,
"path": str(folder),
"created_at": fecha,
"ad_files": ad_files,
"ad_folder": str(subfolder),
}
)
if not videos_con_ad:
st.info("📝 No hi ha audiodescripcions pendents de validació.")
else:
videos_ad_ordenats = sorted(videos_con_ad, key=lambda x: x["created_at"], reverse=True)
opciones_ad = [f"{video['name']} - {video['created_at']}" for video in videos_ad_ordenats]
seleccion_ad = st.selectbox(
"Selecciona una audiodescripció per validar:",
opciones_ad,
index=0 if opciones_ad else None,
)
if seleccion_ad:
indice = opciones_ad.index(seleccion_ad)
video_seleccionat = videos_ad_ordenats[indice]
col1, col2 = st.columns([2, 1])
with col1:
st.markdown("### 🎬 Informació de l'Audiodescripció")
st.markdown(f"**Vídeo:** {video_seleccionat['name']}")
st.markdown(f"**Data:** {video_seleccionat['created_at']}")
st.markdown(f"**Carpeta:** {Path(video_seleccionat['ad_folder']).name}")
st.markdown(f"**Arxius:** {len(video_seleccionat['ad_files'])} audiodescripcions trobades")
if video_seleccionat["ad_files"]:
ad_path = video_seleccionat["ad_files"][0]
st.markdown(f"#### 📄 Contingut ({ad_path.name}):")
try:
texto = ad_path.read_text(encoding="utf-8")
except Exception:
texto = ad_path.read_text(errors="ignore")
st.text_area("Contingut de l'audiodescripció:", texto, height=300, disabled=True)
else:
st.warning("⚠️ No s'han trobat arxius d'audiodescripció.")
with col2:
st.markdown("### 🔍 Accions de Validació")
col_btn1, col_btn2 = st.columns(2)
with col_btn1:
if st.button("✅ Acceptar", type="primary", key=f"accept_ad_{video_seleccionat['name']}"):
success = compliance_client.record_validator_decision(
document_id=f"ad_{video_seleccionat['name']}",
validator_email=f"{username}@veureu.local",
decision="acceptat",
comments=f"Audiodescripció validada per {username}",
)
if success:
st.success("✅ Audiodescripció acceptada i registrada al servei de compliance")
else:
st.error("❌ Error registrant el veredicte")
with col_btn2:
if st.button("❌ Rebutjar", type="secondary", key=f"reject_ad_{video_seleccionat['name']}" ):
success = compliance_client.record_validator_decision(
document_id=f"ad_{video_seleccionat['name']}",
validator_email=f"{username}@veureu.local",
decision="rebutjat",
comments=f"Audiodescripció rebutjada per {username}",
)
if success:
st.success("✅ Audiodescripció rebutjada i registrada al servei de compliance")
else:
st.error("❌ Error registrant el veredicte")
st.markdown("---")
st.markdown("### ℹ️ Informació del Procés de Validació")
st.markdown(
"""
- **Tots els veredictes** es registren al servei de compliance per garantir la traçabilitat
- **Cada validació** inclou veredicte, nom del vídeo i validador responsable
- **Els registres** compleixen amb la normativa AI Act i GDPR
"""
)