diff --git a/sae/WEB-INF/src/controleur/DeleteFil.java b/sae/WEB-INF/src/controleur/DeleteFil.java new file mode 100644 index 0000000000000000000000000000000000000000..a119c57c6f55f187bc76765bc0debc4b89a94ae8 --- /dev/null +++ b/sae/WEB-INF/src/controleur/DeleteFil.java @@ -0,0 +1,29 @@ +package controleur; + +import java.io.IOException; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import modele.FilDeDiscussionDAO; + +@WebServlet("/deleteFil") +public class DeleteFil extends HttpServlet { + + public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { + if (req.getSession(false) == null || req.getSession().getAttribute("email") == null) { + res.sendRedirect(req.getContextPath() + "/login"); + return; + } + int id = Integer.parseInt(req.getParameter("id")); + FilDeDiscussionDAO filDao = new FilDeDiscussionDAO(); + if (filDao.delete(id)) { + req.setAttribute("success", "Fil de discussion supprimé."); + } else { + req.setAttribute("error", "Erreur lors de la suppression du fil de discussion."); + } + res.sendRedirect(req.getContextPath() + "/listerFil"); + } +} diff --git a/sae/WEB-INF/src/controleur/Delete.java b/sae/WEB-INF/src/controleur/DeleteMessage.java similarity index 94% rename from sae/WEB-INF/src/controleur/Delete.java rename to sae/WEB-INF/src/controleur/DeleteMessage.java index 68315c50c563cb1b5326bccf78264658ee4bae1f..efd56d4920ba3549b67cc965bf74524c079a9307 100644 --- a/sae/WEB-INF/src/controleur/Delete.java +++ b/sae/WEB-INF/src/controleur/DeleteMessage.java @@ -9,8 +9,8 @@ import jakarta.servlet.http.HttpServletResponse; import modele.Message; import modele.MessageDao; -@WebServlet("/delete") -public class Delete extends HttpServlet { +@WebServlet("/deleteMessage") +public class DeleteMessage extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { if (req.getSession(false) == null || req.getSession().getAttribute("email") == null) { res.sendRedirect(req.getContextPath() + "/login"); diff --git a/sae/WEB-INF/src/controleur/Fil.java b/sae/WEB-INF/src/controleur/Fil.java index f9a529d6983d8b6ab8d321e1286b94e07ff133b3..e53e86cd59a59aa426219f086d95f31c0c7c2433 100644 --- a/sae/WEB-INF/src/controleur/Fil.java +++ b/sae/WEB-INF/src/controleur/Fil.java @@ -23,6 +23,7 @@ public class Fil extends HttpServlet { return; } req.setAttribute("id", id); + req.getSession().setAttribute("idFil", id); req.getRequestDispatcher("/WEB-INF/vue/fil.jsp").forward(req, res); } } diff --git a/sae/WEB-INF/src/controleur/MenuFil.java b/sae/WEB-INF/src/controleur/MenuFil.java new file mode 100644 index 0000000000000000000000000000000000000000..bbd05d1261a746052cf498022eabdcfea5189aa2 --- /dev/null +++ b/sae/WEB-INF/src/controleur/MenuFil.java @@ -0,0 +1,19 @@ +package controleur; + +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import java.io.IOException; + +@WebServlet("/menuFil") +public class MenuFil extends HttpServlet { + public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { + if (req.getSession(false) == null || req.getSession().getAttribute("email") == null) { + res.sendRedirect(req.getContextPath() + "/login"); + return; + } + req.getRequestDispatcher("/WEB-INF/vue/menuFil.jsp").forward(req, res); + } +} diff --git a/sae/WEB-INF/src/controleur/ModifierFil.java b/sae/WEB-INF/src/controleur/ModifierFil.java new file mode 100644 index 0000000000000000000000000000000000000000..9ae7d8e761876fbd7eb63baa290031752f027a80 --- /dev/null +++ b/sae/WEB-INF/src/controleur/ModifierFil.java @@ -0,0 +1,73 @@ +package controleur; + +import java.io.File; +import java.io.IOException; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Part; +import modele.FilDeDiscussion; +import modele.FilDeDiscussionDAO; +import org.apache.commons.text.StringEscapeUtils; + +@WebServlet("/modifierFil") +@MultipartConfig( + maxFileSize = 1024 * 1024 * 5, + maxRequestSize = 1024 * 1024 * 10, + fileSizeThreshold = 0 +) +public class ModifierFil extends HttpServlet { + private static final String UPLOAD_DIR = "uploads"; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { + if (req.getSession(false) == null || req.getSession().getAttribute("email") == null) { + res.sendRedirect(req.getContextPath() + "/login"); + return; + } + if (req.getSession().getAttribute("idFil") == null) { + res.sendRedirect(req.getContextPath() + "/listerFil"); + return; + } + int id = Integer.parseInt(req.getSession().getAttribute("idFil").toString()); + String nom = StringEscapeUtils.escapeHtml4(req.getParameter("nom")); + String description = StringEscapeUtils.escapeHtml4(req.getParameter("description")); + + Part filePart = req.getPart("file"); + String fileName = null; + if (filePart != null && filePart.getSize() > 0) { + fileName = getFileName(filePart); + String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIR; + File uploadDir = new File(uploadPath); + if (!uploadDir.exists()) { + uploadDir.mkdir(); + } + filePart.write(uploadPath + File.separator + fileName); + } + + FilDeDiscussionDAO fddao = new FilDeDiscussionDAO(); + FilDeDiscussion fil = fddao.findById(id); + fil.setNom(nom); + fil.setDescription(description); + if (fileName != null) { + fil.setLogo(fileName); + } + fddao.update(fil); + + res.sendRedirect(req.getContextPath() + "/fil?id=" + id); + } + + private String getFileName(Part part) { + String contentDisposition = part.getHeader("content-disposition"); + for (String cd : contentDisposition.split(";")) { + if (cd.trim().startsWith("filename")) { + return cd.substring(cd.indexOf('=') + 1).trim().replace("\"", ""); + } + } + return null; + } +} diff --git a/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java b/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java index 38a0e5464cce87d122b47721cffae18b6c2e4926..15ca49d8a1be9c4d4306ad1782cd4d3aaeaf599b 100644 --- a/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java +++ b/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java @@ -64,13 +64,30 @@ public class FilDeDiscussionDAO { return filsDeDiscussion; } - public void delete(int id) { + public boolean delete(int id) { try (Connection con = DS.instance.getConnection()) { PreparedStatement pstmt = con.prepareStatement("DELETE FROM filDeDiscussion WHERE id = ?"); pstmt.setInt(1, id); + int modif = pstmt.executeUpdate(); + return modif > 0; + } catch (Exception e) { + System.err.println(e.getMessage()); + } + return false; + } + + public void update(FilDeDiscussion filDeDiscussion) { + try (Connection con = DS.instance.getConnection()) { + PreparedStatement pstmt = con + .prepareStatement("UPDATE filDeDiscussion SET nom = ?, description = ?, logo = ? WHERE id = ?"); + pstmt.setString(1, filDeDiscussion.getNom()); + pstmt.setString(2, filDeDiscussion.getDescription()); + pstmt.setString(3, filDeDiscussion.getLogo()); + pstmt.setInt(4, filDeDiscussion.getId()); pstmt.executeUpdate(); } catch (Exception e) { System.err.println(e.getMessage()); } } + } diff --git a/sae/WEB-INF/vue/fil.jsp b/sae/WEB-INF/vue/fil.jsp index cb3fe84500828782c52d8b669eda509c4cdc474b..3ef1a0345ab2be035bbd399f46538198307fa27e 100644 --- a/sae/WEB-INF/vue/fil.jsp +++ b/sae/WEB-INF/vue/fil.jsp @@ -43,9 +43,11 @@ <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> + <div class="flex-1 p-6 flex flex-col"> <% + String email = (String) session.getAttribute("email"); int id = Integer.parseInt(request.getParameter("id")); session.setAttribute("filId", id); FilDeDiscussionDAO fddao = new FilDeDiscussionDAO(); @@ -55,6 +57,14 @@ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM yyyy 'à' HH:mm"); %> + <% if (email.equals(fil.getCreateurEmail())) { %> + <div class="flex justify-end"> + <form action="<%= request.getContextPath() %>/menuFil" method="post" enctype="multipart/form-data"> + <input type="hidden" name="id" value="<%= fil.getId() %>"> + <button type="submit" class="bg-yellow-500 text-white px-4 py-2 rounded-lg shadow-md hover:bg-yellow-600 transition-colors">Modifier le fil</button> + </form> + </div> + <% } %> <div class="container mx-auto px-4 mt-8"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg"> <h2 class="text-2xl font-bold mb-4 text-center"><%= fil.getNom() %></h2> @@ -87,7 +97,7 @@ </form> </div> <% if (session.getAttribute("email").equals(m.getAuteurEmail())) { %> - <form action="<%= request.getContextPath() %>/delete" method="post" class="mt-2"> + <form action="<%= request.getContextPath() %>/deleteMessage" method="post" class="mt-2"> <input type="hidden" name="messageId" value="<%= m.getId() %>"> <button type="submit" class="text-red-500 hover:text-red-700">delete</button> </form> diff --git a/sae/WEB-INF/vue/menuFil.jsp b/sae/WEB-INF/vue/menuFil.jsp new file mode 100644 index 0000000000000000000000000000000000000000..3c95d9fa491303302d98a0bd720baa001ba4f0ad --- /dev/null +++ b/sae/WEB-INF/vue/menuFil.jsp @@ -0,0 +1,64 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="modele.FilDeDiscussion" %> +<%@ page import="modele.FilDeDiscussionDAO" %> + +<% + int id = Integer.parseInt(session.getAttribute("filId").toString()); + FilDeDiscussionDAO fddao = new FilDeDiscussionDAO(); + FilDeDiscussion fil = fddao.findById(id); +%> + +<!DOCTYPE html> +<html lang="fr"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Modifier Fil de Discussion</title> + <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> + <link rel="shortcut icon" href="<%= request.getContextPath() %>/images/logo.png"> +</head> +<body class="bg-gray-900 text-white flex"> + <aside class="w-64 bg-gray-800 text-white h-screen flex flex-col fixed"> + <div class="p-4 text-center"> + <img src="<%= request.getContextPath() %>/images/logo.png" alt="CampusTalk Logo" class="w-16 h-16 mx-auto"> + <h1 class="text-2xl font-bold mt-4">CampusTalk</h1> + </div> + <nav class="mt-4 flex-grow"> + <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> + <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> + <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> + </nav> + </aside> + <div class="flex-1 p-6"> + <div class="max-w-2xl mx-auto mt-8 p-6 bg-gray-800 rounded-lg shadow-lg"> + <h2 class="text-2xl font-bold mb-4 text-center">Modifier le Fil de Discussion</h2> + <form action="<%= request.getContextPath() %>/modifierFil" method="post" enctype="multipart/form-data"> + <input type="hidden" name="id" value="<%= fil.getId() %>"> + <div class="mb-4"> + <label for="nom" class="block text-gray-300 font-semibold">Nom :</label> + <input type="text" id="nom" name="nom" value="<%= fil.getNom() %>" class="w-full p-3 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 bg-gray-700 text-white" required> + </div> + <div class="mb-4"> + <label for="description" class="block text-gray-300 font-semibold">Description :</label> + <textarea id="description" name="description" class="w-full p-3 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 bg-gray-700 text-white" rows="3" required><%= fil.getDescription() %></textarea> + </div> + <div class="mb-4"> + <label for="file" class="block text-gray-300 font-semibold">Logo :</label> + <input type="file" id="file" name="file" class="w-full p-3 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 bg-gray-700 text-white"> + <% if (fil.getLogo() != null) { %> + <img src="<%= request.getContextPath() %>/uploads/<%= fil.getLogo() %>" alt="Logo" class="mt-2 message-image"> + <% } %> + </div> + <div class="flex justify-between"> + <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded-lg shadow-md hover:bg-blue-600 transition-colors">Sauvegarder</button> + <form action="<%= request.getContextPath() %>/deleteFil" method="post"> + <input type="hidden" name="id" value="<%= fil.getId() %>"> + <button type="submit" class="bg-red-500 text-white px-4 py-2 rounded-lg shadow-md hover:bg-red-600 transition-colors">Supprimer</button> + </form> + </div> + </form> + </div> + </div> +</body> +</html>