diff --git a/src/app/components/loading/loading.component.css b/src/app/components/loading/loading.component.css new file mode 100644 index 0000000..22d260e --- /dev/null +++ b/src/app/components/loading/loading.component.css @@ -0,0 +1,24 @@ +div { + margin-top: 10em; + display: flex; + justify-content: center; + align-items: center; +} + +img { + animation-name: spin; + animation-duration: 2000ms; + animation-iteration-count: infinite; + animation-timing-function: linear; + max-width: 40%; + max-height: 40%; +} + +@keyframes spin { + from { + transform:rotate(0deg); + } + to { + transform:rotate(360deg); + } +} diff --git a/src/app/components/loading/loading.component.html b/src/app/components/loading/loading.component.html new file mode 100644 index 0000000..29e6720 --- /dev/null +++ b/src/app/components/loading/loading.component.html @@ -0,0 +1,3 @@ +
+ loadign +
diff --git a/src/app/components/loading/loading.component.ts b/src/app/components/loading/loading.component.ts new file mode 100644 index 0000000..0e1870f --- /dev/null +++ b/src/app/components/loading/loading.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import {NgOptimizedImage} from '@angular/common'; + +@Component({ + selector: 'app-loading', + standalone: true, + imports: [ + NgOptimizedImage + ], + templateUrl: './loading.component.html', + styleUrl: './loading.component.css' +}) +export class LoadingComponent { + +} diff --git a/src/app/components/modal/preview-modal/preview-modal.component.css b/src/app/components/modal/preview-modal/preview-modal.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/modal/preview-modal/preview-modal.component.html b/src/app/components/modal/preview-modal/preview-modal.component.html new file mode 100644 index 0000000..5554195 --- /dev/null +++ b/src/app/components/modal/preview-modal/preview-modal.component.html @@ -0,0 +1,15 @@ +@if (post) { + + + +} diff --git a/src/app/components/modal/preview-modal/preview-modal.component.ts b/src/app/components/modal/preview-modal/preview-modal.component.ts new file mode 100644 index 0000000..c446233 --- /dev/null +++ b/src/app/components/modal/preview-modal/preview-modal.component.ts @@ -0,0 +1,21 @@ +import {Component, Input} from '@angular/core'; +import {Dialog} from 'primeng/dialog'; +import {PostHomeComponent} from '../../post-home/post-home.component'; +import {Post} from '../../../models/post'; + +@Component({ + selector: 'app-preview-modal', + standalone: true, + imports: [ + Dialog, + PostHomeComponent + ], + templateUrl: './preview-modal.component.html', + styleUrl: './preview-modal.component.css' +}) +export class PreviewModalComponent { + opened: boolean = true; + @Input({required: true}) post: Post | undefined; + @Input() username: string = ''; + @Input() profilePicture: string = ''; +} diff --git a/src/app/components/modal/update-modal/update-modal.component.css b/src/app/components/modal/update-modal/update-modal.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/modal/update-modal/update-modal.component.html b/src/app/components/modal/update-modal/update-modal.component.html new file mode 100644 index 0000000..1f4b39a --- /dev/null +++ b/src/app/components/modal/update-modal/update-modal.component.html @@ -0,0 +1,15 @@ +@if (post) { + + + +} diff --git a/src/app/components/modal/update-modal/update-modal.component.ts b/src/app/components/modal/update-modal/update-modal.component.ts new file mode 100644 index 0000000..3e55abc --- /dev/null +++ b/src/app/components/modal/update-modal/update-modal.component.ts @@ -0,0 +1,33 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {Dialog} from 'primeng/dialog'; +import {PostFormComponent} from '../../post-form/post-form.component'; +import {Post} from '../../../models/post'; +import {AuthService} from '../../../auth.service'; +import {Author} from '../../../models/author'; + +@Component({ + selector: 'app-update-modal', + standalone: true, + imports: [ + Dialog, + PostFormComponent + ], + templateUrl: './update-modal.component.html', + styleUrl: './update-modal.component.css' +}) +export class UpdateModalComponent { + actualAuthor: Author | undefined; + opened: boolean = true; + @Input({required: true}) post: Post | undefined; + @Output() updatedPost: EventEmitter = new EventEmitter(); + + constructor(private authService: AuthService) { + this.authService.getAuthenticatedAuthor(); + } + + + onSubmit(updatedPost: Post) { + this.updatedPost.emit(updatedPost); + this.opened = false + } +} diff --git a/src/app/components/post-form/post-form.component.html b/src/app/components/post-form/post-form.component.html index 0fdaae2..a2eace2 100644 --- a/src/app/components/post-form/post-form.component.html +++ b/src/app/components/post-form/post-form.component.html @@ -1,13 +1,20 @@
- - + + + + - - + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + = new EventEmitter(); subs: Subscription[] = []; form: FormGroup; uploadedFile: File | undefined; - editorModules = { - toolbar: [ - ['bold', 'italic', 'underline', 'code'], // Styles de texte - [{header: [2, false]}], // Permet d'ajouter un `

` - [{list: 'ordered'}, {list: 'bullet'}], // Listes - ['link', 'image', 'video'], // Ajout de liens et images - ], - }; constructor( private formBuilder: FormBuilder, @@ -111,6 +109,7 @@ export class PostFormComponent implements OnDestroy { }) ).subscribe({ next: (_) => { + this.postUpdate.emit(_); this.successMessage('Succès', 'Post mis à jour avec succès') }, error: (err) => this.failureMessage('Erreur', err.error.message) @@ -140,6 +139,7 @@ export class PostFormComponent implements OnDestroy { } private transformYouTubeLinksToIframes(html: string): string { + // Magie noire return html.replace(/]*href="(https?:\/\/(?:www\.)?(youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]+)[^"]*)".*?<\/a>/g, (_, _url, _prefix, videoId) => { return ``; diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html index b009070..c955c3e 100644 --- a/src/app/pages/home/home.component.html +++ b/src/app/pages/home/home.component.html @@ -13,6 +13,6 @@ [authorProfilePicture]="post.authorProfilePicture"/> } } @else { -

Aucun post n'a été créé pour l'instant

+ }

diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts index 7fc4c66..6dd83fa 100644 --- a/src/app/pages/home/home.component.ts +++ b/src/app/pages/home/home.component.ts @@ -8,6 +8,7 @@ import {PostService} from '../../services/post.service'; import {PostHomeComponent} from '../../components/post-home/post-home.component'; import {AuthorWithPost} from '../../models/author-with-post'; import {AuthService} from '../../auth.service'; +import {LoadingComponent} from '../../components/loading/loading.component'; @Component({ selector: 'app-home', @@ -17,6 +18,7 @@ import {AuthService} from '../../auth.service'; HeaderComponent, ToastModule, PostHomeComponent, + LoadingComponent, ], templateUrl: './home.component.html', styleUrl: './home.component.css' diff --git a/src/app/pages/login/login.component.html b/src/app/pages/login/login.component.html index 5cf79e8..c8c934e 100644 --- a/src/app/pages/login/login.component.html +++ b/src/app/pages/login/login.component.html @@ -5,10 +5,7 @@ - - - + { - // sessionStorage.removeItem('token'); - sessionStorage.setItem('token', tokenObj.token); - return this.authorService.me(tokenObj.token) - })) - .subscribe({ - next: (author: Author) => { - // sessionStorage.removeItem('author'); - sessionStorage.setItem('author', JSON.stringify(author)); - sessionStorage.setItem('token-expiration-date', DateTime.now().plus({millisecond: this.configurationService.getTokenTTL()}).toISO()) - this.getAuthorCookie(); - this.router.navigate(['/']).then(() => { - this.successMessage('Connecté avec succès', 'Heureux de vous revoir ' + this.actualAuthor?.name) - }); - }, - error: (err) => this.failureMessage('Erreur de connexion', err.error.message) - }) - ); - } else { - this.failureMessage('Erreur de connexion', 'Les deux mots de passe ne correspondent pas') - } + this.subs.push + ( + this.authorService.login(this.name, this.password).pipe( + switchMap((tokenObj: any) => { + // sessionStorage.removeItem('token'); + sessionStorage.setItem('token', tokenObj.token); + return this.authorService.me(tokenObj.token) + })) + .subscribe({ + next: (author: Author) => { + // sessionStorage.removeItem('author'); + sessionStorage.setItem('author', JSON.stringify(author)); + sessionStorage.setItem('token-expiration-date', DateTime.now().plus({millisecond: this.configurationService.getTokenTTL()}).toISO()) + this.getAuthorCookie(); + this.router.navigate(['/']).then(() => { + this.successMessage('Connecté avec succès', 'Heureux de vous revoir ' + this.actualAuthor?.name) + }); + }, + error: (err) => this.failureMessage('Erreur de connexion', err.error.message) + }) + ); } getAuthorCookie(): void { diff --git a/src/app/pages/my-posts/my-posts.component.html b/src/app/pages/my-posts/my-posts.component.html index 1ac4c4d..dc8118e 100644 --- a/src/app/pages/my-posts/my-posts.component.html +++ b/src/app/pages/my-posts/my-posts.component.html @@ -23,29 +23,10 @@ {{ post.publicationDate | date: "dd/MM/yyyy à HH:mm" }} {{ post.description }} - - - - + - - - - + this.actualAuthor!.profilePicture = avatar); } this.updatePosts(); } @@ -98,6 +101,24 @@ export class MyPostsComponent implements OnDestroy { }); } + openDialogPreview(post: Post): void { + const modalInstance = this.viewContainer.createComponent(PreviewModalComponent); + modalInstance.setInput("post", post) + modalInstance.setInput("username", this.actualAuthor?.name) + modalInstance.setInput("profilePicture", this.actualAuthor?.profilePicture) + } + + openDialogUpdate(post: Post): void { + const modalInstance = this.viewContainer.createComponent(UpdateModalComponent); + modalInstance.setInput("post", post) + modalInstance.instance.updatedPost.subscribe(post => { + console.log(this.posts.map(a => a.id).indexOf(post.id)) + this.posts[this.posts.map(a => a.id).indexOf(post.id)] = post + this.posts = [... this.posts] + modalInstance.destroy(); + }); + } + openDialog(dialogBooleanTab: boolean[], index: number) { dialogBooleanTab[index] = true; } diff --git a/src/app/pages/profile/profile.component.html b/src/app/pages/profile/profile.component.html index cd066c9..d2bf924 100644 --- a/src/app/pages/profile/profile.component.html +++ b/src/app/pages/profile/profile.component.html @@ -30,5 +30,5 @@ } @else { -

Loading...

+ } diff --git a/src/app/pages/profile/profile.component.ts b/src/app/pages/profile/profile.component.ts index adf896b..937db53 100644 --- a/src/app/pages/profile/profile.component.ts +++ b/src/app/pages/profile/profile.component.ts @@ -10,6 +10,7 @@ import {Button} from 'primeng/button'; import {DialogModule} from 'primeng/dialog'; import {UpdateProfileFormComponent} from '../../components/update-profile-form/update-profile-form.component'; import {AuthService} from '../../auth.service'; +import {LoadingComponent} from '../../components/loading/loading.component'; @Component({ selector: 'app-profile', @@ -21,6 +22,7 @@ import {AuthService} from '../../auth.service'; Button, DialogModule, UpdateProfileFormComponent, + LoadingComponent, ], templateUrl: './profile.component.html', styleUrl: './profile.component.css' diff --git a/src/app/services/author.service.ts b/src/app/services/author.service.ts index a594b7f..f25fae1 100644 --- a/src/app/services/author.service.ts +++ b/src/app/services/author.service.ts @@ -91,4 +91,8 @@ export class AuthorService { } return this.httpClient.post(`${this.apiUrl}/register/admin`, {name: username, password: password, role: role}, httpOptions); } + + getAuthorAvatar(id: string) { + return this.httpClient.get(`${this.apiUrl}/${id}/avatar`); + } } diff --git a/src/assets/icon.jpg b/src/assets/icon.jpg new file mode 100644 index 0000000..7da39e5 Binary files /dev/null and b/src/assets/icon.jpg differ