mise a jour du Dom de ajouter article et modifier article

This commit is contained in:
ben
2025-12-12 14:38:43 +01:00
parent b77f82f216
commit 4fe4facd32
5 changed files with 217 additions and 270 deletions

View File

@@ -4,22 +4,14 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajouter un article</title> <title>Ajouter un article</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/ckeditor.js"></script>
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/translations/fr.js"></script>
<link rel="stylesheet" href="../../css/blog.css"> <link rel="stylesheet" href="../../css/blog.css">
<script src="https://cdn.tiny.cloud/1/1up68ybfp3crmpssl9o7pu6d0e8v3okcnsinhoujnmak7wft/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
<style>
</style>
</head> </head>
<body> <body>
<!-- HEADER -->
<header> <header>
<nav class="navbar navbar-expand-xxl bg-body-tertiary shadow-sm"> <nav class="navbar navbar-expand-xxl bg-body-tertiary shadow-sm">
<div class="container-fluid align-items-center"> <div class="container-fluid align-items-center">
@@ -72,82 +64,62 @@
</nav> </nav>
</header> </header>
<div class="container"> <div class="container mt-5">
<h2 class="mb-5 text-center">Ajouter un article</h2> <h2 class="mb-5 text-center">Ajouter un article</h2>
<form id="ajouterArticleForm"> <form id="ajouterArticleForm">
<!-- Conteneur messages DOM -->
<!--Erreur titre vide--> <div id="messages" class="mb-3"></div>
<div id="errorEmpty" class="alert alert-danger d-none">Le titre de l'article est obligatoire</div>
<!--Erreur image invalide-->
<div id="errorImage" class="alert alert-danger d-none">
Format d'image invalide. Formats acceptés : JPG, PNG
</div>
<!--Erreur titre existant-->
<div id="errorExists" class="alert alert-danger d-none">Ce titre existe déjà. Choisissez un autre titre.</div>
<!--Succès ajout article-->
<div id="successMsg" class="alert alert-success d-none">Article ajouté avec succès !</div>
<!-- Catégorie --> <!-- Catégorie -->
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">Catégorie de l'article (obligatoire)</label> <label class="form-label fw-bold">Catégorie *</label>
<select id="articleCategory" class="form-select" required> <select id="articleCategory" class="form-select">
<option value="" disabled selected>Choisissez une catégorie</option> <option value="">Choisissez une catégorie</option>
<option value="actualités">Actualités</option> <option value="actualités">Actualités</option>
<option value="chien">Chien</option> <option value="chien">Chien</option>
<option value="chat">Chat</option> <option value="chat">Chat</option>
<option value="boutique">Boutique</option> <option value="boutique">Boutique</option>
</select> </select>
</div> </div>
<!-- Titre -->
<div class="mb-4">
<label class="form-label fw-bold">Titre *</label>
<input type="text" id="articleTitle" class="form-control">
</div>
<!-- Contenu -->
<div class="mb-3">
<label class="form-label fw-bold">Contenu</label>
<textarea id="articleContent"></textarea>
</div>
<!-- Titre --> <!-- Image -->
<div class="mb-4"> <div class="mb-4">
<label class="form-label fw-bold">Titre de l'article (obligatoire)</label> <label class="form-label fw-bold">Image</label>
<input type="text" id="articleTitle" class="form-control" placeholder="Entrez le titre de l'article"> <input type="file" id="articleImage" class="form-control">
</div> </div>
<!-- Contenu --> <!-- Publié -->
<div class="mb-3">
<label class="form-label fw-bold">Contenu de l'article</label>
<textarea id="articleContent" class="form-control" rows="5" placeholder="Entrez le contenu de l'article"></textarea>
</div>
<!-- Image -->
<div class="mb-4">
<label class="form-label fw-bold">Image de l'article</label>
<input type="file" id="articleImage" class="form-control" accept="image/*">
</div>
<!--Publié-->
<div class="form-check mb-3"> <div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="articlePublished"> <input class="form-check-input" type="checkbox" id="articlePublished">
<label class="form-check-label" for="articlePublished">Publié (sera publié sur le facebook)</label> <label class="form-check-label">Publié</label>
</div> </div>
<!-- Boutons -->
<!--Boutons-->
<div class="d-flex gap-3 mt-4"> <div class="d-flex gap-3 mt-4">
<a href="../html/accueil_blog.html" class="btn btn-secondary w-50">Annuler</a> <a href="../html/accueil_blog.html" class="btn btn-secondary w-50">Annuler</a>
<button type="submit" class="btn btn-primary w-50">Ajouter</button> <button type="submit" class="btn btn-primary w-50">Ajouter</button>
</div> </div>
</form> </form>
</div> </div>
<script src="../js/ajouter_article.js"></script> <script src="../js/ajouter_article.js"></script>
<script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.tiny.cloud/1/1up68ybfp3crmpssl9o7pu6d0e8v3okcnsinhoujnmak7wft/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
<script> <script>
tinymce.init({ tinymce.init({
selector: '#articleContent', selector: '#articleContent',
height: 400, height: 400,
@@ -157,10 +129,5 @@ tinymce.init({
}); });
</script> </script>
</body> </body>
</html> </html>

View File

@@ -4,32 +4,16 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modifier un article</title> <title>Modifier un article</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/ckeditor.js"></script>
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/translations/fr.js"></script>
<link rel="stylesheet" href="../../css/blog.css">
<script src="https://cdn.tiny.cloud/1/1up68ybfp3crmpssl9o7pu6d0e8v3okcnsinhoujnmak7wft/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css">
<style>
body {
background: #f4f6f9;
}
.container {
margin-top: 40px;
}
.preview-img {
max-width: 15px;
border-radius: 8px
}
.ck-editor__editable {
min-height: 350px;
}
</style>
</head> </head>
<body> <body>
<!-- HEADER -->
<header> <header>
<nav class="navbar navbar-expand-xxl bg-body-tertiary shadow-sm"> <nav class="navbar navbar-expand-xxl bg-body-tertiary shadow-sm">
<div class="container-fluid align-items-center"> <div class="container-fluid align-items-center">
@@ -82,107 +66,79 @@
</nav> </nav>
</header> </header>
<div class="container"> <div class="container">
<h2 class="mb-4 text-center">Modifier un article</h2> <h2 class="mb-4 text-center">Modifier un article</h2>
<!--Erreur titre vide--> <!-- Messages DOM -->
<div id="errorEmpty" class="alert alert-danger d-none"> <div id="messages" class="mb-3"></div>
g Le titre de l'article est obligatoire.
</div>
<!--Erreur image invalide--> <form id="editArticleForm">
<div id="errorImage" class="alert alert-danger d-none">
Format d'image invalide. Formats acceptés : JPG, PNG, GIF.
</div>
<!--Erreur titre existant--> <!-- Titre -->
<div id="errorExists" class="alert alert-danger d-none"> <div class="mb-3">
Ce titre existe déjà. Veuillez en choisir un autre. <label class="form-label fw-bold">Titre *</label>
</div> <input type="text" id="articleTitle" class="form-control">
</div>
<!--Succès--> <!-- Contenu -->
<div id="successMsg" class="alert alert-success d-none"> <div class="mb-3">
L'article a été modifié avec succès ! <label class="form-label fw-bold">Contenu</label>
</div> <textarea id="articleContent"></textarea>
</div>
<!-- Formulaire --> <!-- Catégorie -->
<form id="editArticleForm"> <div class="mb-4">
<label class="form-label fw-bold">Catégorie</label>
<input type="text" id="articleCategory" class="form-control" list="categories">
<datalist id="categories">
<option value="actualités">
<option value="chien">
<option value="chat">
<option value="boutique">
</datalist>
</div>
<!-- Image -->
<div class="mb-4">
<label class="fw-bold">Image actuelle</label>
<div>
<img id="imagePreview" class="preview-img mb-2 d-none" alt="apercu image">
<input type="file" id="articleImage" class="form-control">
</div>
</div>
<!--Titre--> <!-- Publié -->
<div class="mb-3"> <div class="form-check mb-3">
<label class="form-label fw-bold">Titre de l'article (obligatoire)</label> <input class="form-check-input" type="checkbox" id="articlePublished">
<input type="text" id="articleTitle" class="form-control" value="Titre de l'article actuel" placeholder="Modifier le titre"> <label class="form-check-label">Publié (sera publié sur facebook)</label>
</div> </div>
<!--Contenu--> <!-- Boutons -->
<div class="mb-3"> <div class="d-flex gap-3 mt-4">
<label class="form-label fw-bold">Contenu de l'article</label> <a href="../../blog/html/accueil_blog.html" class="btn btn-secondary w-50">Annuler</a>
<textarea id="articleContent" class="form-control" rows="5">Contenu de l'article actuel...</textarea> <button type="submit" class="btn btn-primary w-50">Enregistrer</button>
</div> </div>
<!--Catégorie-->
<div class="mb-4">
<label class="form-label fw-bold">Catégorie de l'article</label>
<input
type="text"
id="articleCategory"
class="form-control"
list="categories"
placeholder="Entrez une catégorie">
<datalist id="categories">
<option value="actualités">
<option value="chien">
<option value="chat">
<option value="boutique">
</datalist>
</div>
<!-- Image actuelle -->
<label class="fw-bold">Image actuelle</label>
<div class="mb-4">
<img src="/blog/categories/images/article1.jpg" alt="Image actuelle" class="preview-img mb-2">
<input type="file" id="articleImage" class="form-control" accept="image/*">
</div>
<!--Publié-->
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="articlePublished" checked>
<label class="form-check-label">Publié (sera publié sur facebook)</label>
</div>
<!--Boutons-->
<div class="d-flex gap-3 mt-4">
<a href="../../blog/html/accueil_blog.html" class="btn btn-secondary w-50">Annuler</a>
<button type="submit" class="btn btn-primary w-50">Enregistrer</button>
</div>
</form>
</form>
</div> </div>
<script>
ClassicEditor
.create(document.querySelector('#articleContent'), {
language: 'fr',
toolbar: [
'heading',
'bold', 'italic', 'underline',
'bulletedList', 'numberedList',
'undo', 'redo'
]
})
</script>
<script src="../js/modifier_article.js"></script> <script src="../js/modifier_article.js"></script>
<script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script>
tinymce.init({
selector: "#articleContent",
height: 400,
language: "fr",
plugins: "lists fullscreen",
toolbar: "undo redo | bold italic underline | bullist numlist | fullscreen",
branding: false,
promotion: false,
menubar: false
});
</script>
</body> </body>
</html> </html>

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modifier une catégorie</title> <title>Modifier une catégorie</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="../../node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="../../css/blog.css"> <link rel="stylesheet" href="../../css/blog.css">

View File

@@ -1,94 +1,102 @@
const form = document.getElementById('ajouterArticleForm'); const form = document.getElementById("ajouterArticleForm");
const imgField = document.getElementById('articleImage'); const messages = document.getElementById("messages");
const titleField = document.getElementById('articleTitle');
const categoryField = document.getElementById('articleCategory');
const publishedField = document.getElementById('articlePublished');
const errorEmpty = document.getElementById('errorEmpty'); const imgField = document.getElementById("articleImage");
const errorImage = document.getElementById('errorImage'); const titleField = document.getElementById("articleTitle");
const errorExists = document.getElementById('errorExists'); const categoryField = document.getElementById("articleCategory");
const successMsg = document.getElementById('successMsg'); const publishedField = document.getElementById("articlePublished");
// Simulation BDD // Simulation BDD
const titreExistants = ['décoration noel', 'coupe de chien']; const titresExistants = ["décoration noel", "coupe de chien"];
form.addEventListener('submit', function(e) { /* =========================
DOM : messages
========================= */
function showMessage(type, text) {
messages.innerHTML = "";
const div = document.createElement("div");
div.className = `alert alert-${type}`;
div.textContent = text;
messages.appendChild(div);
}
/* =========================
Validation image
========================= */
function imageValide(file) {
if (!file) return true;
return ["image/jpeg", "image/png"].includes(file.type);
}
/* =========================
Submit formulaire
========================= */
form.addEventListener("submit", function (e) {
e.preventDefault(); e.preventDefault();
messages.innerHTML = "";
const titre = titleField.value.trim().toLowerCase(); const titre = titleField.value.trim();
const fichierImage = imgField.files[0]; const titreLower = titre.toLowerCase();
const contenu = tinymce.get("articleContent").getContent(); const contenu = tinymce.get("articleContent").getContent().trim();
const categorie = categoryField.value; const categorie = categoryField.value;
const published = publishedField.checked; // récupère la case cochée const image = imgField.files[0];
const published = publishedField.checked;
// Reset messages
errorEmpty.classList.add('d-none');
errorImage.classList.add('d-none');
errorExists.classList.add('d-none');
successMsg.classList.add('d-none');
// Catégorie obligatoire // Catégorie obligatoire
if (categorie === "") { if (!categorie) {
errorEmpty.textContent = "Veuillez choisir une catégorie."; showMessage("danger", "Veuillez choisir une catégorie.");
errorEmpty.classList.remove('d-none');
return; return;
} }
// Titre obligatoire // Titre obligatoire
if (titre === "") { if (!titre) {
errorEmpty.textContent = "Le titre de l'article est obligatoire."; showMessage("danger", "Le titre de l'article est obligatoire.");
errorEmpty.classList.remove('d-none');
return; return;
} }
// Titre déjà existant // Titre existant
if (titreExistants.includes(titre)) { if (titresExistants.includes(titreLower)) {
errorExists.classList.remove('d-none'); showMessage("danger", "Ce titre existe déjà. Choisissez-en un autre.");
return; return;
} }
// Contenu obligatoire // Contenu obligatoire
if (contenu.trim() === "") { if (!contenu) {
errorEmpty.textContent = "Le contenu de l'article ne peut pas être vide."; showMessage("danger", "Le contenu de l'article ne peut pas être vide.");
errorEmpty.classList.remove('d-none');
return; return;
} }
// Image invalide // Image valide
if (fichierImage) { if (!imageValide(image)) {
const validFormats = ['image/jpeg', 'image/png']; showMessage("danger", "Format d'image invalide. JPG ou PNG uniquement.");
if (!validFormats.includes(fichierImage.type)) { return;
errorImage.classList.remove('d-none');
return;
}
} }
// Simuler enregistrement // Enregistrement titre simulé
titreExistants.push(titre); titresExistants.push(titreLower);
// Création article
// CRÉATION DE L'ARTICLE
const nouvelArticle = { const nouvelArticle = {
id: Date.now(), id: Date.now(),
titre: titleField.value.trim(), titre,
contenu: contenu, contenu,
categorie: categorie, categorie,
published: published, // valeur TRUE/FALSE pour afficher le badge Facebook published,
date: new Date().toISOString() date: new Date().toISOString()
}; };
// LocalStorage
// SAUVEGARDE DANS LOCALSTORAGE const articles = JSON.parse(localStorage.getItem("articles")) || [];
let articles = JSON.parse(localStorage.getItem("articles")) || [];
articles.push(nouvelArticle); articles.push(nouvelArticle);
localStorage.setItem("articles", JSON.stringify(articles)); localStorage.setItem("articles", JSON.stringify(articles));
console.log("Article enregistré :", nouvelArticle); showMessage("success", "Article ajouté avec succès !");
// Succès // Reset
successMsg.classList.remove('d-none'); form.reset();
tinymce.get("articleContent").setContent("");
// Redirection // Redirection
setTimeout(() => { setTimeout(() => {
@@ -96,11 +104,13 @@ form.addEventListener('submit', function(e) {
}, 1000); }, 1000);
}); });
// TinyMCE INIT /* =========================
TinyMCE
========================= */
tinymce.init({ tinymce.init({
selector: '#articleContent', selector: "#articleContent",
height: 400, height: 400,
language: 'fr', language: "fr",
plugins: 'lists fullscreen', plugins: "lists fullscreen",
toolbar: 'undo redo | bold italic underline | bullist numlist | fullscreen' toolbar: "undo redo | bold italic underline | bullist numlist | fullscreen"
}); });

View File

@@ -1,60 +1,74 @@
const form = document.getElementById("editArticleForm"); const form = document.getElementById("editArticleForm");
const messages = document.getElementById("messages");
const imgField = document.getElementById("articleImage"); const imgField = document.getElementById("articleImage");
const titleField = document.getElementById("articleTitle"); const titleField = document.getElementById("articleTitle");
const contentField = document.getElementById("articleContent"); const contentField = document.getElementById("articleContent");
const categoryField = document.getElementById("articleCategory"); const categoryField = document.getElementById("articleCategory");
const publishedField = document.getElementById("articlePublished"); const publishedField = document.getElementById("articlePublished");
const errorEmpty = document.getElementById("errorEmpty"); // Simulation BDD pour doublons
const errorImage = document.getElementById("errorImage");
const errorExists = document.getElementById("errorExists");
const successMsg = document.getElementById("successMsg");
// Simulation BDD pour vérifier doublons
const titresExistants = [ const titresExistants = [
"article de test", "article de test",
"nouveautés chiens", "nouveautés chiens",
"actualité du mois", "actualité du mois"
]; ];
function showMessage(type, text) {
messages.innerHTML = "";
const div = document.createElement("div");
div.className = `alert alert-${type}`;
div.textContent = text;
messages.appendChild(div);
}
function imageValide(file) {
if (!file) return true;
return ["image/jpeg", "image/png", "image/gif"].includes(file.type);
}
form.addEventListener("submit", function (e) { form.addEventListener("submit", function (e) {
e.preventDefault(); e.preventDefault();
messages.innerHTML = "";
const titre = titleField.value.trim().toLowerCase(); const titre = titleField.value.trim().toLowerCase();
const fichierImage = imgField.files[0]; const contenu = tinymce.get("articleContent").getContent().trim();
const image = imgField.files[0];
// Reset messages // Titre obligatoire
errorEmpty.classList.add("d-none"); if (!titre) {
errorImage.classList.add("d-none"); showMessage("danger", "Le titre de l'article est obligatoire.");
errorExists.classList.add("d-none");
successMsg.classList.add("d-none");
//Titre obligatoire
if (titre === "") {
errorEmpty.classList.remove("d-none");
return; return;
} }
// Titre déjà existant ? // Titre existant
if (titresExistants.includes(titre)) { if (titresExistants.includes(titre)) {
errorExists.classList.remove("d-none"); showMessage("danger", "Ce titre existe déjà. Veuillez en choisir un autre.");
return; return;
} }
//Vérification image // Contenu obligatoire
if (fichierImage) { if (!contenu) {
const validFormats = ["image/jpeg", "image/png", "image/gif"]; showMessage("danger", "Le contenu de l'article ne peut pas être vide.");
if (!validFormats.includes(fichierImage.type)) { return;
errorImage.classList.remove("d-none"); }
return;
} // Image valide
if (!imageValide(image)) {
showMessage("danger", "Format d'image invalide. JPG, PNG ou GIF uniquement.");
return;
} }
// Succès // Succès
successMsg.classList.remove("d-none"); showMessage("success", "L'article a été modifié avec succès !");
// Redirection après succès // Redirection
setTimeout(() => { setTimeout(() => {
window.location.href = "../../blog/html/accueil_blog.html"; window.location.href = "../../blog/html/accueil_blog.html";
}, 1500); }, 1500);
}); });