youtubeDownloader/client/src/views/queuePanel/QueuePanel.scss
Nicolas 725c5a5a7f feat(client): frontend (formulaire d'ajout + file d'attente)
Interface web complète : formulaire d'ajout (URL directe ou recherche de
chaîne) et panneau de file d'attente avec sondage de la progression.

- views/downloadForm/ : sélecteur de mode (vidéo/audio/miniature) partagé,
  ajout direct par URL, recherche de chaîne (GET /api/channel) avec ajout
  par résultat. Construction DOM via createElement/textContent (jamais
  d'innerHTML avec du texte venant de YouTube), pas juste par prudence :
  ça évite aussi tout risque d'injection depuis un titre de vidéo.
- views/queuePanel/ : sonde GET /api/queue toutes les 1,5s, affiche statut/
  progression/erreur par élément, annulation et lien de téléchargement
  natif (<a download>, pas de fetch+blob).
- api/ : clients fetch typés (channelApi, queueApi), chaque await dans son
  propre try/catch avec message d'erreur adapté (réseau vs HTTP vs JSON).
- QueueItem gagne un champ title optionnel (purement informatif, jamais
  utilisé pour construire la commande yt-dlp) pour un affichage plus
  parlant qu'une URL brute.
- client/tsconfig.json + build.mjs : cible ES2022 (nécessaire pour
  Error.cause, jusque-là ES2020).
- Vitest ajouté côté client (fonctions pures de src/format.ts ; le câblage
  DOM est vérifié manuellement, pas de jsdom pour l'instant).

Deux bugs réels trouvés et corrigés en testant dans un vrai navigateur
(pas seulement en lisant le code) :
- CSS : un attribut `hidden` sur un conteneur `display: flex` se faisait
  écraser par cette règle (même spécificité, la feuille de l'auteur gagne)
  - les deux panneaux d'options restaient visibles en même temps.
- server/src/routes/channel.ts : ne mappait vers 502 que les YtDlpError
  (code de sortie non nul), pas les erreurs brutes de spawn (ex. binaire
  introuvable - ENOENT), qui remontaient donc en 500 générique. Corrigé +
  test de non-régression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 09:28:49 +02:00

82 lines
1.1 KiB
SCSS

.queue-panel {
display: flex;
flex-direction: column;
gap: 0.75rem;
h2 {
margin: 0;
font-size: 1.1rem;
}
&__empty {
color: #666;
font-size: 0.85rem;
}
&__list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
&__item {
border: 1px solid #eee;
border-left-width: 4px;
border-radius: 4px;
padding: 0.5rem 0.75rem;
&--completed {
border-left-color: #2e7d32;
}
&--failed {
border-left-color: #b00020;
}
&--running {
border-left-color: #1565c0;
}
&--cancelled {
border-left-color: #999;
}
&--pending {
border-left-color: #999;
}
}
&__item-title {
margin: 0;
font-size: 0.9rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__item-meta {
margin: 0.15rem 0 0;
font-size: 0.75rem;
color: #666;
}
&__item-progress {
width: 100%;
margin-top: 0.35rem;
}
&__item-error {
margin: 0.35rem 0 0;
font-size: 0.75rem;
color: #b00020;
}
&__item-actions {
margin-top: 0.35rem;
display: flex;
gap: 0.5rem;
}
&__item-download {
font-size: 0.85rem;
}
}