Annuler
diff --git a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts
index 608a637..15c521b 100644
--- a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts
+++ b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts
@@ -3,6 +3,7 @@ import { ProfilEditionService } from './profil-edition.service';
import { HttpEventType, HttpResponse } from '@angular/common/http';
import { User } from '../../core/entities';
import { AuthService } from '../../core/services/auth.service';
+import { NotificationsComponent } from 'src/app/core/notifications/notifications.component';
@Component({
selector: 'app-profil-edition',
@@ -33,8 +34,6 @@ export class ProfilEditionComponent implements OnInit {
selectedFiles: FileList;
currentFileUpload: File;
progress: { percentage: number } = { percentage: 0 };
- modelError: string;
- result: string;
constructor(
private profilEditionService: ProfilEditionService,
@@ -69,32 +68,21 @@ export class ProfilEditionComponent implements OnInit {
console.log('File ' + result.body + ' completely uploaded!');
this.model.image = result.body as string;
this.authService.setAuthenticated(this.model);
- this.setMessage('Image de profil modifiée.', false);
+ NotificationsComponent.success('Image de profil modifiée.');
}
this.selectedFiles = undefined;
+ }, error => {
+ console.log(error);
+ NotificationsComponent.error('Une erreur est survenue lors de l\'upload de votre image de profil.');
});
}
}
onSubmit(): void {
this.profilEditionService.updateUser(this.model).subscribe(() => {
- this.setMessage('Modification enregistrée.', false);
+ NotificationsComponent.success('Modification enregistrée.');
}, error => {
- this.setMessage('L\'adresse mail saisie n\'est pas disponible.', true);
+ NotificationsComponent.error('L\'adresse mail saisie n\'est pas disponible.');
});
}
-
- setMessage(message: string, error: boolean): void {
- this[error ? 'modelError' : 'result'] = message;
-
- const resultMsgDiv = document.getElementById(error ? 'errorMsg' : 'resultMsg');
- resultMsgDiv.style.maxHeight = '64px';
-
- setTimeout(() => {
- resultMsgDiv.style.maxHeight = '0px';
- setTimeout(() => {
- this[error ? 'modelError' : 'result'] = undefined;
- }, 550);
- }, 3000);
- }
}
diff --git a/src/main/ts/src/app/app.component.html b/src/main/ts/src/app/app.component.html
index c22508b..eb875a3 100755
--- a/src/main/ts/src/app/app.component.html
+++ b/src/main/ts/src/app/app.component.html
@@ -1,4 +1,5 @@
+
diff --git a/src/main/ts/src/app/app.module.ts b/src/main/ts/src/app/app.module.ts
index 8fe9db7..5a7cdbe 100755
--- a/src/main/ts/src/app/app.module.ts
+++ b/src/main/ts/src/app/app.module.ts
@@ -1,7 +1,6 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
-import { HttpModule } from '@angular/http';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RouterModule } from '@angular/router';
@@ -37,6 +36,8 @@ import { SearchComponent } from './search/search.component';
import { SigninComponent } from './signin/signin.component';
import { VersionRevisionComponent } from './version-revisions/version-revisions.component';
import { HealthCheckComponent } from './health-check/health-check.component';
+import { NotificationElement } from './core/notifications/notification-element/notification-element.component';
+import { NotificationsComponent } from './core/notifications/notifications.component';
// Reusable components
import { PostCardComponent } from './core/post-card/post-card.component';
@@ -63,6 +64,8 @@ import { HealthCheckService } from './health-check/health-check.service';
@NgModule({
declarations: [
AppComponent,
+ NotificationsComponent,
+ NotificationElement,
HeaderComponent,
FooterComponent,
LoginComponent,
@@ -84,12 +87,11 @@ import { HealthCheckService } from './health-check/health-check.service';
SearchBarComponent,
ProgressBarComponent,
ForbiddenComponent,
- HealthCheckComponent
+ HealthCheckComponent,
],
imports: [
BrowserModule,
FormsModule,
- HttpModule,
HttpClientModule,
MDBBootstrapModule.forRoot(),
RouterModule.forRoot(
diff --git a/src/main/ts/src/app/core/interceptors/unauthorized.interceptor.ts b/src/main/ts/src/app/core/interceptors/unauthorized.interceptor.ts
index f795113..764a89d 100644
--- a/src/main/ts/src/app/core/interceptors/unauthorized.interceptor.ts
+++ b/src/main/ts/src/app/core/interceptors/unauthorized.interceptor.ts
@@ -19,7 +19,7 @@ export class UnauthorizedInterceptor implements HttpInterceptor {
this.router.navigate(['/login']);
}
- const error = err.error.message || err.statusText;
+ const error = (err.error && err.error.message) || err.statusText;
return throwError(error);
}));
}
diff --git a/src/main/ts/src/app/core/notifications/notification-class.ts b/src/main/ts/src/app/core/notifications/notification-class.ts
new file mode 100644
index 0000000..b9a56df
--- /dev/null
+++ b/src/main/ts/src/app/core/notifications/notification-class.ts
@@ -0,0 +1,26 @@
+/**
+ * Class which represents a notification class.
+ * It serves to set the notification appearence.
+ */
+export class NotificationClass {
+ /**
+ * Default constructor.
+ * @param {string} icon Class name of font-awsome icon.
+ * @param {string} clazz The class to set notification style.
+ */
+ constructor(
+ public icon: string,
+ public clazz: string,
+ ) {}
+}
+
+/**
+ * Constant instances of NotificationClass.
+ */
+export const NotificationClasses = Object.freeze({
+ 'Error': new NotificationClass('exclamation-circle ', 'alert-danger'),
+ 'Warn': new NotificationClass('exclamation-triangle', 'alert-warning'),
+ 'Info': new NotificationClass('info-circle', 'alert-info'),
+ 'Success': new NotificationClass('check-circle', 'alert-success')
+});
+
diff --git a/src/main/ts/src/app/core/notifications/notification-element/notification-element.component.html b/src/main/ts/src/app/core/notifications/notification-element/notification-element.component.html
new file mode 100644
index 0000000..ff63a21
--- /dev/null
+++ b/src/main/ts/src/app/core/notifications/notification-element/notification-element.component.html
@@ -0,0 +1,7 @@
+
+ {{model.content}}
+
+
+
+
diff --git a/src/main/ts/src/app/core/notifications/notification-element/notification-element.component.ts b/src/main/ts/src/app/core/notifications/notification-element/notification-element.component.ts
new file mode 100644
index 0000000..371e219
--- /dev/null
+++ b/src/main/ts/src/app/core/notifications/notification-element/notification-element.component.ts
@@ -0,0 +1,78 @@
+import { NotificationClass } from './../notification-class';
+import { Component, Input, OnInit, ViewChild, ElementRef } from '@angular/core';
+
+/**
+ * Class which represents a notification in the notifications list.
+ */
+@Component({
+ selector: 'app-notification-element',
+ templateUrl: 'notification-element.component.html',
+ styles: [`
+ #notification {
+ transition: all 0.7s ease-out;
+ position: relative;
+ }
+ .close {
+ position: absolute;
+ right: 7px;
+ top: 12px;
+ font-size: 19px;
+ opacity: 0;
+ }
+ #notification:hover .close {
+ opacity: 0.5;
+ }
+ `]
+})
+export class NotificationElement implements OnInit {
+ /**
+ * The notification model.
+ */
+ @Input() model: NotificationModel;
+ /**
+ * The notification DOM element.
+ */
+ @ViewChild('notification') notification: ElementRef;
+
+ /**
+ * Sets the DOM element in the model object and plays with opacity.
+ */
+ ngOnInit(): void {
+ this.model.notification = this.notification;
+
+ this.notification.nativeElement.style.opacity = 0;
+ setTimeout(() => {
+ this.notification.nativeElement.style.opacity = 1;
+ }, 100);
+ }
+}
+
+/**
+ * Class which represents the notification model.
+ */
+export class NotificationModel {
+ /**
+ * Element which represents the DOM element of the notification element.
+ */
+ notification: ElementRef;
+
+ /**
+ * Default constructor.
+ * @param {string} content The message of the notification.
+ * @param {NotificationClass} notificationClass The category of the notification (info, error...).
+ */
+ constructor(
+ public content: string,
+ public notificationClass: NotificationClass
+ ) {}
+
+ /**
+ * Hides the notification DOM element.
+ */
+ public hide(): void {
+ this.notification.nativeElement.style.opacity = 0;
+ setTimeout(() => {
+ this.notification.nativeElement.style.display = 'none';
+ }, 800);
+ }
+}
diff --git a/src/main/ts/src/app/core/notifications/notifications.component.html b/src/main/ts/src/app/core/notifications/notifications.component.html
new file mode 100644
index 0000000..9765310
--- /dev/null
+++ b/src/main/ts/src/app/core/notifications/notifications.component.html
@@ -0,0 +1,5 @@
+
+
diff --git a/src/main/ts/src/app/core/notifications/notifications.component.ts b/src/main/ts/src/app/core/notifications/notifications.component.ts
new file mode 100644
index 0000000..64e2f10
--- /dev/null
+++ b/src/main/ts/src/app/core/notifications/notifications.component.ts
@@ -0,0 +1,108 @@
+import { NotificationClass, NotificationClasses } from './notification-class';
+import { NotificationModel } from './notification-element/notification-element.component';
+import { Component, OnInit } from '@angular/core';
+
+/**
+ * Class which offers the notifications service.
+ */
+@Component({
+ selector: 'app-notifications',
+ templateUrl: 'notifications.component.html',
+ styles: [`
+ #notification-container {
+ position: fixed;
+ top: 50px;
+ right: 20px;
+ width: 300px;
+ z-index: 1100;
+ }
+ `]
+})
+export class NotificationsComponent implements OnInit {
+ /**
+ * Singleton of the notification service.
+ */
+ private static component: NotificationsComponent;
+
+ /**
+ * List of notifications model.
+ */
+ notificationList: Array = [];
+
+ /**
+ * Creates an error notification.
+ * @param {string} message The content of the notification.
+ */
+ public static error(message: string): void {
+ NotificationsComponent.notif(message, NotificationClasses.Error);
+ }
+
+ /**
+ * Creates a warning notification.
+ * @param {string} message The content of the notification.
+ */
+ public static warn(message: string): void {
+ NotificationsComponent.notif(message, NotificationClasses.Warn);
+ }
+
+ /**
+ * Creates an info notification.
+ * @param {string} message The content of the notification.
+ */
+ public static info(message: string): void {
+ NotificationsComponent.notif(message, NotificationClasses.Info);
+ }
+
+ /**
+ * Creates a success notification.
+ * @param {string} message The content of the notification.
+ */
+ public static success(message: string): void {
+ NotificationsComponent.notif(message, NotificationClasses.Success);
+ }
+
+ /**
+ * Create a notification. The {@code notifClass} param defines the category of
+ * the notification (info, error...).
+ * @param {string} message The content of the notification.
+ * @param {NotificationClass} notifClass The category of the notification.
+ */
+ private static notif(message: string, notifClass: NotificationClass): void {
+ const elem = new NotificationModel(message, notifClass);
+
+ NotificationsComponent.component.notificationList.push(elem);
+
+ setTimeout(() => {
+ elem.hide();
+
+ setTimeout(() => {
+ NotificationsComponent.clearNotificationList();
+ }, 900);
+ }, 4500);
+ }
+
+ /**
+ * Clears the consumed notifications in the list.
+ * When a notification is created, a cooldown is set to hide it after a certain time period.
+ * In this cooldown, the notification have only its display as {@code none}, but the
+ * notification isn't remove from the list. This method removes it.
+ */
+ private static clearNotificationList(): void {
+ NotificationsComponent.component.notificationList.forEach(elem => {
+ if (elem.notification.nativeElement.style.display === 'none') {
+ const index = NotificationsComponent.component.notificationList.indexOf(elem);
+ if (index > -1) {
+ NotificationsComponent.component.notificationList.splice(index, 1);
+ }
+ }
+ });
+ }
+
+ /**
+ * Set the reference of the singleton here because this component
+ * is created at the application startup.
+ */
+ ngOnInit(): void {
+ NotificationsComponent.component = this;
+ }
+}
diff --git a/src/main/ts/src/app/disconnection/disconnection.component.ts b/src/main/ts/src/app/disconnection/disconnection.component.ts
index af616f1..0088183 100755
--- a/src/main/ts/src/app/disconnection/disconnection.component.ts
+++ b/src/main/ts/src/app/disconnection/disconnection.component.ts
@@ -1,6 +1,6 @@
+import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
-import { Http } from '@angular/http';
import { AuthService } from '../core/services/auth.service';
@@ -13,7 +13,7 @@ export class DisconnectionComponent implements OnInit {
constructor(
private authService: AuthService,
private router: Router,
- private http: Http
+ private http: HttpClient
) {}
ngOnInit(): void {
diff --git a/src/main/ts/src/app/login/login.component.html b/src/main/ts/src/app/login/login.component.html
index 25c8fd4..7ff0d86 100755
--- a/src/main/ts/src/app/login/login.component.html
+++ b/src/main/ts/src/app/login/login.component.html
@@ -30,11 +30,6 @@
required />