Add the post component.
This commit is contained in:
@@ -14,6 +14,9 @@ import { appRoutes } from './app.routing';
|
||||
// Guard
|
||||
import { AuthGuard } from './core/guards/auth.guard';
|
||||
|
||||
// Interceptor
|
||||
import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interceptor';
|
||||
|
||||
// Components
|
||||
import { AppComponent } from './app.component';
|
||||
import { HeaderComponent } from './header/header.component';
|
||||
@@ -24,6 +27,7 @@ import { MyPostsComponent } from './posts/myPosts/my-posts.component';
|
||||
import { AccountSettingsComponent } from './account-settings/account-settings.component';
|
||||
import { ChangePasswordComponent } from './account-settings/change-password/change-password.component';
|
||||
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
||||
import { PostComponent } from './posts/post.component';
|
||||
|
||||
// Reusable components
|
||||
import { PostCardComponent } from './core/post-card/post-card.component';
|
||||
@@ -37,7 +41,7 @@ import { LoginService } from './login/login.service';
|
||||
import { MyPostsService } from './posts/myPosts/my-posts.service';
|
||||
import { ChangePasswordService } from './account-settings/change-password/change-password.service';
|
||||
import { ProfilEditionService } from './account-settings/profil-edition/profil-edition.service';
|
||||
import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interceptor';
|
||||
import { PostService } from './posts/post.service';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -51,7 +55,8 @@ import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interc
|
||||
MyPostsComponent,
|
||||
AccountSettingsComponent,
|
||||
ChangePasswordComponent,
|
||||
ProfilEditionComponent
|
||||
ProfilEditionComponent,
|
||||
PostComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@@ -74,6 +79,7 @@ import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interc
|
||||
MyPostsService,
|
||||
ChangePasswordService,
|
||||
ProfilEditionService,
|
||||
PostService,
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: UnauthorizedInterceptor, multi: true }
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
|
||||
@@ -9,6 +9,7 @@ import { MyPostsComponent } from './posts/myPosts/my-posts.component';
|
||||
import { AccountSettingsComponent } from './account-settings/account-settings.component';
|
||||
import { ChangePasswordComponent } from './account-settings/change-password/change-password.component';
|
||||
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
||||
import { PostComponent } from './posts/post.component';
|
||||
|
||||
export const appRoutes: Routes = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||
@@ -19,5 +20,6 @@ export const appRoutes: Routes = [
|
||||
{ path: 'accountSettings', component: AccountSettingsComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'changePassword', component: ChangePasswordComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'profilEdit', component: ProfilEditionComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'posts/:postKey', component: PostComponent },
|
||||
{ path: '**', redirectTo: '/home' }
|
||||
];
|
||||
|
||||
67
src/main/ts-v7/src/app/posts/post.component.html
Normal file
67
src/main/ts-v7/src/app/posts/post.component.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<div id="content" *ngIf="!notFound">
|
||||
<app-spinner *ngIf="!loaded"></app-spinner>
|
||||
<div class="card" *ngIf="loaded">
|
||||
<img [src]="post?.image" class="img-fluid" alt="Post image">
|
||||
|
||||
<a *ngIf="owned" class="btn-card-floating waves-light white-text"
|
||||
routerLink="/posts/update/{{post.key}}">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
|
||||
<div class="card-body">
|
||||
<h1 class="card-title">{{post.title}}</h1>
|
||||
<h4>{{post.description}}</h4>
|
||||
<hr/>
|
||||
<div [innerHTML]="getContent()"></div>
|
||||
</div>
|
||||
|
||||
<div class="card-data">
|
||||
<img [src]="getAvatarUrl()"
|
||||
class="author-img"
|
||||
[alt]="post.author.name"
|
||||
[mdbTooltip]="post.author.name"
|
||||
placement="bottom"/>
|
||||
Article écrit par {{post.author.name}}
|
||||
<span class="creation-date-area">({{post.creationDate | date:'HH:mm:ss dd/MM/yyyy'}})</span>
|
||||
<button *ngIf="owned" type="button" class="btn btn-danger waves-light float-right" (click)="alertDelete.show()" mdbRippleRadius>
|
||||
<i class="fa fa-trash mr-1"></i> Supprimer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div mdbModal #alertDelete="mdb-modal" class="modal fade" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-notify modal-danger" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<p class="heading lead">Suppression de l'article</p>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="alertDelete.hide()">
|
||||
<span aria-hidden="true" class="white-text">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-center">
|
||||
<p>Êtes vous sûr de vouloir supprimer cet article ?</p>
|
||||
<p *ngIf="postDeletionFailed" class="red-text">
|
||||
Une erreur est survenue lors de la suppression de l'article.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a type="button"
|
||||
class="btn btn-outline-secondary-modal"
|
||||
data-dismiss="modal"
|
||||
(click)="alertDelete.hide()"
|
||||
mdbRippleRadius>
|
||||
Annuler
|
||||
</a>
|
||||
<a type="button" mdbRippleRadius
|
||||
class="btn btn-primary-modal waves-light"
|
||||
(click)="deletePost()">
|
||||
<i class="fa fa-trash"></i> Supprimer
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <app-not-found *ngIf="notFound"></app-not-found> -->
|
||||
106
src/main/ts-v7/src/app/posts/post.component.ts
Normal file
106
src/main/ts-v7/src/app/posts/post.component.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Component, OnInit, SecurityContext, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
|
||||
import { Post, User } from '../core/entities';
|
||||
import { PostService } from './post.service';
|
||||
import { AuthService } from '../core/services/auth.service';
|
||||
|
||||
declare let Prism: any;
|
||||
|
||||
@Component({
|
||||
selector: 'app-post',
|
||||
templateUrl: './post.component.html',
|
||||
styles: [`
|
||||
.author-img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.card .card-data {
|
||||
padding: 15px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
#content {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
.creation-date-area {
|
||||
color: #bdbdbd;
|
||||
font-style: italic;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class PostComponent implements OnInit {
|
||||
post: Post = new Post('', '', '', '', '', null, new User('', '', '', '', '', null, null, ''), null);
|
||||
loaded: boolean;
|
||||
notFound: boolean;
|
||||
owned: boolean;
|
||||
|
||||
@ViewChild('alertDelete') alertDelete;
|
||||
|
||||
postDeletionFailed: boolean;
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private postService: PostService,
|
||||
private sanitizer: DomSanitizer,
|
||||
private authService: AuthService
|
||||
) {
|
||||
this.loaded = false;
|
||||
this.owned = false;
|
||||
this.postDeletionFailed = false;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.postService.getPost(this.activatedRoute.snapshot.paramMap.get('postKey')).subscribe(post => {
|
||||
this.post = post;
|
||||
this.loaded = true;
|
||||
this.owned = this.isOwned();
|
||||
setTimeout(() => {
|
||||
Prism.highlightAll();
|
||||
}, 100);
|
||||
}, error => {
|
||||
if (error instanceof HttpErrorResponse && error.status === 404) {
|
||||
this.notFound = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private isOwned(): boolean {
|
||||
let result = false;
|
||||
|
||||
const connectedUser = this.authService.getUser();
|
||||
if (connectedUser) {
|
||||
result = this.post.author.key === connectedUser.key;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
getContent(): SafeHtml {
|
||||
return this.sanitizer.sanitize(SecurityContext.HTML, this.post.text);
|
||||
}
|
||||
|
||||
getAvatarUrl(): string {
|
||||
return this.post.author.image
|
||||
? `./api/images/loadAvatar/${this.post.author.image}`
|
||||
: './assets/images/default_user.png';
|
||||
}
|
||||
|
||||
deletePost(): void {
|
||||
this.postDeletionFailed = false;
|
||||
|
||||
this.postService.deletePost(this.post).subscribe(() => {
|
||||
this.alertDelete.hide();
|
||||
this.router.navigate(['/myPosts']);
|
||||
}, error => {
|
||||
this.postDeletionFailed = true;
|
||||
setTimeout(() => {
|
||||
this.postDeletionFailed = false;
|
||||
}, 3500);
|
||||
});
|
||||
}
|
||||
}
|
||||
18
src/main/ts-v7/src/app/posts/post.service.ts
Normal file
18
src/main/ts-v7/src/app/posts/post.service.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Post } from '../core/entities';
|
||||
|
||||
@Injectable()
|
||||
export class PostService {
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getPost(postKey: string): Observable<Post> {
|
||||
return this.http.get<Post>(`/api/posts/${postKey}`);
|
||||
}
|
||||
|
||||
deletePost(postToDelete: Post): Observable<any> {
|
||||
return this.http.delete(`/api/posts/${postToDelete.key}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user