diff --git a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts index 64cdaf00a6..ef90c4e06b 100644 --- a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts @@ -194,6 +194,7 @@ export class GroupListComponent extends UnsubscribeComponent implements OnInit { }, } ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; this.apollo .mutate({ mutation: FETCH_GROUPS }) .pipe(takeUntil(this.destroy$)) @@ -202,19 +203,19 @@ export class GroupListComponent extends UnsubscribeComponent implements OnInit { if (data) this.groups = data.fetchGroups || []; this.filteredGroups = this.groups; this.loadingFetch = loading; - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.groups.ready' ); - snackBarRef.instance.loading = false; + snackBarSpinner.instance.loading = false; setTimeout(() => snackBarRef.instance.dismiss(), 1000); }, error: () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.groups.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; setTimeout(() => snackBarRef.instance.dismiss(), 1000); }, diff --git a/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.html b/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.html index 7d5f1bcc45..f4e67cf689 100644 --- a/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.html +++ b/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.html @@ -1,15 +1,15 @@ -{{ data.message }} - - +{{ message }} + + diff --git a/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.ts b/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.ts index 77c6f4fab0..808fd7c98a 100644 --- a/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.ts +++ b/libs/shared/src/lib/components/snackbar-spinner/snackbar-spinner.component.ts @@ -12,7 +12,12 @@ import { BehaviorSubject } from 'rxjs'; styleUrls: ['./snackbar-spinner.component.scss'], }) export class SnackbarSpinnerComponent { - data!: SnackBarData; + /** Message displayed in snackbar */ + public message!: string; + /** Boolean indicating whether there is an error. */ + public error?: boolean; + /** Loading indicator */ + public loading = true; /** * The constructor function is a special function that is called when a new instance of the class is @@ -24,6 +29,9 @@ export class SnackbarSpinnerComponent { @Inject(SNACKBAR_DATA) public dataToken: BehaviorSubject ) { - this.data = this.dataToken.getValue(); + const data = this.dataToken.getValue(); + this.message = data.message; + this.error = data.error; + this.loading = data.loading; } } diff --git a/libs/shared/src/lib/services/download/download.service.ts b/libs/shared/src/lib/services/download/download.service.ts index b981f0b51f..b0b992d2b4 100644 --- a/libs/shared/src/lib/services/download/download.service.ts +++ b/libs/shared/src/lib/services/download/download.service.ts @@ -21,6 +21,9 @@ const BLOB_TYPE_TO_PATH: Record = { [BlobType.APPLICATION_STYLE]: 'style', }; +/** Snackbar duration in ms */ +const SNACKBAR_DURATION = 3000; + /** * Shared download service. Handles export and upload events. * TODO: rename in file service @@ -82,6 +85,7 @@ export class DownloadService { const { snackBarRef, headers } = this.triggerFileDownloadMessage( 'common.notifications.file.download.processing' ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; this.restService .get(path, { ...options, responseType: 'blob', headers }) @@ -89,19 +93,20 @@ export class DownloadService { next: (res) => { const blob = new Blob([res], { type }); this.saveFile(fileName, blob); - snackBarRef.instance.message = this.translate.instant( + console.log(snackBarRef.nestedComponent); + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.ready' ); - snackBarRef.instance.loading = false; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); }, error: () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); }, }); } @@ -123,34 +128,35 @@ export class DownloadService { const { snackBarRef, headers } = this.triggerFileDownloadMessage( 'common.notifications.file.download.processing' ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; this.restService .post(path, body, { responseType: 'blob', headers }) .subscribe({ next: (res) => { if (body?.email) { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.ongoing' ); - snackBarRef.instance.loading = false; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); } else { const blob = new Blob([res], { type }); this.saveFile(fileName, blob); - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.ready' ); - snackBarRef.instance.loading = false; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); } }, error: () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); }, }); } @@ -179,6 +185,7 @@ export class DownloadService { const { snackBarRef, headers } = this.triggerFileDownloadMessage( 'common.notifications.file.download.processing' ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; this.restService .post(path, { users }, { responseType: 'blob', headers }) @@ -186,19 +193,19 @@ export class DownloadService { (res) => { const blob = new Blob([res], { type: `text/${type};charset=utf-8;` }); this.saveFile(fileName, blob); - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.ready' ); - snackBarRef.instance.loading = false; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); }, () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.download.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); } ); } @@ -229,26 +236,27 @@ export class DownloadService { const { snackBarRef, headers } = this.triggerFileDownloadMessage( 'common.notifications.file.upload.processing' ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; const formData = new FormData(); formData.append('excelFile', file, file.name); return this.restService.post(path, formData, { headers }).pipe( tap({ next: () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.upload.ready' ); - snackBarRef.instance.loading = false; + snackBarSpinner.instance.loading = false; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); }, error: () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.upload.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); }, }) ); @@ -275,6 +283,7 @@ export class DownloadService { }, } ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; const path = `upload/${BLOB_TYPE_TO_PATH[type]}/${entity}`; const headers = new HttpHeaders({ @@ -289,20 +298,20 @@ export class DownloadService { .subscribe((res: { path: string }) => { const { path } = res ?? {}; if (path) { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.upload.ready' ); - snackBarRef.instance.loading = false; + snackBarSpinner.instance.loading = false; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); resolve(path); } else { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.file.upload.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; - setTimeout(() => snackBarRef.instance.dismiss(), 1000); + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; + setTimeout(() => snackBarRef.instance.dismiss(), SNACKBAR_DURATION); reject(); } }); diff --git a/libs/shared/src/lib/services/email/email.service.ts b/libs/shared/src/lib/services/email/email.service.ts index bde9be46f3..e05d7bba65 100644 --- a/libs/shared/src/lib/services/email/email.service.ts +++ b/libs/shared/src/lib/services/email/email.service.ts @@ -94,6 +94,7 @@ export class EmailService { }, } ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; let fileFolderId = ''; if (files && files.length > 0) { const response = await firstValueFrom(this.sendFiles(files)); @@ -124,19 +125,19 @@ export class EmailService { ) .subscribe({ next: () => { - (snackBarRef.instance.message = this.translate.instant( + (snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.email.sent' )), - (snackBarRef.instance.loading = false); + (snackBarSpinner.instance.loading = false); setTimeout(() => snackBarRef.instance.dismiss(), 1000); }, error: () => { - (snackBarRef.instance.message = this.translate.instant( + (snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.email.error' )), - (snackBarRef.instance.loading = false); - snackBarRef.instance.error = true; + (snackBarSpinner.instance.loading = false); + snackBarSpinner.instance.error = true; setTimeout(() => snackBarRef.instance.dismiss(), 1000); }, }); @@ -182,6 +183,7 @@ export class EmailService { }, } ); + const snackBarSpinner = snackBarRef.instance.nestedComponent; const headers = new HttpHeaders({ 'Content-Type': 'application/json', }); @@ -203,10 +205,10 @@ export class EmailService { ) .subscribe({ next: async (res) => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.email.ready' ); - snackBarRef.instance.loading = false; + snackBarSpinner.instance.loading = false; setTimeout(() => snackBarRef.instance.dismiss(), 1000); const { EmailPreviewComponent } = await import( '../../components/email-preview/email-preview.component' @@ -234,11 +236,11 @@ export class EmailService { }); }, error: () => { - snackBarRef.instance.message = this.translate.instant( + snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.email.error' ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; + snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.error = true; setTimeout(() => snackBarRef.instance.dismiss(), 1000); }, diff --git a/libs/ui/src/lib/snackbar/snackbar.component.ts b/libs/ui/src/lib/snackbar/snackbar.component.ts index e2f74d9510..36d24634f0 100644 --- a/libs/ui/src/lib/snackbar/snackbar.component.ts +++ b/libs/ui/src/lib/snackbar/snackbar.component.ts @@ -1,5 +1,6 @@ import { Component, + ComponentRef, ElementRef, EventEmitter, Inject, @@ -30,7 +31,7 @@ export class SnackbarComponent { snackBarContentView!: ViewContainerRef; /** The data for the snack bar. */ data!: BehaviorSubject; - /** The message to display in the snack bar. */ + /** Message displayed in snackbar */ message!: string; /** Boolean indicating whether there is an error. */ error = false; @@ -38,8 +39,15 @@ export class SnackbarComponent { displaySnackBar = false; /** The action to perform. */ action!: string; - /** Function to resolve after a certain duration. */ + /** Reference to nested component ( if created from one ) */ + public nestedComponent?: ComponentRef; + /** + * Function to resolve after a certain duration. + * + * @param duration duration in ms + * @returns Promise + */ durationResolver = (duration: number) => new Promise((resolve) => setTimeout(resolve, duration)); @@ -120,7 +128,11 @@ export class SnackbarComponent { */ openFromComponent(component: ComponentType, config: SnackBarConfig) { this.setSnackbarProperties(config); - this.snackBarContentView?.createComponent(component); + const ref = this.snackBarContentView?.createComponent(component); + console.log(ref.instance); + this.nestedComponent = ref; + console.log(this.nestedComponent); + ref.changeDetectorRef.detectChanges(); this.triggerSnackBar(config.duration); } diff --git a/libs/ui/src/lib/snackbar/snackbar.service.ts b/libs/ui/src/lib/snackbar/snackbar.service.ts index 017c192d58..ac1353bb45 100644 --- a/libs/ui/src/lib/snackbar/snackbar.service.ts +++ b/libs/ui/src/lib/snackbar/snackbar.service.ts @@ -53,6 +53,7 @@ export class SnackbarService { const appendBody = this.shadowDom ?? this.document.body; appendBody.appendChild(snackBar.location.nativeElement); this.app.attachView(snackBar.hostView); + snackBar.changeDetectorRef.detectChanges(); } /**