Add the post component.
This commit is contained in:
@@ -14,6 +14,9 @@ import { appRoutes } from './app.routing';
|
|||||||
// Guard
|
// Guard
|
||||||
import { AuthGuard } from './core/guards/auth.guard';
|
import { AuthGuard } from './core/guards/auth.guard';
|
||||||
|
|
||||||
|
// Interceptor
|
||||||
|
import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interceptor';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { HeaderComponent } from './header/header.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 { AccountSettingsComponent } from './account-settings/account-settings.component';
|
||||||
import { ChangePasswordComponent } from './account-settings/change-password/change-password.component';
|
import { ChangePasswordComponent } from './account-settings/change-password/change-password.component';
|
||||||
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
||||||
|
import { PostComponent } from './posts/post.component';
|
||||||
|
|
||||||
// Reusable components
|
// Reusable components
|
||||||
import { PostCardComponent } from './core/post-card/post-card.component';
|
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 { MyPostsService } from './posts/myPosts/my-posts.service';
|
||||||
import { ChangePasswordService } from './account-settings/change-password/change-password.service';
|
import { ChangePasswordService } from './account-settings/change-password/change-password.service';
|
||||||
import { ProfilEditionService } from './account-settings/profil-edition/profil-edition.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({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -51,7 +55,8 @@ import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interc
|
|||||||
MyPostsComponent,
|
MyPostsComponent,
|
||||||
AccountSettingsComponent,
|
AccountSettingsComponent,
|
||||||
ChangePasswordComponent,
|
ChangePasswordComponent,
|
||||||
ProfilEditionComponent
|
ProfilEditionComponent,
|
||||||
|
PostComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@@ -74,6 +79,7 @@ import { UnauthorizedInterceptor } from './core/interceptors/unauthorized.interc
|
|||||||
MyPostsService,
|
MyPostsService,
|
||||||
ChangePasswordService,
|
ChangePasswordService,
|
||||||
ProfilEditionService,
|
ProfilEditionService,
|
||||||
|
PostService,
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: UnauthorizedInterceptor, multi: true }
|
{ provide: HTTP_INTERCEPTORS, useClass: UnauthorizedInterceptor, multi: true }
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { MyPostsComponent } from './posts/myPosts/my-posts.component';
|
|||||||
import { AccountSettingsComponent } from './account-settings/account-settings.component';
|
import { AccountSettingsComponent } from './account-settings/account-settings.component';
|
||||||
import { ChangePasswordComponent } from './account-settings/change-password/change-password.component';
|
import { ChangePasswordComponent } from './account-settings/change-password/change-password.component';
|
||||||
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
||||||
|
import { PostComponent } from './posts/post.component';
|
||||||
|
|
||||||
export const appRoutes: Routes = [
|
export const appRoutes: Routes = [
|
||||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||||
@@ -19,5 +20,6 @@ export const appRoutes: Routes = [
|
|||||||
{ path: 'accountSettings', component: AccountSettingsComponent, canActivate: [AuthGuard] },
|
{ path: 'accountSettings', component: AccountSettingsComponent, canActivate: [AuthGuard] },
|
||||||
{ path: 'changePassword', component: ChangePasswordComponent, canActivate: [AuthGuard] },
|
{ path: 'changePassword', component: ChangePasswordComponent, canActivate: [AuthGuard] },
|
||||||
{ path: 'profilEdit', component: ProfilEditionComponent, canActivate: [AuthGuard] },
|
{ path: 'profilEdit', component: ProfilEditionComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'posts/:postKey', component: PostComponent },
|
||||||
{ path: '**', redirectTo: '/home' }
|
{ 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