FEAT : Ajout des commentaires

This commit is contained in:
2025-12-01 21:47:15 +01:00
parent ca3e693969
commit 4a35c375ec
16 changed files with 234 additions and 6 deletions

View File

@@ -4,6 +4,7 @@ import local.epul4a.fotosharing.model.Photo;
import local.epul4a.fotosharing.model.Utilisateur; import local.epul4a.fotosharing.model.Utilisateur;
import local.epul4a.fotosharing.repository.PhotoRepository; import local.epul4a.fotosharing.repository.PhotoRepository;
import local.epul4a.fotosharing.security.CustomUserDetails; import local.epul4a.fotosharing.security.CustomUserDetails;
import local.epul4a.fotosharing.service.CommentaireService;
import local.epul4a.fotosharing.service.PhotoService; import local.epul4a.fotosharing.service.PhotoService;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.PathResource; import org.springframework.core.io.PathResource;
@@ -25,10 +26,12 @@ public class PhotoController {
private final PhotoService photoService; private final PhotoService photoService;
private final PhotoRepository photoRepository; private final PhotoRepository photoRepository;
private final CommentaireService commentaireService;
public PhotoController(PhotoService photoService, PhotoRepository photoRepository) { public PhotoController(PhotoService photoService, PhotoRepository photoRepository, CommentaireService commentaireService) {
this.photoService = photoService; this.photoService = photoService;
this.photoRepository = photoRepository; this.photoRepository = photoRepository;
this.commentaireService = commentaireService;
} }
@GetMapping("/upload") @GetMapping("/upload")
@@ -91,6 +94,37 @@ public class PhotoController {
return "galerie"; return "galerie";
} }
@GetMapping("/photo/{id}")
public String viewPhoto(@PathVariable Long id,
Model model,
Authentication auth) {
Photo photo = photoRepository.findById(id).orElse(null);
if (photo == null) {
return "redirect:/galerie";
}
model.addAttribute("photo", photo);
model.addAttribute("commentaires", commentaireService.listByPhoto(id));
// utilisateur connecté (peut être null si visiteur)
String currentUser = (auth != null ? auth.getName() : null);
model.addAttribute("currentUser", currentUser);
return "photo-detail";
}
@PostMapping("/photo/{id}/comment")
public String addComment(@PathVariable Long id,
@RequestParam String contenu,
Authentication auth) {
if (auth == null) {
return "redirect:/login";
}
String email = auth.getName();
commentaireService.addComment(id, email, contenu);
return "redirect:/photo/" + id;
}
} }

View File

@@ -0,0 +1,11 @@
package local.epul4a.fotosharing.repository;
import local.epul4a.fotosharing.model.Commentaire;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CommentaireRepository extends JpaRepository<Commentaire, Long> {
List<Commentaire> findByPhoto_IdOrderByDateCommentaireAsc(Long photoId);
}

View File

@@ -39,7 +39,7 @@ public class SecurityConfig {
http http
.userDetailsService(customUserDetailsService) // Utiliser directement le UserDetailsService .userDetailsService(customUserDetailsService) // Utiliser directement le UserDetailsService
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers("/register", "/login", "/css/**", "/js/**", "/photo/*/raw", "/galerie").permitAll() .requestMatchers("/register", "/login", "/css/**", "/js/**", "/galerie", "/photo/*", "/photo/*/raw").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
) )
.formLogin(form -> form .formLogin(form -> form

View File

@@ -0,0 +1,9 @@
package local.epul4a.fotosharing.service;
import local.epul4a.fotosharing.model.Commentaire;
import java.util.List;
public interface CommentaireService {
List<Commentaire> listByPhoto(Long photoId);
void addComment(Long photoId, String email, String contenu);
}

View File

@@ -0,0 +1,50 @@
package local.epul4a.fotosharing.service.impl;
import local.epul4a.fotosharing.model.Commentaire;
import local.epul4a.fotosharing.model.Photo;
import local.epul4a.fotosharing.model.Utilisateur;
import local.epul4a.fotosharing.repository.CommentaireRepository;
import local.epul4a.fotosharing.repository.PhotoRepository;
import local.epul4a.fotosharing.repository.UtilisateurRepository;
import local.epul4a.fotosharing.service.CommentaireService;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class CommentaireServiceImpl implements CommentaireService {
private final CommentaireRepository commentaireRepository;
private final PhotoRepository photoRepository;
private final UtilisateurRepository utilisateurRepository;
public CommentaireServiceImpl(CommentaireRepository commentaireRepository,
PhotoRepository photoRepository,
UtilisateurRepository utilisateurRepository) {
this.commentaireRepository = commentaireRepository;
this.photoRepository = photoRepository;
this.utilisateurRepository = utilisateurRepository;
}
@Override
public List<Commentaire> listByPhoto(Long photoId) {
return commentaireRepository.findByPhoto_IdOrderByDateCommentaireAsc(photoId);
}
@Override
public void addComment(Long photoId, String email, String contenu) {
Photo photo = photoRepository.findById(photoId)
.orElseThrow(() -> new RuntimeException("Photo introuvable"));
Utilisateur user = utilisateurRepository.findByEmail(email)
.orElseThrow(() -> new RuntimeException("Utilisateur introuvable"));
Commentaire c = new Commentaire();
c.setPhoto(photo);
c.setAuteur(user);
c.setContenu(contenu);
c.setDateCommentaire(LocalDateTime.now());
commentaireRepository.save(c);
}
}

View File

@@ -10,7 +10,7 @@
<li th:each="p : ${photos}"> <li th:each="p : ${photos}">
<span th:text="${p.nomFichierOriginal}">nom</span> <span th:text="${p.nomFichierOriginal}">nom</span>
<a th:href="@{'/photo/' + ${p.id} + '/raw'}" target="_blank">Voir</a> <a th:href="@{'/photo/' + ${p.id}}">Voir</a>
</li> </li>
</ul> </ul>
</body> </body>

View File

@@ -18,7 +18,7 @@
<li th:each="p : ${photos}"> <li th:each="p : ${photos}">
<span th:text="${p.nomFichierOriginal}">Nom du fichier</span> <span th:text="${p.nomFichierOriginal}">Nom du fichier</span>
<a th:href="@{'/photo/' + ${p.id} + '/raw'}" target="_blank">Voir</a> <a th:href="@{'/photo/' + ${p.id}}">Voir</a>
</li> </li>
</ul> </ul>

View File

@@ -0,0 +1,62 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8"/>
<title>Détail de la photo</title>
</head>
<body>
<h1>Détail de la photo</h1>
<p>
<a th:href="@{/}">Accueil</a> |
<a th:href="@{/galerie}">Galerie publique</a> |
<a th:href="@{/mes-photos}">Mes photos</a>
</p>
<!-- Affichage de la photo -->
<div>
<img th:src="@{'/photo/' + ${photo.id} + '/raw'}"
alt="Photo"
style="max-width:500px; border:1px solid #ccc; margin:20px 0;"/>
</div>
<!-- Infos -->
<ul>
<li><strong>Nom original :</strong> <span th:text="${photo.nomFichierOriginal}"></span></li>
<li><strong>Date upload :</strong> <span th:text="${photo.dateUpload}"></span></li>
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
</ul>
<!-- Commentaires -->
<h2>Commentaires</h2>
<div th:if="${#lists.isEmpty(commentaires)}">
<p>Aucun commentaire pour l'instant.</p>
</div>
<ul th:if="${!#lists.isEmpty(commentaires)}">
<li th:each="c : ${commentaires}">
<strong th:text="${c.auteur.email}">Auteur</strong> :
<span th:text="${c.contenu}"></span>
<em>(<span th:text="${c.dateCommentaire}"></span>)</em>
</li>
</ul>
<!-- Formulaire d'ajout de commentaire -->
<div th:if="${currentUser}">
<h3>Ajouter un commentaire</h3>
<form th:action="@{'/photo/' + ${photo.id} + '/comment'}" method="post">
<textarea name="contenu" rows="3" cols="50"></textarea><br/>
<button type="submit">Envoyer</button>
</form>
</div>
<div th:if="${currentUser == null}">
<p><a th:href="@{/login}">Connectez-vous</a> pour commenter.</p>
</div>
<p>
<a th:href="@{'/photo/' + ${photo.id} + '/raw'}" target="_blank">Voir en grande taille</a>
</p>
</body>
</html>

View File

@@ -10,7 +10,7 @@
<li th:each="p : ${photos}"> <li th:each="p : ${photos}">
<span th:text="${p.nomFichierOriginal}">nom</span> <span th:text="${p.nomFichierOriginal}">nom</span>
<a th:href="@{'/photo/' + ${p.id} + '/raw'}" target="_blank">Voir</a> <a th:href="@{'/photo/' + ${p.id}}">Voir</a>
</li> </li>
</ul> </ul>
</body> </body>

View File

@@ -18,7 +18,7 @@
<li th:each="p : ${photos}"> <li th:each="p : ${photos}">
<span th:text="${p.nomFichierOriginal}">Nom du fichier</span> <span th:text="${p.nomFichierOriginal}">Nom du fichier</span>
<a th:href="@{'/photo/' + ${p.id} + '/raw'}" target="_blank">Voir</a> <a th:href="@{'/photo/' + ${p.id}}">Voir</a>
</li> </li>
</ul> </ul>

View File

@@ -0,0 +1,62 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8"/>
<title>Détail de la photo</title>
</head>
<body>
<h1>Détail de la photo</h1>
<p>
<a th:href="@{/}">Accueil</a> |
<a th:href="@{/galerie}">Galerie publique</a> |
<a th:href="@{/mes-photos}">Mes photos</a>
</p>
<!-- Affichage de la photo -->
<div>
<img th:src="@{'/photo/' + ${photo.id} + '/raw'}"
alt="Photo"
style="max-width:500px; border:1px solid #ccc; margin:20px 0;"/>
</div>
<!-- Infos -->
<ul>
<li><strong>Nom original :</strong> <span th:text="${photo.nomFichierOriginal}"></span></li>
<li><strong>Date upload :</strong> <span th:text="${photo.dateUpload}"></span></li>
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
</ul>
<!-- Commentaires -->
<h2>Commentaires</h2>
<div th:if="${#lists.isEmpty(commentaires)}">
<p>Aucun commentaire pour l'instant.</p>
</div>
<ul th:if="${!#lists.isEmpty(commentaires)}">
<li th:each="c : ${commentaires}">
<strong th:text="${c.auteur.email}">Auteur</strong> :
<span th:text="${c.contenu}"></span>
<em>(<span th:text="${c.dateCommentaire}"></span>)</em>
</li>
</ul>
<!-- Formulaire d'ajout de commentaire -->
<div th:if="${currentUser}">
<h3>Ajouter un commentaire</h3>
<form th:action="@{'/photo/' + ${photo.id} + '/comment'}" method="post">
<textarea name="contenu" rows="3" cols="50"></textarea><br/>
<button type="submit">Envoyer</button>
</form>
</div>
<div th:if="${currentUser == null}">
<p><a th:href="@{/login}">Connectez-vous</a> pour commenter.</p>
</div>
<p>
<a th:href="@{'/photo/' + ${photo.id} + '/raw'}" target="_blank">Voir en grande taille</a>
</p>
</body>
</html>