|
<!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"> |
|
|
|
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> |
|
|
|
<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 { |
|
|
|
|
|
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); |
|
} |
|
|
|
.card-header { |
|
background-color: #f8f9fa; |
|
border-bottom: 2px solid #e9ecef; |
|
font-weight: 600; |
|
padding: 1rem 1.25rem; |
|
display: flex; |
|
align-items: center; |
|
} |
|
|
|
.nav-tabs { |
|
border-bottom: 2px solid #dee2e6; |
|
margin-bottom: 1.5rem; |
|
} |
|
|
|
.nav-tabs .nav-link { |
|
border: none; |
|
border-bottom: 2px solid transparent; |
|
color: #6c757d; |
|
font-weight: 500; |
|
padding: 1rem 1.5rem; |
|
transition: all 0.2s ease-in-out; |
|
display: inline-flex; |
|
align-items: center; |
|
gap: 0.5rem; |
|
} |
|
|
|
.nav-tabs .nav-link:hover { |
|
border-bottom-color: #adb5bd; |
|
color: #007bff; |
|
} |
|
|
|
.nav-tabs .nav-link.active { |
|
background-color: transparent; |
|
border-bottom: 2px solid #007bff; |
|
color: #007bff; |
|
font-weight: 600; |
|
} |
|
|
|
.list-group-item { |
|
border: none; |
|
border-bottom: 1px solid #e9ecef; |
|
padding: 1rem 1.25rem; |
|
} |
|
|
|
.list-group-item:last-child { |
|
border-bottom: none; |
|
} |
|
|
|
.btn { |
|
border-radius: 4px; |
|
padding: 0.5rem 1rem; |
|
transition: all 0.2s ease-in-out; |
|
} |
|
|
|
.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; |
|
} |
|
|
|
.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; |
|
animation: fadeInOut 5s ease-in-out forwards; |
|
} |
|
|
|
@keyframes fadeInOut { |
|
0% { opacity: 0; } |
|
10% { opacity: 1; } |
|
90% { opacity: 1; transform: translateY(0); } |
|
100% { opacity: 0; transform: translateY(-10px); } |
|
} |
|
|
|
.editable { |
|
display: none; |
|
background-color: #f0f2f5; |
|
padding: 1rem; |
|
border: 1px dashed #ced4da; |
|
border-radius: 4px; |
|
margin-top: 1rem; |
|
} |
|
|
|
.display-mode { |
|
line-height: 1.5; |
|
flex-grow: 1; |
|
margin-right: 1rem; |
|
} |
|
.display-mode strong { |
|
color: #343a40; |
|
} |
|
.display-mode small { |
|
display: block; |
|
margin-top: 0.25rem; |
|
} |
|
|
|
.action-buttons { |
|
display: flex; |
|
gap: 0.5rem; |
|
flex-shrink: 0; |
|
} |
|
|
|
.text-muted { |
|
color: #6c757d !important; |
|
font-size: 0.875rem; |
|
} |
|
.text-muted i { |
|
margin-left: 0.25rem; |
|
} |
|
|
|
|
|
.btn-icon { |
|
display: inline-flex; |
|
align-items: center; |
|
gap: 0.5rem; |
|
} |
|
|
|
|
|
#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; |
|
background-color: #e9ecef; |
|
font-size: 0.9rem; |
|
} |
|
.btn-group .btn { |
|
margin-right: -1px; |
|
} |
|
.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> |
|
|
|
|
|
<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> |
|
|
|
|
|
<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> |
|
|
|
|
|
<div class="tab-content" id="gestionTabContent"> |
|
|
|
|
|
<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> |
|
|
|
<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> |
|
|
|
<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> |
|
|
|
|
|
<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> |
|
|
|
<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> |
|
|
|
<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> |
|
|
|
|
|
<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"> |
|
<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> |
|
|
|
|
|
</span> |
|
|
|
<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> |
|
|
|
<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> |
|
|
|
|
|
<div class="tab-pane fade" id="ajouter" role="tabpanel" aria-labelledby="ajouter-tab"> |
|
<div class="row"> |
|
|
|
<div class="col-md-6"> |
|
|
|
<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> |
|
|
|
|
|
<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> |
|
|
|
|
|
<div class="col-md-6"> |
|
|
|
<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"> |
|
|
|
<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> |
|
|
|
|
|
<div class="tab-pane fade" id="ia-input" role="tabpanel" aria-labelledby="ia-tab"> |
|
<form id="ia-generation-form"> |
|
<input type="hidden" name="action" value="generate_ia_content"> |
|
<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> |
|
|
|
</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> |
|
|
|
<div id="ia-error-container" class="mt-3 alert alert-danger d-none" role="alert"></div> |
|
|
|
<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> |
|
|
|
<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> |
|
|
|
</div> |
|
</div> |
|
|
|
|
|
|
|
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script> |
|
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> |
|
|
|
<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() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$('#flash-message-container .alert').delay(5000).fadeOut(1000); |
|
|
|
|
|
|
|
|
|
$(document).on('click', '.edit-button', function(e) { |
|
e.preventDefault(); |
|
const listItem = $(this).closest('.list-group-item'); |
|
|
|
listItem.siblings().find('.editable').slideUp(); |
|
listItem.siblings().find('.display-mode, .action-buttons').show(); |
|
|
|
listItem.find('.editable').slideDown(); |
|
listItem.find('.display-mode, .action-buttons').hide(); |
|
|
|
listItem.find('.editable').find('input[type="text"], textarea').first().focus(); |
|
}); |
|
|
|
|
|
$(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(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
$(document).on('submit', 'form.delete-form', function(e) { |
|
const actionInput = $(this).find('input[name="action"]'); |
|
|
|
if (actionInput.length > 0 && actionInput.val().startsWith('delete_')) { |
|
|
|
if (!confirm('Êtes-vous sûr de vouloir supprimer cet élément ? Cette action est irréversible.')) { |
|
e.preventDefault(); |
|
} |
|
|
|
} |
|
}); |
|
|
|
|
|
|
|
|
|
$('#ia-generation-form').on('submit', function(e) { |
|
e.preventDefault(); |
|
|
|
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(); |
|
|
|
|
|
if (!youtubeUrl || !prompt || !title || !category) { |
|
errorContainer.text('Veuillez remplir tous les champs requis pour la génération IA.').removeClass('d-none'); |
|
return; |
|
} |
|
|
|
const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+$/; |
|
if (!youtubeRegex.test(youtubeUrl)) { |
|
errorContainer.text('Veuillez entrer une URL YouTube valide.').removeClass('d-none'); |
|
return; |
|
} |
|
|
|
|
|
|
|
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(''); |
|
|
|
|
|
$.ajax({ |
|
url: '/generate-content', |
|
type: 'POST', |
|
contentType: 'application/json', |
|
data: JSON.stringify({ |
|
youtube_url: youtubeUrl, |
|
prompt: prompt, |
|
model: model |
|
|
|
}), |
|
success: function(response) { |
|
if (response.success && response.text) { |
|
generatedContentTextarea.val(response.text.trim()); |
|
resultContainer.removeClass('d-none'); |
|
} else { |
|
|
|
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) { |
|
|
|
let errorMessage = 'Erreur lors de la communication avec le serveur. '; |
|
if (xhr.responseJSON && xhr.responseJSON.error) { |
|
errorMessage += xhr.responseJSON.error; |
|
} else if (xhr.responseText) { |
|
|
|
errorMessage += `(${xhr.status}: ${error}). Réponse: ${xhr.responseText.substring(0, 100)}...`; |
|
} else { |
|
errorMessage += `(${xhr.status}: ${error})`; |
|
} |
|
errorContainer.text(errorMessage).removeClass('d-none'); |
|
}, |
|
complete: function() { |
|
|
|
generateBtn.prop('disabled', false).find('i').removeClass('fa-spinner fa-spin').addClass('fa-magic'); |
|
loadingIndicator.addClass('d-none'); |
|
} |
|
}); |
|
}); |
|
|
|
|
|
$('#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; |
|
} |
|
|
|
|
|
$('#final_titre_texte').val(titre); |
|
$('#final_contenu_texte').val(contenu); |
|
$('#final_sous_categorie_id').val(sousCategorieId); |
|
$('#submit-ia-content-form').submit(); |
|
}); |
|
|
|
|
|
$('#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(); |
|
|
|
|
|
$('#titre_texte').val(titre); |
|
$('#contenu_texte').val(contenu); |
|
$('#sous_categorie_id').val(sousCategorieId); |
|
|
|
|
|
$('#manual-tab').tab('show'); |
|
|
|
|
|
$('html, body').animate({ |
|
scrollTop: $("#manual-add-text-form").offset().top - 20 |
|
}, 500); |
|
|
|
|
|
$('#ia-result-container').addClass('d-none'); |
|
}); |
|
|
|
}); |
|
</script> |
|
</body> |
|
</html> |