ajout et suppression de commentaire

This commit is contained in:
Guams 2025-01-24 20:54:22 +01:00
parent 0109a54356
commit 8ce9b82863
8 changed files with 104 additions and 17 deletions

View File

@ -3,3 +3,9 @@
height: 8rem; height: 8rem;
resize: none; resize: none;
} }
form {
gap: 1rem;
display: flex;
flex-direction: column;
}

View File

@ -1,4 +1,4 @@
<form [formGroup]="commentForm" (ngSubmit)="onSubmit()"> <form [formGroup]="commentForm" (ngSubmit)="onSubmit()">
<textarea class="textarea" [(ngModel)]="commentForm.value.content" maxlength="512" formControlName="content" id="desc" pInputTextarea></textarea> <textarea class="textarea" [(ngModel)]="commentForm.value.content" maxlength="512" formControlName="content" id="desc" pInputTextarea></textarea>
<p-button [disabled]="commentForm.invalid" type="submit" label="Envoyer"></p-button> <p-button [ngStyle]="{ alignSelf: 'flex-end' }" [disabled]="commentForm.invalid" type="submit" label="Envoyer"></p-button>
</form> </form>

View File

@ -8,6 +8,7 @@ import {Author} from '../../models/author';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {Comment} from '../../models/comment'; import {Comment} from '../../models/comment';
import {MessageService} from 'primeng/api'; import {MessageService} from 'primeng/api';
import {NgStyle} from '@angular/common';
@Component({ @Component({
selector: 'app-comment-form', selector: 'app-comment-form',
@ -15,7 +16,8 @@ import {MessageService} from 'primeng/api';
imports: [ imports: [
ReactiveFormsModule, ReactiveFormsModule,
InputTextareaModule, InputTextareaModule,
Button Button,
NgStyle
], ],
templateUrl: './comment-form.component.html', templateUrl: './comment-form.component.html',
styleUrl: './comment-form.component.css' styleUrl: './comment-form.component.css'

View File

@ -50,7 +50,7 @@ export class LoginComponent implements OnDestroy {
.subscribe({ .subscribe({
next: (author: Author) => { next: (author: Author) => {
console.log(author) console.log(author)
this.cookieService.set("author", JSON.stringify(author)); this.cookieService.set("author", JSON.stringify(author), {path: '/'});
this.getAuthorCookie(); this.getAuthorCookie();
this.router.navigate(['/']).then(() => { this.router.navigate(['/']).then(() => {
this.successMessage('Connecté avec succès', 'Heureux de vous revoir ' + this.actualAuthor?.name) this.successMessage('Connecté avec succès', 'Heureux de vous revoir ' + this.actualAuthor?.name)

View File

@ -68,6 +68,13 @@ em {
margin-top: 5rem; margin-top: 5rem;
} }
.delete-dialog {
display: flex;
justify-content: center;
align-items: center;
gap: 3em;
}
.comment-div { .comment-div {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,7 +1,7 @@
<app-header></app-header> <app-header></app-header>
@if (concernedPost) { @if (concernedPost) {
<div class="title-div"> <div class="title-div">
<h1>{{ concernedPost?.title }}</h1> <h1>{{ concernedPost.title }}</h1>
<em>Publié le {{ concernedPost.publicationDate | date: "dd/MM/yyyy à HH:mm" }}</em> <em>Publié le {{ concernedPost.publicationDate | date: "dd/MM/yyyy à HH:mm" }}</em>
</div> </div>
<div [innerHTML]="concernedPost.body | safeHtml" class="body-content"></div> <div [innerHTML]="concernedPost.body | safeHtml" class="body-content"></div>
@ -18,10 +18,26 @@
<em>{{ comment.authorName }}</em> <em>{{ comment.authorName }}</em>
<p class="{{ comment.authorRole }}">- {{ comment.authorRole }}</p> <p class="{{ comment.authorRole }}">- {{ comment.authorRole }}</p>
@if (comment.isUpdated) { @if (comment.isUpdated) {
<p> Mis à jour le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p> <p> Modifié le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p>
} @else { } @else {
<p> Envoyé le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p> <p> Envoyé le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p>
} }
@if (actualAuthor) {
@if (comment.authorId === actualAuthor.id || actualAuthor.role === 'ADMIN') {
<p-button severity="danger" icon="pi pi-trash" (onClick)="setCommentDialogVisible(comment.id)"></p-button>
<p-dialog [closable]="false" [modal]="true" header='Supprimer le commentaire ?' [visible]="commentDeleteDialogMap.get(comment.id) ?? false">
<div class="delete-dialog">
<p-button label="Annuler"
icon="pi pi-times"
severity="info"
(click)="setCommentDialogHidden(comment.id)"/>
<p-button label="Oui" icon="pi pi-trash"
(click)="deleteComment(comment)"
severity="danger"/>
</div>
</p-dialog>
}
}
</div> </div>
} @else { } @else {
<div class="comment-div"> <div class="comment-div">
@ -29,10 +45,26 @@
<em>{{ comment.authorName }}</em> <em>{{ comment.authorName }}</em>
<p class="{{ comment.authorRole }}">- {{ comment.authorRole }}</p> <p class="{{ comment.authorRole }}">- {{ comment.authorRole }}</p>
@if (comment.isUpdated) { @if (comment.isUpdated) {
<p> Mis à jour le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p> <p> Modifié le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p>
} @else { } @else {
<p> Envoyé le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p> <p> Envoyé le {{ comment.commentDate | date: "dd/MM/yyyy à HH:mm" }}</p>
} }
@if (actualAuthor) {
@if (comment.authorId === actualAuthor.id || actualAuthor.role === 'ADMIN') {
<p-button severity="danger" icon="pi pi-trash" (onClick)="setCommentDialogVisible(comment.id)"></p-button>
<p-dialog [closable]="false" [modal]="true" header='Supprimer le commentaire ?' [visible]="commentDeleteDialogMap.get(comment.id) ?? false">
<div class="delete-dialog">
<p-button label="Annuler"
icon="pi pi-times"
severity="info"
(click)="setCommentDialogHidden(comment.id)"/>
<p-button label="Oui" icon="pi pi-trash"
(click)="deleteComment(comment)"
severity="danger"/>
</div>
</p-dialog>
}
}
</div> </div>
} }
<p>{{ comment.content }}</p> <p>{{ comment.content }}</p>

View File

@ -15,6 +15,8 @@ import {CookieService} from 'ngx-cookie-service';
import {Author} from '../../models/author'; import {Author} from '../../models/author';
import {CommentFormComponent} from '../../components/comment-form/comment-form.component'; import {CommentFormComponent} from '../../components/comment-form/comment-form.component';
import {FooterComponent} from '../../components/footer/footer.component'; import {FooterComponent} from '../../components/footer/footer.component';
import {Button} from 'primeng/button';
import {DialogModule} from 'primeng/dialog';
@Component({ @Component({
selector: 'app-post', selector: 'app-post',
@ -26,7 +28,9 @@ import {FooterComponent} from '../../components/footer/footer.component';
CardModule, CardModule,
SafeHtmlPipe, SafeHtmlPipe,
CommentFormComponent, CommentFormComponent,
FooterComponent FooterComponent,
Button,
DialogModule
], ],
templateUrl: './post.component.html', templateUrl: './post.component.html',
styleUrl: './post.component.css' styleUrl: './post.component.css'
@ -36,6 +40,7 @@ export class PostComponent {
comments: Comment[] = []; comments: Comment[] = [];
concernedPost: Post | undefined; concernedPost: Post | undefined;
actualAuthor: Author | undefined; actualAuthor: Author | undefined;
commentDeleteDialogMap: Map<bigint, boolean> = new Map();
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
@ -66,6 +71,7 @@ export class PostComponent {
} }
return 0 return 0
}); });
this.comments.forEach(comment => this.commentDeleteDialogMap.set(comment.id, false));
}, },
error: err => this.failureMessage("Erreur", err.message) error: err => this.failureMessage("Erreur", err.message)
})); }));
@ -81,6 +87,31 @@ export class PostComponent {
this.sortCommentList(this.comments); this.sortCommentList(this.comments);
} }
setCommentDialogVisible(commentId: bigint) {
this.commentDeleteDialogMap.set(commentId, true);
}
setCommentDialogHidden(commentId: bigint) {
this.commentDeleteDialogMap.set(commentId, false);
}
deleteComment(comment: Comment) {
const token = this.cookieService.get('token');
if (token) {
this.subs.push(
this.commentService.delete(comment.id, token).subscribe({
next: () => {
this.comments = this.comments.filter(c => c.id !== comment.id);
this.successMessage('Succès', 'Le commentaire a été supprimé avec succès');
this.setCommentDialogHidden(comment.id);
this.commentDeleteDialogMap.delete(comment.id);
},
error: err => this.failureMessage("Erreur", err.message)
})
);
}
}
sortCommentList(comments: Comment[]) { sortCommentList(comments: Comment[]) {
comments.sort((a, b) => { comments.sort((a, b) => {
if (a.commentDate > b.commentDate) { if (a.commentDate > b.commentDate) {
@ -92,6 +123,16 @@ export class PostComponent {
}) })
} }
successMessage(summary: string, detail: string): void {
this.messageService.add({
severity: 'success',
summary: summary,
detail: detail,
life: 3000,
closable: false
});
}
failureMessage(summary: string, detail: string): void { failureMessage(summary: string, detail: string): void {
this.messageService.add({ this.messageService.add({
severity: 'error', severity: 'error',

View File

@ -22,14 +22,13 @@ export class CommentService {
}; };
return this.httpClient.post<Comment>(`${this.url}/posts/${postId}`, {postId: postId, authorId: authorId, content: content}, httpOptions); return this.httpClient.post<Comment>(`${this.url}/posts/${postId}`, {postId: postId, authorId: authorId, content: content}, httpOptions);
} }
}
// POST localhost:8080/api/comments/posts/1 delete(commentId: bigint, token: string) {
// Content-Type: application/json const httpOptions = {
// Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ3cml0ZXIiLCJpYXQiOjE3MzY2OTYwNDgsImV4cCI6MTczNjczMjA0OH0.lHkOTGUzklZFJvm3poEhU5RhcG32y-ew-I2WpqDLVOs headers: new HttpHeaders({
// 'Authorization': `Bearer ${token}`
// { })
// "postId": 1, };
// "content": "test", return this.httpClient.delete<Comment>(`${this.url}/${commentId}`, httpOptions);
// "authorId": "2c8c4079-8649-4086-9a4e-3d7ddcb402d8" }
// } }