bbd / templates /gere.html
Docfile's picture
Update templates/gere.html
4b7155d verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Gestion dhes Données</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap CSS with SRI -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<!-- Font Awesome CSS with SRI -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
body {
background-color: #f8f9fa;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.container {
/* Utilisation de container-fluid pour une meilleure largeur sur grand écran, ou garder max-width */
/* max-width: 1200px; */
margin: 0 auto;
padding: 2rem;
}
.page-title {
color: #2c3e50;
margin-bottom: 2rem;
font-weight: 600;
}
.card {
margin-bottom: 20px;
border: none;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s ease-in-out;
}
.card:hover {
transform: translateY(-2px); /* Subtile effet au survol */
}
.card-header {
background-color: #f8f9fa; /* Ou une couleur contrastante comme #e9ecef */
border-bottom: 2px solid #e9ecef;
font-weight: 600;
padding: 1rem 1.25rem;
display: flex; /* Pour aligner icône et texte */
align-items: center;
}
.nav-tabs {
border-bottom: 2px solid #dee2e6;
margin-bottom: 1.5rem; /* Un peu plus d'espace */
}
.nav-tabs .nav-link {
border: none;
border-bottom: 2px solid transparent; /* Préparer pour l'état actif */
color: #6c757d;
font-weight: 500;
padding: 1rem 1.5rem;
transition: all 0.2s ease-in-out;
display: inline-flex; /* Pour aligner icône et texte */
align-items: center;
gap: 0.5rem; /* Espace entre icône et texte */
}
.nav-tabs .nav-link:hover {
border-bottom-color: #adb5bd; /* Léger indicateur au survol */
color: #007bff;
}
.nav-tabs .nav-link.active {
background-color: transparent;
border-bottom: 2px solid #007bff;
color: #007bff;
font-weight: 600; /* Rendre l'onglet actif plus visible */
}
.list-group-item {
border: none;
border-bottom: 1px solid #e9ecef;
padding: 1rem 1.25rem; /* Harmoniser padding avec card-header */
}
.list-group-item:last-child {
border-bottom: none;
}
.btn {
border-radius: 4px;
padding: 0.5rem 1rem;
transition: all 0.2s ease-in-out;
}
/* Amélioration couleurs boutons (Bootstrap 4 utilise déjà ces couleurs, mais on peut affiner) */
.btn-warning { color: #212529; }
.btn-danger { color: #fff; }
.btn-success { color: #fff; }
.btn-info { color: #fff; }
.btn-primary { color: #fff; }
.btn-secondary { color: #fff; }
.form-control {
border-radius: 4px;
border: 1px solid #ced4da;
padding: 0.5rem 0.75rem; /* Ajustement padding */
}
.form-control:focus {
border-color: #80bdff;
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}
.alert {
border-radius: 4px;
margin-bottom: 1.5rem; /* Cohérence espacement */
animation: fadeInOut 5s ease-in-out forwards; /* 'forwards' garde l'état final (opacity: 0) */
}
@keyframes fadeInOut {
0% { opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; transform: translateY(0); }
100% { opacity: 0; transform: translateY(-10px); } /* Légère animation de sortie */
}
.editable {
display: none;
background-color: #f0f2f5; /* Légèrement différent pour le mode édition */
padding: 1rem;
border: 1px dashed #ced4da; /* Indicateur visuel */
border-radius: 4px;
margin-top: 1rem; /* Espace entre l'affichage et l'édition */
}
.display-mode {
line-height: 1.5;
flex-grow: 1; /* Permet au texte de prendre l'espace disponible */
margin-right: 1rem; /* Espace avant les boutons */
}
.display-mode strong {
color: #343a40; /* Rendre le titre plus distinct */
}
.display-mode small {
display: block; /* Mettre les détails sur une nouvelle ligne si nécessaire */
margin-top: 0.25rem;
}
.action-buttons {
display: flex;
gap: 0.5rem;
flex-shrink: 0; /* Empêche les boutons de rétrécir */
}
.text-muted {
color: #6c757d !important; /* Forcer la couleur si nécessaire */
font-size: 0.875rem;
}
.text-muted i {
margin-left: 0.25rem; /* Espace avant l'icône dans small */
}
.btn-icon {
display: inline-flex;
align-items: center;
gap: 0.5rem; /* Espace entre icône et texte dans le bouton */
}
/* Styles spécifiques pour la partie IA */
#ia-loading .spinner-border {
width: 1.5rem;
height: 1.5rem;
}
#ia-result-container {
border: 1px solid #e9ecef;
padding: 1rem;
background-color: #fff;
border-radius: 4px;
}
#ia_generated_content {
font-family: monospace; /* Utile pour du contenu potentiellement formaté */
background-color: #e9ecef; /* Indiquer que c'est en lecture seule */
font-size: 0.9rem;
}
.btn-group .btn { /* Assurer que les boutons dans btn-group s'affichent correctement */
margin-right: -1px; /* Correction pour Bootstrap 4 btn-group */
}
.btn-group .btn:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.btn-group .btn:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
</style>
</head>
<body>
<div class="container mt-4">
<h1 class="page-title text-center"><i class="fas fa-database mr-2"></i>Gestion des Données</h1>
<!-- Zone pour les messages flash -->
<div id="flash-message-container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Fermer">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
<!-- Onglets de navigation -->
<ul class="nav nav-tabs" id="gestionTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="matieres-tab" data-toggle="tab" href="#matieres" role="tab" aria-controls="matieres" aria-selected="true">
<i class="fas fa-book"></i> Matières
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="sous-categories-tab" data-toggle="tab" href="#sous-categories" role="tab" aria-controls="sous-categories" aria-selected="false">
<i class="fas fa-list"></i> Sous-Catégories
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="textes-tab" data-toggle="tab" href="#textes" role="tab" aria-controls="textes" aria-selected="false">
<i class="fas fa-file-alt"></i> Textes
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="ajouter-tab" data-toggle="tab" href="#ajouter" role="tab" aria-controls="ajouter" aria-selected="false">
<i class="fas fa-plus-circle"></i> Ajouter
</a>
</li>
</ul>
<!-- Contenu des onglets -->
<div class="tab-content" id="gestionTabContent">
<!-- Onglet Matières -->
<div class="tab-pane fade show active" id="matieres" role="tabpanel" aria-labelledby="matieres-tab">
<div class="card">
<div class="card-header">
<i class="fas fa-book mr-2"></i>Liste des Matières
</div>
<ul class="list-group list-group-flush">
{% for matiere in matieres %}
<li class="list-group-item" id="matiere-{{ matiere.id }}">
<div class="d-flex justify-content-between align-items-center">
<span class="display-mode">{{ matiere.nom }}</span>
<!-- Formulaire d'édition caché -->
<form method="post" class="editable flex-grow-1 mr-2">
<input type="hidden" name="action" value="edit_matiere_{{ matiere.id }}">
<div class="input-group">
<input type="text" name="edit_nom_matiere_{{ matiere.id }}" value="{{ matiere.nom }}" class="form-control" required>
<div class="input-group-append">
<button type="submit" class="btn btn-success btn-icon">
<i class="fas fa-check"></i> Enregistrer
</button>
<button type="button" class="btn btn-secondary btn-icon cancel-edit">
<i class="fas fa-times"></i> Annuler
</button>
</div>
</div>
</form>
<!-- Boutons d'action visibles -->
<div class="action-buttons">
<button class="btn btn-warning btn-sm btn-icon edit-button">
<i class="fas fa-edit"></i> Modifier
</button>
<form method="post" class="d-inline delete-form">
<input type="hidden" name="action" value="delete_matiere_{{ matiere.id }}">
<button type="submit" class="btn btn-danger btn-sm btn-icon">
<i class="fas fa-trash"></i> Supprimer
</button>
</form>
</div>
</div>
</li>
{% else %}
<li class="list-group-item text-center text-muted">Aucune matière trouvée.</li>
{% endfor %}
</ul>
</div>
</div>
<!-- Onglet Sous-Catégories -->
<div class="tab-pane fade" id="sous-categories" role="tabpanel" aria-labelledby="sous-categories-tab">
<div class="card">
<div class="card-header">
<i class="fas fa-list mr-2"></i>Liste des Sous-Catégories
</div>
<ul class="list-group list-group-flush">
{% for sous_categorie in sous_categories %}
<li class="list-group-item" id="sous-categorie-{{ sous_categorie.id }}">
<div class="d-flex justify-content-between align-items-center">
<span class="display-mode">
{{ sous_categorie.nom }}
<small class="text-muted"><i class="fas fa-book"></i>{{ sous_categorie.matiere.nom }}</small>
</span>
<!-- Formulaire d'édition caché -->
<form method="post" class="editable flex-grow-1 mr-2">
<input type="hidden" name="action" value="edit_sous_categorie_{{ sous_categorie.id }}">
<div class="form-row align-items-center">
<div class="col-md-6 mb-2 mb-md-0">
<input type="text" name="edit_nom_sous_categorie_{{ sous_categorie.id }}" value="{{ sous_categorie.nom }}" class="form-control" placeholder="Nom" required>
</div>
<div class="col-md-4 mb-2 mb-md-0">
<select name="edit_matiere_id_{{ sous_categorie.id }}" class="form-control" required>
{% for matiere in matieres %}
<option value="{{ matiere.id }}" {% if matiere.id == sous_categorie.matiere_id %}selected{% endif %}>
{{ matiere.nom }}
</option>
{% endfor %}
</select>
</div>
<div class="col-md-2">
<div class="btn-group" role="group">
<button type="submit" class="btn btn-success btn-icon">
<i class="fas fa-check"></i> <span class="d-none d-lg-inline">Enr.</span>
</button>
<button type="button" class="btn btn-secondary btn-icon cancel-edit">
<i class="fas fa-times"></i> <span class="d-none d-lg-inline">Ann.</span>
</button>
</div>
</div>
</div>
</form>
<!-- Boutons d'action visibles -->
<div class="action-buttons">
<button class="btn btn-warning btn-sm btn-icon edit-button">
<i class="fas fa-edit"></i> Modifier
</button>
<form method="post" class="d-inline delete-form">
<input type="hidden" name="action" value="delete_sous_categorie_{{ sous_categorie.id }}">
<button type="submit" class="btn btn-danger btn-sm btn-icon">
<i class="fas fa-trash"></i> Supprimer
</button>
</form>
</div>
</div>
</li>
{% else %}
<li class="list-group-item text-center text-muted">Aucune sous-catégorie trouvée.</li>
{% endfor %}
</ul>
</div>
</div>
<!-- Onglet Textes -->
<div class="tab-pane fade" id="textes" role="tabpanel" aria-labelledby="textes-tab">
<div class="card">
<div class="card-header">
<i class="fas fa-file-alt mr-2"></i>Liste des Textes
</div>
<ul class="list-group list-group-flush">
{% for texte in textes %}
<li class="list-group-item" id="texte-{{ texte.id }}">
<div class="d-flex justify-content-between align-items-start"> <!-- align-items-start pour contenu multiligne -->
<span class="display-mode">
<strong>{{ texte.titre }}</strong>
<small class="text-muted">
<i class="fas fa-list"></i>{{ texte.sous_categorie.nom }}
<i class="fas fa-book"></i>{{ texte.sous_categorie.matiere.nom }}
</small>
<!-- Optionnel: Aperçu du contenu -->
<!-- <p class="text-muted mt-1 mb-0 small">{{ texte.contenu | truncate(100) }}</p> -->
</span>
<!-- Formulaire d'édition caché -->
<form method="post" class="editable flex-grow-1 mr-2">
<input type="hidden" name="action" value="edit_texte_{{ texte.id }}">
<div class="form-group">
<label for="edit_titre_texte_{{ texte.id }}" class="sr-only">Titre</label>
<input type="text" id="edit_titre_texte_{{ texte.id }}" name="edit_titre_texte_{{ texte.id }}" value="{{ texte.titre }}" class="form-control mb-2" placeholder="Titre" required>
</div>
<div class="form-group">
<label for="edit_contenu_texte_{{ texte.id }}" class="sr-only">Contenu</label>
<textarea id="edit_contenu_texte_{{ texte.id }}" name="edit_contenu_texte_{{ texte.id }}" class="form-control mb-2" rows="4" placeholder="Contenu" required>{{ texte.contenu }}</textarea>
</div>
<div class="form-row align-items-center">
<div class="col-md-8 mb-2 mb-md-0">
<label for="edit_sous_categorie_id_{{ texte.id }}" class="sr-only">Sous-catégorie</label>
<select id="edit_sous_categorie_id_{{ texte.id }}" name="edit_sous_categorie_id_{{ texte.id }}" class="form-control" required>
{% for sous_categorie in sous_categories %}
<option value="{{ sous_categorie.id }}" {% if sous_categorie.id == texte.sous_categorie_id %}selected{% endif %}>
{{ sous_categorie.nom }} ({{ sous_categorie.matiere.nom }})
</option>
{% endfor %}
</select>
</div>
<div class="col-md-4">
<div class="btn-group" role="group">
<button type="submit" class="btn btn-success btn-icon">
<i class="fas fa-check"></i> <span class="d-none d-lg-inline">Enr.</span>
</button>
<button type="button" class="btn btn-secondary btn-icon cancel-edit">
<i class="fas fa-times"></i> <span class="d-none d-lg-inline">Ann.</span>
</button>
</div>
</div>
</div>
</form>
<!-- Boutons d'action visibles -->
<div class="action-buttons">
<button class="btn btn-warning btn-sm btn-icon edit-button">
<i class="fas fa-edit"></i> Modifier
</button>
<form method="post" class="d-inline delete-form">
<input type="hidden" name="action" value="delete_texte_{{ texte.id }}">
<button type="submit" class="btn btn-danger btn-sm btn-icon">
<i class="fas fa-trash"></i> Supprimer
</button>
</form>
</div>
</div>
</li>
{% else %}
<li class="list-group-item text-center text-muted">Aucun texte trouvé.</li>
{% endfor %}
</ul>
</div>
</div>
<!-- Onglet Ajouter -->
<div class="tab-pane fade" id="ajouter" role="tabpanel" aria-labelledby="ajouter-tab">
<div class="row">
<!-- Colonne pour Matière et Sous-catégorie -->
<div class="col-md-6">
<!-- Formulaire d'ajout d'une matière -->
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-plus-circle mr-2"></i>Ajouter une Matière
</div>
<div class="card-body">
<form method="post">
<input type="hidden" name="action" value="add_matiere">
<div class="form-group">
<label for="nom_matiere">Nom de la Matière</label>
<input type="text" id="nom_matiere" name="nom_matiere" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary btn-icon">
<i class="fas fa-plus"></i> Ajouter Matière
</button>
</form>
</div>
</div>
<!-- Formulaire d'ajout d'une sous-catégorie -->
<div class="card">
<div class="card-header">
<i class="fas fa-plus-circle mr-2"></i>Ajouter une Sous-Catégorie
</div>
<div class="card-body">
<form method="post">
<input type="hidden" name="action" value="add_sous_categorie">
<div class="form-group">
<label for="nom_sous_categorie">Nom de la Sous-Catégorie</label>
<input type="text" id="nom_sous_categorie" name="nom_sous_categorie" class="form-control" required>
</div>
<div class="form-group">
<label for="matiere_id">Matière associée</label>
<select id="matiere_id" name="matiere_id" class="form-control" required>
<option value="" disabled selected>Choisir une matière...</option>
{% for matiere in matieres %}
<option value="{{ matiere.id }}">{{ matiere.nom }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary btn-icon">
<i class="fas fa-plus"></i> Ajouter Sous-Catégorie
</button>
</form>
</div>
</div>
</div>
<!-- Colonne pour Texte -->
<div class="col-md-6">
<!-- Formulaire d'ajout d'un texte avec module IA -->
<div class="card">
<div class="card-header">
<i class="fas fa-plus-circle mr-2"></i>Ajouter un Texte
</div>
<div class="card-body">
<ul class="nav nav-pills mb-3" id="textInputTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="manual-tab" data-toggle="pill" href="#manual-input" role="tab" aria-controls="manual-input" aria-selected="true">
<i class="fas fa-edit mr-1"></i> Manuel
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="ia-tab" data-toggle="pill" href="#ia-input" role="tab" aria-controls="ia-input" aria-selected="false">
<i class="fas fa-robot mr-1"></i> Génération IA
</a>
</li>
</ul>
<div class="tab-content" id="textInputTabContent">
<!-- Onglet Saisie Manuelle -->
<div class="tab-pane fade show active" id="manual-input" role="tabpanel" aria-labelledby="manual-tab">
<form method="post" id="manual-add-text-form">
<input type="hidden" name="action" value="add_texte">
<div class="form-group">
<label for="titre_texte">Titre du Texte</label>
<input type="text" id="titre_texte" name="titre_texte" class="form-control" required>
</div>
<div class="form-group">
<label for="contenu_texte">Contenu du Texte</label>
<textarea id="contenu_texte" name="contenu_texte" class="form-control" rows="5" required></textarea>
</div>
<div class="form-group">
<label for="sous_categorie_id">Sous-Catégorie</label>
<select id="sous_categorie_id" name="sous_categorie_id" class="form-control" required>
<option value="" disabled selected>Choisir une sous-catégorie...</option>
{% for sous_categorie in sous_categories %}
<option value="{{ sous_categorie.id }}">{{ sous_categorie.nom }} ({{ sous_categorie.matiere.nom }})</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary btn-icon">
<i class="fas fa-plus"></i> Ajouter Texte Manuel
</button>
</form>
</div>
<!-- Onglet Génération IA -->
<div class="tab-pane fade" id="ia-input" role="tabpanel" aria-labelledby="ia-tab">
<form id="ia-generation-form"> <!-- Pas de method="post" ici, géré par AJAX -->
<input type="hidden" name="action" value="generate_ia_content"> <!-- Gardé pour info, mais pas soumis classiquement -->
<div class="form-group">
<label for="ia_titre_texte">Titre du Texte (pour référence)</label>
<input type="text" id="ia_titre_texte" name="ia_titre_texte" class="form-control" required>
</div>
<div class="form-group">
<label for="youtube_url">URL de la vidéo YouTube</label>
<input type="url" id="youtube_url" name="youtube_url" class="form-control" placeholder="https://www.youtube.com/watch?v=..." required>
</div>
<div class="form-group">
<label for="ia_prompt">Instruction pour l'IA (Prompt)</label>
<textarea id="ia_prompt" name="ia_prompt" class="form-control" rows="3" placeholder="Ex: Faire un résumé détaillé de cette vidéo avec les points clés et des exemples." required></textarea>
</div>
<div class="form-group">
<label for="ia_model">Modèle Gemini</label>
<select id="ia_model" name="ia_model" class="form-control">
<option value="gemini-2.5-pro-exp-03-25">gemini-2.5-pro-exp-03-25</option>
<option value="gemini-2.0-flash">gemini-2.0-flash</option>
<!-- Ajouter d'autres modèles si disponibles/pertinents -->
</select>
</div>
<div class="form-group">
<label for="ia_sous_categorie_id">Sous-Catégorie (pour classement)</label>
<select id="ia_sous_categorie_id" name="ia_sous_categorie_id" class="form-control" required>
<option value="" disabled selected>Choisir une sous-catégorie...</option>
{% for sous_categorie in sous_categories %}
<option value="{{ sous_categorie.id }}">{{ sous_categorie.nom }} ({{ sous_categorie.matiere.nom }})</option>
{% endfor %}
</select>
</div>
<button type="submit" id="generate-content-btn" class="btn btn-info btn-icon">
<i class="fas fa-magic"></i> Générer le Contenu
</button>
<div id="ia-loading" class="mt-3 d-none">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Génération en cours...</span>
</div>
<span class="ml-2 align-middle">Analyse de la vidéo et génération en cours, veuillez patienter...</span>
</div>
<!-- Zone pour afficher les erreurs AJAX -->
<div id="ia-error-container" class="mt-3 alert alert-danger d-none" role="alert"></div>
<!-- Zone pour afficher le résultat -->
<div id="ia-result-container" class="mt-3 d-none">
<div class="form-group">
<label for="ia_generated_content"><strong>Contenu Généré</strong></label>
<textarea id="ia_generated_content" name="ia_generated_content" class="form-control" rows="10" readonly></textarea>
</div>
<button type="button" id="use-content-btn" class="btn btn-success btn-icon">
<i class="fas fa-check"></i> Utiliser ce Contenu
</button>
<button type="button" id="modify-content-btn" class="btn btn-warning btn-icon ml-2">
<i class="fas fa-edit"></i> Modifier avant Utilisation
</button>
</div>
</form>
<!-- Formulaire caché pour soumettre le texte généré/finalisé -->
<form method="post" id="submit-ia-content-form" class="d-none">
<input type="hidden" name="action" value="add_texte">
<input type="hidden" id="final_titre_texte" name="titre_texte">
<input type="hidden" id="final_contenu_texte" name="contenu_texte">
<input type="hidden" id="final_sous_categorie_id" name="sous_categorie_id">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- Fin Onglet Ajouter -->
</div> <!-- Fin tab-content -->
</div> <!-- Fin container -->
<!-- Scripts -->
<!-- jQuery with SRI -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<!-- Popper.js with SRI -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<!-- Bootstrap JS with SRI -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
// --- Gestion Générale UI ---
// Initialiser les tooltips si vous en ajoutez
// $('[data-toggle="tooltip"]').tooltip();
// Faire disparaître les messages flash après un délai
$('#flash-message-container .alert').delay(5000).fadeOut(1000);
// --- Gestion Édition Inline ---
// Clic sur le bouton "Modifier"
$(document).on('click', '.edit-button', function(e) {
e.preventDefault();
const listItem = $(this).closest('.list-group-item');
// Cache tous les autres formulaires d'édition ouverts dans la même liste
listItem.siblings().find('.editable').slideUp();
listItem.siblings().find('.display-mode, .action-buttons').show();
// Affiche le formulaire d'édition pour cet item
listItem.find('.editable').slideDown();
listItem.find('.display-mode, .action-buttons').hide();
// Focus sur le premier input du formulaire éditable
listItem.find('.editable').find('input[type="text"], textarea').first().focus();
});
// Clic sur le bouton "Annuler" dans un formulaire d'édition
$(document).on('click', '.cancel-edit', function(e) {
e.preventDefault();
const listItem = $(this).closest('.list-group-item');
listItem.find('.editable').slideUp();
listItem.find('.display-mode, .action-buttons').show();
// Optionnel: Réinitialiser les valeurs du formulaire aux valeurs d'origine si nécessaire
// (nécessiterait de stocker les valeurs initiales ou de ne pas soumettre le formulaire)
});
// --- Gestion Suppression ---
// Intercepter la soumission des formulaires de suppression pour confirmation
$(document).on('submit', 'form.delete-form', function(e) {
const actionInput = $(this).find('input[name="action"]');
// Vérifier si c'est bien une action de suppression
if (actionInput.length > 0 && actionInput.val().startsWith('delete_')) {
// Utiliser une boîte de dialogue de confirmation
if (!confirm('Êtes-vous sûr de vouloir supprimer cet élément ? Cette action est irréversible.')) {
e.preventDefault(); // Annuler la soumission si l'utilisateur clique sur "Annuler"
}
// Si l'utilisateur confirme, le formulaire est soumis normalement
}
});
// --- Gestion Génération IA ---
$('#ia-generation-form').on('submit', function(e) {
e.preventDefault(); // Empêche la soumission classique du formulaire
const generateBtn = $('#generate-content-btn');
const loadingIndicator = $('#ia-loading');
const resultContainer = $('#ia-result-container');
const errorContainer = $('#ia-error-container');
const generatedContentTextarea = $('#ia_generated_content');
const youtubeUrl = $('#youtube_url').val().trim();
const prompt = $('#ia_prompt').val().trim();
const model = $('#ia_model').val();
const title = $('#ia_titre_texte').val().trim();
const category = $('#ia_sous_categorie_id').val();
// Validation simple côté client
if (!youtubeUrl || !prompt || !title || !category) {
errorContainer.text('Veuillez remplir tous les champs requis pour la génération IA.').removeClass('d-none');
return;
}
// Validation basique de l'URL YouTube
const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+$/;
if (!youtubeRegex.test(youtubeUrl)) {
errorContainer.text('Veuillez entrer une URL YouTube valide.').removeClass('d-none');
return;
}
// Réinitialiser l'état UI
generateBtn.prop('disabled', true).find('i').removeClass('fa-magic').addClass('fa-spinner fa-spin');
loadingIndicator.removeClass('d-none');
resultContainer.addClass('d-none');
errorContainer.addClass('d-none').text('');
generatedContentTextarea.val('');
// Appel AJAX vers le backend Flask
$.ajax({
url: '/generate-content', // L'URL de votre route Flask pour la génération
type: 'POST',
contentType: 'application/json', // Important pour envoyer du JSON
data: JSON.stringify({ // Convertir les données JS en chaîne JSON
youtube_url: youtubeUrl,
prompt: prompt,
model: model
// Note: titre et catégorie ne sont pas envoyés pour génération, mais utilisés après
}),
success: function(response) {
if (response.success && response.text) {
generatedContentTextarea.val(response.text.trim()); // Afficher le texte reçu
resultContainer.removeClass('d-none'); // Afficher la zone de résultat
} else {
// Gérer les erreurs renvoyées par le backend (même si status 200)
const errorMessage = response.error || 'Une erreur inconnue est survenue lors de la génération.';
errorContainer.text('Erreur : ' + errorMessage).removeClass('d-none');
}
},
error: function(xhr, status, error) {
// Gérer les erreurs de communication réseau ou serveur (status != 2xx)
let errorMessage = 'Erreur lors de la communication avec le serveur. ';
if (xhr.responseJSON && xhr.responseJSON.error) {
errorMessage += xhr.responseJSON.error;
} else if (xhr.responseText) {
// Essayer d'afficher une partie de la réponse texte si JSON échoue
errorMessage += `(${xhr.status}: ${error}). Réponse: ${xhr.responseText.substring(0, 100)}...`;
} else {
errorMessage += `(${xhr.status}: ${error})`;
}
errorContainer.text(errorMessage).removeClass('d-none');
},
complete: function() {
// Quoi qu'il arrive (succès ou erreur), réactiver le bouton et cacher le spinner
generateBtn.prop('disabled', false).find('i').removeClass('fa-spinner fa-spin').addClass('fa-magic');
loadingIndicator.addClass('d-none');
}
});
});
// Bouton "Utiliser ce Contenu" (après génération IA)
$('#use-content-btn').on('click', function() {
const titre = $('#ia_titre_texte').val().trim();
const contenu = $('#ia_generated_content').val().trim();
const sousCategorieId = $('#ia_sous_categorie_id').val();
if (!titre || !contenu || !sousCategorieId) {
alert("Impossible d'utiliser le contenu : des informations (titre, contenu généré ou catégorie) sont manquantes.");
return;
}
// Remplir le formulaire caché et le soumettre pour ajout
$('#final_titre_texte').val(titre);
$('#final_contenu_texte').val(contenu);
$('#final_sous_categorie_id').val(sousCategorieId);
$('#submit-ia-content-form').submit();
});
// Bouton "Modifier avant Utilisation" (après génération IA)
$('#modify-content-btn').on('click', function() {
const titre = $('#ia_titre_texte').val().trim();
const contenu = $('#ia_generated_content').val().trim();
const sousCategorieId = $('#ia_sous_categorie_id').val();
// Pré-remplir les champs du formulaire manuel
$('#titre_texte').val(titre);
$('#contenu_texte').val(contenu);
$('#sous_categorie_id').val(sousCategorieId);
// Basculer vers l'onglet de saisie manuelle
$('#manual-tab').tab('show'); // Utiliser Bootstrap pour changer d'onglet
// Optionnel: Faire défiler la page jusqu'au formulaire manuel
$('html, body').animate({
scrollTop: $("#manual-add-text-form").offset().top - 20 // -20 pour un peu d'espace au dessus
}, 500);
// Cacher la zone de résultat IA pour éviter la confusion
$('#ia-result-container').addClass('d-none');
});
}); // Fin $(document).ready
</script>
</body>
</html>