From 460cc234506da86f89d3707b8864b1aee5c4728f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20PAILHAREY?= <rpailharey@grandlyon.com> Date: Mon, 27 Nov 2023 10:12:40 +0000 Subject: [PATCH] feat(ui): updated toaster --- .../manage-employers.component.ts | 6 +- .../manage-jobs/manage-jobs.component.ts | 7 +-- .../manage-users/manage-users.component.ts | 10 ++-- src/app/app.module.ts | 2 +- src/app/contact/contact.component.ts | 2 +- .../newsletter-subscription.component.ts | 4 +- .../profile-newsletter.component.ts | 8 ++- .../structure-members-management.component.ts | 6 +- .../reset-password.component.ts | 3 +- src/app/services/notification.service.ts | 44 +++++++++----- .../structure-exclude.component.ts | 3 +- src/assets/ico/toast-error.svg | 9 +-- src/assets/ico/toast-info.svg | 8 ++- src/assets/ico/toast-success.svg | 8 ++- src/assets/ico/toast-warning.svg | 5 ++ src/styles.scss | 60 +++++++++---------- 16 files changed, 104 insertions(+), 81 deletions(-) create mode 100644 src/assets/ico/toast-warning.svg diff --git a/src/app/admin/components/manage-employers/manage-employers.component.ts b/src/app/admin/components/manage-employers/manage-employers.component.ts index 81f5f3e73..f125b6eb8 100644 --- a/src/app/admin/components/manage-employers/manage-employers.component.ts +++ b/src/app/admin/components/manage-employers/manage-employers.component.ts @@ -164,7 +164,7 @@ export class ManageEmployersComponent implements OnInit { this.adminService.deleteEmployer(employer._id).subscribe( (data) => { this.validatedEmployers = this.validatedEmployers.filter((obj) => obj._id !== data._id); - this.notificationService.showSuccess("L'employeur a bien été supprimée.", ''); + this.notificationService.showSuccess("L'employeur a bien été supprimée."); }, (err) => { this.notificationService.showError(`${err.error.message}`, 'Une erreur est survenue'); @@ -175,7 +175,7 @@ export class ManageEmployersComponent implements OnInit { public onChange(arg): void { this.adminService.editEmployer(arg.data._id, arg.data.name).subscribe(() => { - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); this.findValidatedEmployers(); this.findUnvalidatedEmployers(); }); @@ -200,7 +200,7 @@ export class ManageEmployersComponent implements OnInit { context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] }); this.findValidatedEmployers(); this.findUnvalidatedEmployers(); - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); }); } else { if (context.oldValue) { diff --git a/src/app/admin/components/manage-jobs/manage-jobs.component.ts b/src/app/admin/components/manage-jobs/manage-jobs.component.ts index 686866528..8734a32a9 100644 --- a/src/app/admin/components/manage-jobs/manage-jobs.component.ts +++ b/src/app/admin/components/manage-jobs/manage-jobs.component.ts @@ -266,7 +266,7 @@ export class ManageJobsComponent implements OnInit { return; } else { this.adminService.updateJob(arg.data._id, arg.data).subscribe(() => { - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); this.findValidatedJobs(); this.findUnvalidatedJobs(); }); @@ -296,7 +296,7 @@ export class ManageJobsComponent implements OnInit { context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] }); this.findValidatedJobs(); this.findUnvalidatedJobs(); - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); }); } else { if (context.oldValue) { @@ -381,8 +381,7 @@ export class ManageJobsComponent implements OnInit { } else { this.adminService.editJobsGroup(arg.data._id, arg.data.name).subscribe(() => { this.notificationService.showSuccess( - 'Le groupe de fonction ' + arg.oldValue + ' à bien été remplacé par ' + arg.data.name + '.', - '' + `Le groupe de fonction ${arg.oldValue} à bien été remplacé par ${arg.data.name}.` ); this.getJobsGroupsWithJobs(); this.initColumnDef(); diff --git a/src/app/admin/components/manage-users/manage-users.component.ts b/src/app/admin/components/manage-users/manage-users.component.ts index 2edddabf1..40324aa89 100644 --- a/src/app/admin/components/manage-users/manage-users.component.ts +++ b/src/app/admin/components/manage-users/manage-users.component.ts @@ -233,7 +233,7 @@ export class ManageUsersComponent { this.adminService.setUserEmployer(selectedEmployer._id, arg.data.id).subscribe(() => { arg.node.data[arg.colDef.field] = selectedEmployer; arg.api.refreshCells({ rowNodes: [arg.node], columns: [arg.column.colId] }); - this.notificationService.showSuccess("L'employeur a bien été attribué.", ''); + this.notificationService.showSuccess("L'employeur a bien été attribué."); }); return; } @@ -264,13 +264,13 @@ export class ManageUsersComponent { this.adminService.setUserJob(newJob._id, context.node.data._id).subscribe((data) => { context.node.data[context.colDef.field] = data.job; context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] }); - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); }); } else { this.adminService.removeUserJob(context.node.data._id).subscribe((data) => { context.node.data[context.colDef.field] = data.job; context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] }); - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); }); } } else { @@ -288,13 +288,13 @@ export class ManageUsersComponent { this.adminService.setUserEmployer(newEmployer._id, context.node.data._id).subscribe((data) => { context.node.data[context.colDef.field] = data.employer; context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] }); - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); }); } else { this.adminService.removeUserEmployer(context.node.data._id).subscribe((data) => { context.node.data[context.colDef.field] = data.employer; context.api.refreshCells({ rowNodes: [context.node], columns: [context.column.colId] }); - this.notificationService.showSuccess("L'opération a réussie.", ''); + this.notificationService.showSuccess("L'opération a réussie."); }); } } else { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b0caadecb..b10f3f5f5 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,4 +1,4 @@ -import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; +import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http'; import { LOCALE_ID, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; diff --git a/src/app/contact/contact.component.ts b/src/app/contact/contact.component.ts index b8df1e7a2..7ef4f790a 100644 --- a/src/app/contact/contact.component.ts +++ b/src/app/contact/contact.component.ts @@ -69,7 +69,7 @@ export class ContactComponent implements OnInit { this.contactService.sendMessage(contactMessage).subscribe( () => { this.loading = false; - this.notificationService.showSuccess('Votre message a bien été envoyé', 'Demande de contact'); + this.notificationService.showSuccess('Demande de contact', 'Votre message a bien été envoyé'); this.router.navigate(['']); }, () => { diff --git a/src/app/newsletter-subscription/newsletter-subscription.component.ts b/src/app/newsletter-subscription/newsletter-subscription.component.ts index cc5a90ff1..33635f7b9 100644 --- a/src/app/newsletter-subscription/newsletter-subscription.component.ts +++ b/src/app/newsletter-subscription/newsletter-subscription.component.ts @@ -64,7 +64,7 @@ export class NewsletterSubscriptionComponent implements OnInit { ); } else { this.notificationService.showErrorPleaseRetry( - `L'email ${this.f.email.value} n'a pu être ajouté à la newsletter` + `L'email ${this.f.email.value} n'a pas pu être ajouté à la newsletter` ); } }); @@ -84,7 +84,7 @@ export class NewsletterSubscriptionComponent implements OnInit { ); } else { this.notificationService.showErrorPleaseRetry( - `L'email ${this.f.email.value} n'a pu être retiré de la newsletter` + `L'email ${this.f.email.value} n'a pas pu être retiré de la newsletter` ); } }); diff --git a/src/app/profile/profile-newsletter/profile-newsletter.component.ts b/src/app/profile/profile-newsletter/profile-newsletter.component.ts index 4594eddb6..688a91a09 100644 --- a/src/app/profile/profile-newsletter/profile-newsletter.component.ts +++ b/src/app/profile/profile-newsletter/profile-newsletter.component.ts @@ -39,7 +39,9 @@ export class ProfileNewsletterComponent implements OnInit { `L'email ${this.userEmail} semble factice ou invalide` ); } else { - this.notificationService.showErrorPleaseRetry(`L'email ${this.userEmail} n'a pu être ajouté à la newsletter`); + this.notificationService.showErrorPleaseRetry( + `L'email ${this.userEmail} n'a pas pu être ajouté à la newsletter` + ); } this.isLoading = false; }, @@ -50,7 +52,7 @@ export class ProfileNewsletterComponent implements OnInit { this.isLoading = true; this.newsletterService.unsubscribe(this.userEmail).subscribe({ next: (result) => { - this.notificationService.showSuccess(`L'email ${result.email} a bien été retiré à la newsletter`); + this.notificationService.showSuccess(`L'email ${result.email} a bien été retiré de la newsletter`); this.isSubscribed = false; this.isLoading = false; }, @@ -62,7 +64,7 @@ export class ProfileNewsletterComponent implements OnInit { ); } else { this.notificationService.showErrorPleaseRetry( - `L'email ${this.userEmail} n'a pu être retiré de la newsletter` + `L'email ${this.userEmail} n'a pas pu être retiré de la newsletter` ); } this.isLoading = false; diff --git a/src/app/profile/structure-members-management/structure-members-management.component.ts b/src/app/profile/structure-members-management/structure-members-management.component.ts index 9237c71ff..3a0a818f1 100644 --- a/src/app/profile/structure-members-management/structure-members-management.component.ts +++ b/src/app/profile/structure-members-management/structure-members-management.component.ts @@ -71,8 +71,7 @@ export class StructureMembersManagementComponent implements OnInit { () => { this.structureWithOwners.owners = this.structureWithOwners.owners.filter((obj) => obj._id !== member._id); this.notificationService.showSuccess( - `${this.displayMemberName(member)} a bien été exclu de ${this.structure.structureName}`, - '' + `${this.displayMemberName(member)} a bien été exclu de ${this.structure.structureName}` ); }, () => { @@ -91,8 +90,7 @@ export class StructureMembersManagementComponent implements OnInit { () => { this.tempUsers = this.tempUsers.filter((obj) => obj._id !== member._id); this.notificationService.showSuccess( - `La demande d'ajout de ${member.email} à ${this.structure.structureName} a bien été annulée`, - '' + `La demande d'ajout de ${member.email} à ${this.structure.structureName} a bien été annulée` ); }, () => { diff --git a/src/app/reset-password/reset-password.component.ts b/src/app/reset-password/reset-password.component.ts index 82a8f0404..09b36b2fc 100644 --- a/src/app/reset-password/reset-password.component.ts +++ b/src/app/reset-password/reset-password.component.ts @@ -54,8 +54,7 @@ export class ResetPasswordComponent implements OnInit { this.authService.resetPassword(this.f.email.value).subscribe({ next: () => { this.notificationService.showSuccess( - 'Un mail de confirmation de modification de votre mot de passe vous a été envoyé.', - '' + 'Un mail de confirmation de modification de votre mot de passe vous a été envoyé.' ); this.router.navigate(['/login']); }, diff --git a/src/app/services/notification.service.ts b/src/app/services/notification.service.ts index e022e272a..e2e3b34e1 100644 --- a/src/app/services/notification.service.ts +++ b/src/app/services/notification.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { ToastrService } from 'ngx-toastr'; +import { ActiveToast, ToastrService } from 'ngx-toastr'; @Injectable({ providedIn: 'root', @@ -7,34 +7,50 @@ import { ToastrService } from 'ngx-toastr'; export class NotificationService { constructor(private toastr: ToastrService) {} - public showSuccess(message: string, title = '', timeOut = 10000): void { - this.toastr.success(message, title, { + public showWarning(title: string, message = '', timeOut = 10000): ActiveToast<unknown> { + return this.toastr.warning(message, title, { timeOut: timeOut, + disableTimeOut: timeOut === 0, }); } - // Par défaut, l'erreur reste affichée jusqu'à ce qu'on clique dessus - public showError(message: string, title = '', timeOut = 0): void { - this.toastr.error(message, title, { + public showSuccess(title: string, message = '', timeOut = 10000): ActiveToast<unknown> { + return this.toastr.success(message, title, { + timeOut: timeOut, + disableTimeOut: timeOut === 0, + }); + } + + /** + * By default, the error is displayed until clicked on. + */ + public showError(title: string, message = '', timeOut = 0): ActiveToast<unknown> { + return this.toastr.error(message, title, { + timeOut: timeOut, + disableTimeOut: timeOut === 0, + }); + } + + public showInfo(title: string, message = '', timeOut = 10000): ActiveToast<unknown> { + return this.toastr.info(message, title, { timeOut: timeOut, - disableTimeOut: timeOut ? false : true, + disableTimeOut: timeOut === 0, }); } + public showErrorPleaseRetry(title: string, timeOut = 0): void { - this.showError('Merci de réessayer plus tard ou de contacter un administrateur', title, timeOut); + this.showError(title, 'Merci de réessayer plus tard ou de contacter un administrateur', timeOut); } // Par défaut, l'erreur reste affichée jusqu'à ce qu'on clique dessus public showAppNewVersion(): void { - const update = this.toastr.info( - 'Une nouvelle version est disponible, cliquer ici pour mettre à jour.', + const update = this.showInfo( 'Nouvelle version', - { - disableTimeOut: true, - } + 'Une nouvelle version est disponible, cliquer ici pour mettre à jour.', + 0 ); - update.onTap.subscribe((_action) => { + update.onTap.subscribe(() => { window.location.reload(); }); } diff --git a/src/app/structure/structure-exclude/structure-exclude.component.ts b/src/app/structure/structure-exclude/structure-exclude.component.ts index a9dbc04b4..a1d18fd28 100644 --- a/src/app/structure/structure-exclude/structure-exclude.component.ts +++ b/src/app/structure/structure-exclude/structure-exclude.component.ts @@ -57,8 +57,7 @@ export class StructureExcludeComponent implements OnInit { this.structureService.removeOwnerFromStructure(params.get('userId'), params.get('id')).subscribe( () => { this.notificationService.showSuccess( - `${this.newMemberName} a bien été exclu de ${this.structure.structureName}`, - '' + `${this.newMemberName} a bien été exclu de ${this.structure.structureName}` ); this.router.navigateByUrl(`/acteurs?id=${this.structureId}`); }, diff --git a/src/assets/ico/toast-error.svg b/src/assets/ico/toast-error.svg index ee0c5fef9..25407c39d 100644 --- a/src/assets/ico/toast-error.svg +++ b/src/assets/ico/toast-error.svg @@ -1,4 +1,5 @@ -<svg width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M26.8169 11.4821C27.3593 10.9397 28.2738 10.9749 28.8596 11.5607C29.4454 12.1464 29.4806 13.061 28.9382 13.6034L13.2247 29.3169C12.6823 29.8593 11.7677 29.8241 11.1819 29.2383C10.5962 28.6525 10.561 27.738 11.1034 27.1956L26.8169 11.4821Z" fill="#FF0000"/> -<path d="M28.8169 27.5179C29.3593 28.0603 29.3241 28.9749 28.7383 29.5607C28.1525 30.1464 27.2379 30.1816 26.6955 29.6392L10.9821 13.9257C10.4397 13.3833 10.4748 12.4688 11.0606 11.883C11.6464 11.2972 12.561 11.262 13.1034 11.8044L28.8169 27.5179Z" fill="#FF0000"/> -</svg> +<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path + d="M20 3.33334C10.8 3.33334 3.33331 10.8 3.33331 20C3.33331 29.2 10.8 36.6667 20 36.6667C29.2 36.6667 36.6666 29.2 36.6666 20C36.6666 10.8 29.2 3.33334 20 3.33334ZM20 21.6667C19.0833 21.6667 18.3333 20.9167 18.3333 20V13.3333C18.3333 12.4167 19.0833 11.6667 20 11.6667C20.9166 11.6667 21.6666 12.4167 21.6666 13.3333V20C21.6666 20.9167 20.9166 21.6667 20 21.6667ZM21.6666 28.3333H18.3333V25H21.6666V28.3333Z" + fill="#DA3635" /> +</svg> \ No newline at end of file diff --git a/src/assets/ico/toast-info.svg b/src/assets/ico/toast-info.svg index 96420e351..a23dc9275 100644 --- a/src/assets/ico/toast-info.svg +++ b/src/assets/ico/toast-info.svg @@ -1,3 +1,5 @@ -<svg width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path fill-rule="evenodd" clip-rule="evenodd" d="M34 20.5C34 28.232 27.732 34.5 20 34.5C12.268 34.5 6 28.232 6 20.5C6 12.768 12.268 6.5 20 6.5C27.732 6.5 34 12.768 34 20.5ZM20.0001 18.9999C20.8285 18.9999 21.5001 19.6715 21.5001 20.4999V27.4999C21.5001 28.3284 20.8285 28.9999 20.0001 29C19.1717 29 18.5001 28.3284 18.5001 27.5V20.4999C18.5001 19.6715 19.1717 18.9999 20.0001 18.9999ZM20 16.362C21.0665 16.362 21.931 15.4975 21.931 14.431C21.931 13.3645 21.0665 12.4999 20 12.4999C18.9335 12.4999 18.069 13.3645 18.069 14.431C18.069 15.4975 18.9335 16.362 20 16.362Z" fill="#2F96B4"/> -</svg> +<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path + d="M20 3.33333C10.8 3.33333 3.33331 10.8 3.33331 20C3.33331 29.2 10.8 36.6667 20 36.6667C29.2 36.6667 36.6666 29.2 36.6666 20C36.6666 10.8 29.2 3.33333 20 3.33333ZM20 28.3333C19.0833 28.3333 18.3333 27.5833 18.3333 26.6667V20C18.3333 19.0833 19.0833 18.3333 20 18.3333C20.9166 18.3333 21.6666 19.0833 21.6666 20V26.6667C21.6666 27.5833 20.9166 28.3333 20 28.3333ZM21.6666 15H18.3333V11.6667H21.6666V15Z" + fill="#0073E9" /> +</svg> \ No newline at end of file diff --git a/src/assets/ico/toast-success.svg b/src/assets/ico/toast-success.svg index 0e3288b11..aa6b3da96 100644 --- a/src/assets/ico/toast-success.svg +++ b/src/assets/ico/toast-success.svg @@ -1,3 +1,5 @@ -<svg width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M10 21.1364L17.3889 27.5L23.1944 20.5L29 13.5" stroke="#47C562" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> -</svg> +<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path + d="M20 3.33334C10.8 3.33334 3.33331 10.8 3.33331 20C3.33331 29.2 10.8 36.6667 20 36.6667C29.2 36.6667 36.6666 29.2 36.6666 20C36.6666 10.8 29.2 3.33334 20 3.33334ZM15.4833 27.15L9.49998 21.1667C8.84998 20.5167 8.84998 19.4667 9.49998 18.8167C10.15 18.1667 11.2 18.1667 11.85 18.8167L16.6666 23.6167L28.1333 12.15C28.7833 11.5 29.8333 11.5 30.4833 12.15C31.1333 12.8 31.1333 13.85 30.4833 14.5L17.8333 27.15C17.2 27.8 16.1333 27.8 15.4833 27.15Z" + fill="#1D8844" /> +</svg> \ No newline at end of file diff --git a/src/assets/ico/toast-warning.svg b/src/assets/ico/toast-warning.svg new file mode 100644 index 000000000..ff3bd7a39 --- /dev/null +++ b/src/assets/ico/toast-warning.svg @@ -0,0 +1,5 @@ +<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path + d="M7.45 35H32.55C35.1167 35 36.7167 32.2167 35.4333 30L22.8833 8.31667C21.6 6.10001 18.4 6.10001 17.1167 8.31667L4.56667 30C3.28333 32.2167 4.88333 35 7.45 35ZM20 23.3333C19.0833 23.3333 18.3333 22.5833 18.3333 21.6667V18.3333C18.3333 17.4167 19.0833 16.6667 20 16.6667C20.9167 16.6667 21.6667 17.4167 21.6667 18.3333V21.6667C21.6667 22.5833 20.9167 23.3333 20 23.3333ZM21.6667 30H18.3333V26.6667H21.6667V30Z" + fill="#CF4B00" /> +</svg> \ No newline at end of file diff --git a/src/styles.scss b/src/styles.scss index 3b00fe0c9..63872028e 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -89,41 +89,41 @@ a { } //Toastr .ngx-toastr { + background: white; + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.35) !important; + border-radius: 0.5rem !important; + padding: 0.5rem 0.75rem 0.5rem 3.5rem !important; + background-size: 2.5rem !important; + background-position: 0.5rem, center !important; + min-height: 6.25rem; + display: flex; + flex-direction: column; + justify-content: center; + transition: all 300ms ease; + + &:hover { + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.7) !important; + } + + &.toast-warning { + border: solid 1px $info-warning; + color: $info-warning; + background-image: url('/assets/ico/toast-warning.svg'); + } &.toast-success { - background: white; - box-shadow: $box-shadow-simple; - color: $grey-1; - border: solid 3px $green-1; - &::after { - content: url('/assets/ico/toast-success.svg') !important; - position: absolute !important; - top: 5px !important; - left: 5px !important; - } + border: solid 1px $info-success; + color: $info-success; + background-image: url('/assets/ico/toast-success.svg'); } &.toast-error { - background: white; - box-shadow: $box-shadow-simple; - color: $grey-1; - border: solid 3px $red-error; - &::after { - content: url('assets/ico/toast-error.svg') !important; - position: absolute !important; - top: 5px !important; - left: 5px !important; - } + border: solid 1px $info-error; + color: $info-error; + background-image: url('assets/ico/toast-error.svg'); } &.toast-info { - background: white; - box-shadow: $box-shadow-simple; - color: $grey-1; - border: solid 3px $blue; - &::after { - content: url('assets/ico/toast-info.svg') !important; - position: absolute !important; - top: 30px !important; - left: 5px !important; - } + border: solid 1px $info-blue; + color: $info-blue; + background-image: url('assets/ico/toast-info.svg'); } } -- GitLab