diff --git a/apps/metadata-editor/src/app/duplicate-record.resolver.spec.ts b/apps/metadata-editor/src/app/duplicate-record.resolver.spec.ts index 2ec7eafc53..9290157ac4 100644 --- a/apps/metadata-editor/src/app/duplicate-record.resolver.spec.ts +++ b/apps/metadata-editor/src/app/duplicate-record.resolver.spec.ts @@ -75,12 +75,16 @@ describe('DuplicateRecordResolver', () => { expect(resolvedData).toBeUndefined() }) it('should show error notification', () => { - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - title: 'editor.record.loadError.title', - text: 'editor.record.loadError.body oopsie', - closeMessage: 'editor.record.loadError.closeMessage', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + title: 'editor.record.loadError.title', + text: 'editor.record.loadError.body oopsie', + closeMessage: 'editor.record.loadError.closeMessage', + }, + undefined, + expect.any(Error) + ) }) }) }) diff --git a/apps/metadata-editor/src/app/duplicate-record.resolver.ts b/apps/metadata-editor/src/app/duplicate-record.resolver.ts index 89df9a5699..78f95c4890 100644 --- a/apps/metadata-editor/src/app/duplicate-record.resolver.ts +++ b/apps/metadata-editor/src/app/duplicate-record.resolver.ts @@ -23,18 +23,22 @@ export class DuplicateRecordResolver { .openRecordForDuplication(route.paramMap.get('uuid')) .pipe( catchError((error) => { - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.loadError.title' - ), - text: `${this.translateService.instant( - 'editor.record.loadError.body' - )} ${error.message}`, - closeMessage: this.translateService.instant( - 'editor.record.loadError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.loadError.title' + ), + text: `${this.translateService.instant( + 'editor.record.loadError.body' + )} ${error.message}`, + closeMessage: this.translateService.instant( + 'editor.record.loadError.closeMessage' + ), + }, + undefined, + error + ) return EMPTY }) ) diff --git a/apps/metadata-editor/src/app/edit-record.resolver.spec.ts b/apps/metadata-editor/src/app/edit-record.resolver.spec.ts index ffe79371a8..28bb067edb 100644 --- a/apps/metadata-editor/src/app/edit-record.resolver.spec.ts +++ b/apps/metadata-editor/src/app/edit-record.resolver.spec.ts @@ -75,12 +75,16 @@ describe('EditRecordResolver', () => { expect(resolvedData).toBeUndefined() }) it('should show error notification', () => { - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - title: 'editor.record.loadError.title', - text: 'editor.record.loadError.body oopsie', - closeMessage: 'editor.record.loadError.closeMessage', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + title: 'editor.record.loadError.title', + text: 'editor.record.loadError.body oopsie', + closeMessage: 'editor.record.loadError.closeMessage', + }, + undefined, + expect.any(Error) + ) }) }) }) diff --git a/apps/metadata-editor/src/app/edit-record.resolver.ts b/apps/metadata-editor/src/app/edit-record.resolver.ts index 337a1bf858..fe4c9d7486 100644 --- a/apps/metadata-editor/src/app/edit-record.resolver.ts +++ b/apps/metadata-editor/src/app/edit-record.resolver.ts @@ -23,18 +23,22 @@ export class EditRecordResolver { .openRecordForEdition(route.paramMap.get('uuid')) .pipe( catchError((error) => { - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.loadError.title' - ), - text: `${this.translateService.instant( - 'editor.record.loadError.body' - )} ${error.message}`, - closeMessage: this.translateService.instant( - 'editor.record.loadError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.loadError.title' + ), + text: `${this.translateService.instant( + 'editor.record.loadError.body' + )} ${error.message}`, + closeMessage: this.translateService.instant( + 'editor.record.loadError.closeMessage' + ), + }, + undefined, + error + ) return EMPTY }) ) diff --git a/apps/metadata-editor/src/app/edit/edit-page.component.spec.ts b/apps/metadata-editor/src/app/edit/edit-page.component.spec.ts index 1885913f8e..cee46e3c67 100644 --- a/apps/metadata-editor/src/app/edit/edit-page.component.spec.ts +++ b/apps/metadata-editor/src/app/edit/edit-page.component.spec.ts @@ -121,24 +121,32 @@ describe('EditPageComponent', () => { describe('publish version error', () => { it('shows notification', () => { ;(facade.saveError$ as any).next(new PublicationVersionError('1.0.0')) - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - title: 'editor.record.publishVersionError.title', - text: 'editor.record.publishVersionError.body', - closeMessage: 'editor.record.publishVersionError.closeMessage', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + title: 'editor.record.publishVersionError.title', + text: 'editor.record.publishVersionError.body', + closeMessage: 'editor.record.publishVersionError.closeMessage', + }, + undefined, + expect.any(PublicationVersionError) + ) }) }) describe('publish error', () => { it('shows notification', () => { ;(facade.saveError$ as any).next(new Error('oopsie')) - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - title: 'editor.record.publishError.title', - text: 'editor.record.publishError.body oopsie', - closeMessage: 'editor.record.publishError.closeMessage', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + title: 'editor.record.publishError.title', + text: 'editor.record.publishError.body oopsie', + closeMessage: 'editor.record.publishError.closeMessage', + }, + undefined, + expect.any(Error) + ) }) }) @@ -204,4 +212,25 @@ describe('EditPageComponent', () => { expect(await firstValueFrom(component.isLastPage$)).toBe(false) }) }) + + describe('subscriptions', () => { + it('should add 3 subscriptions to component.subscription', () => { + const addSpy = jest.spyOn(component.subscription, 'add') + component.ngOnInit() + expect(addSpy).toHaveBeenCalledTimes(3) + }) + it('should add 4 subscriptions to component.subscription when on /create route', () => { + const activatedRoute = TestBed.inject(ActivatedRoute) + activatedRoute.snapshot.routeConfig.path = '/create' + fixture.detectChanges() + const addSpy = jest.spyOn(component.subscription, 'add') + component.ngOnInit() + expect(addSpy).toHaveBeenCalledTimes(4) + }) + it('unsubscribes', () => { + const unsubscribeSpy = jest.spyOn(component.subscription, 'unsubscribe') + component.ngOnDestroy() + expect(unsubscribeSpy).toHaveBeenCalled() + }) + }) }) diff --git a/apps/metadata-editor/src/app/edit/edit-page.component.ts b/apps/metadata-editor/src/app/edit/edit-page.component.ts index fe630e18ba..bead8d580e 100644 --- a/apps/metadata-editor/src/app/edit/edit-page.component.ts +++ b/apps/metadata-editor/src/app/edit/edit-page.component.ts @@ -24,7 +24,6 @@ import { combineLatest, filter, firstValueFrom, Subscription, take } from 'rxjs' import { map } from 'rxjs/operators' import { SidebarComponent } from '../dashboard/sidebar/sidebar.component' import { PageSelectorComponent } from './components/page-selector/page-selector.component' -import { PublishButtonComponent } from './components/publish-button/publish-button.component' import { TopToolbarComponent } from './components/top-toolbar/top-toolbar.component' marker('editor.record.form.bottomButtons.comeBackLater') @@ -41,7 +40,6 @@ marker('editor.record.form.bottomButtons.next') CommonModule, ButtonComponent, MatProgressSpinnerModule, - PublishButtonComponent, TopToolbarComponent, NotificationsContainerComponent, PageSelectorComponent, @@ -83,32 +81,40 @@ export class EditPageComponent implements OnInit, OnDestroy { this.subscription.add( this.facade.saveError$.subscribe((error) => { if (error instanceof PublicationVersionError) { - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.publishVersionError.title' - ), - text: this.translateService.instant( - 'editor.record.publishVersionError.body', - { currentVersion: error.detectedApiVersion } - ), - closeMessage: this.translateService.instant( - 'editor.record.publishVersionError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.publishVersionError.title' + ), + text: this.translateService.instant( + 'editor.record.publishVersionError.body', + { currentVersion: error.detectedApiVersion } + ), + closeMessage: this.translateService.instant( + 'editor.record.publishVersionError.closeMessage' + ), + }, + undefined, + error + ) } else { - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.publishError.title' - ), - text: `${this.translateService.instant( - 'editor.record.publishError.body' - )} ${error.message}`, - closeMessage: this.translateService.instant( - 'editor.record.publishError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.publishError.title' + ), + text: `${this.translateService.instant( + 'editor.record.publishError.body' + )} ${error.message}`, + closeMessage: this.translateService.instant( + 'editor.record.publishError.closeMessage' + ), + }, + undefined, + error + ) } }) ) @@ -132,25 +138,29 @@ export class EditPageComponent implements OnInit, OnDestroy { // if we're on the /create route, go to /edit/{uuid} on first change if (this.route.snapshot.routeConfig?.path.includes('create')) { - this.facade.draftSaveSuccess$.pipe(take(1)).subscribe(() => { - this.router.navigate(['edit', currentRecord.uniqueIdentifier], { - replaceUrl: true, + this.subscription.add( + this.facade.draftSaveSuccess$.pipe(take(1)).subscribe(() => { + this.router.navigate(['edit', currentRecord.uniqueIdentifier], { + replaceUrl: true, + }) }) - }) + ) } // if the record unique identifier changes, navigate to /edit/newUuid - this.facade.record$ - .pipe( - filter( - (record) => - record?.uniqueIdentifier !== currentRecord.uniqueIdentifier - ), - take(1) - ) - .subscribe((savedRecord) => { - this.router.navigate(['edit', savedRecord.uniqueIdentifier]) - }) + this.subscription.add( + this.facade.record$ + .pipe( + filter( + (record) => + record?.uniqueIdentifier !== currentRecord.uniqueIdentifier + ), + take(1) + ) + .subscribe((savedRecord) => { + this.router.navigate(['edit', savedRecord.uniqueIdentifier]) + }) + ) } ngOnDestroy() { diff --git a/libs/feature/editor/src/lib/components/import-record/import-record.component.spec.ts b/libs/feature/editor/src/lib/components/import-record/import-record.component.spec.ts index 09430bde77..d55480972d 100644 --- a/libs/feature/editor/src/lib/components/import-record/import-record.component.spec.ts +++ b/libs/feature/editor/src/lib/components/import-record/import-record.component.spec.ts @@ -112,7 +112,8 @@ describe('ImportRecordComponent', () => { title: 'editor.record.importFromExternalFile.failure.title', text: `editor.record.importFromExternalFile.failure.body `, }), - 2500 + 2500, + mockError ) expect(component.isRecordImportInProgress).toBe(false) diff --git a/libs/feature/editor/src/lib/components/import-record/import-record.component.ts b/libs/feature/editor/src/lib/components/import-record/import-record.component.ts index 2bb72582c4..02e470ebb0 100644 --- a/libs/feature/editor/src/lib/components/import-record/import-record.component.ts +++ b/libs/feature/editor/src/lib/components/import-record/import-record.component.ts @@ -142,7 +142,8 @@ export class ImportRecordComponent { 'editor.record.importFromExternalFile.failure.body' )} ${error.message ?? ''}`, }, - 2500 + 2500, + error ) this.isRecordImportInProgress = false this.cdr.markForCheck() diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts index ce65f266c4..0ad7fa1c75 100644 --- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts +++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts @@ -143,12 +143,16 @@ describe('FormFieldOnlineLinkResourcesComponent', () => { expect(component.uploadProgress).toBeUndefined() component.handleFileChange(file) uploadSubject.error(new Error('something went wrong')) - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - closeMessage: 'editor.record.onlineResourceError.closeMessage', - text: 'editor.record.onlineResourceError.body something went wrong', - title: 'editor.record.onlineResourceError.title', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + closeMessage: 'editor.record.onlineResourceError.closeMessage', + text: 'editor.record.onlineResourceError.body something went wrong', + title: 'editor.record.onlineResourceError.title', + }, + undefined, + expect.any(Error) + ) }) }) describe('handleUploadCancel', () => { diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts index 3000324226..97cc3c138a 100644 --- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts +++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts @@ -137,18 +137,22 @@ export class FormFieldOnlineLinkResourcesComponent { private handleError(error: Error) { this.uploadProgress = undefined this.cd.detectChanges() - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.onlineResourceError.title' - ), - text: `${this.translateService.instant( - 'editor.record.onlineResourceError.body' - )} ${error.message}`, - closeMessage: this.translateService.instant( - 'editor.record.onlineResourceError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.onlineResourceError.title' + ), + text: `${this.translateService.instant( + 'editor.record.onlineResourceError.body' + )} ${error.message}`, + closeMessage: this.translateService.instant( + 'editor.record.onlineResourceError.closeMessage' + ), + }, + undefined, + error + ) } private openEditDialog(resource: OnlineLinkResource, index: number) { diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts index 6079095018..8aaca6802d 100644 --- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts +++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts @@ -192,18 +192,22 @@ export class FormFieldOnlineResourcesComponent { private handleError(error: Error) { this.uploadProgress = undefined - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.onlineResourceError.title' - ), - text: `${this.translateService.instant( - 'editor.record.onlineResourceError.body' - )} ${error.message}`, - closeMessage: this.translateService.instant( - 'editor.record.onlineResourceError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.onlineResourceError.title' + ), + text: `${this.translateService.instant( + 'editor.record.onlineResourceError.body' + )} ${error.message}`, + closeMessage: this.translateService.instant( + 'editor.record.onlineResourceError.closeMessage' + ), + }, + undefined, + error + ) } private openEditDialog(resource: OnlineNotLinkResource, index: number) { diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts index a18dab7012..d3555ed6d7 100644 --- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts +++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts @@ -119,12 +119,16 @@ describe('FormFieldOverviewsComponent', () => { expect(component.uploadProgress).toBeUndefined() component.handleFileChange(file) uploadSubject.error(new Error('something went wrong')) - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - closeMessage: 'editor.record.resourceError.closeMessage', - text: 'editor.record.resourceError.body something went wrong', - title: 'editor.record.resourceError.title', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + closeMessage: 'editor.record.resourceError.closeMessage', + text: 'editor.record.resourceError.body something went wrong', + title: 'editor.record.resourceError.title', + }, + undefined, + expect.any(Error) + ) }) }) diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts index ae56250a87..3e4c25db48 100644 --- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts +++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts @@ -109,15 +109,21 @@ export class FormFieldOverviewsComponent { private handleError = (error: Error) => { this.uploadProgress = undefined this.cd.markForCheck() - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant('editor.record.resourceError.title'), - text: `${this.translateService.instant( - 'editor.record.resourceError.body' - )} ${error.message}`, - closeMessage: this.translateService.instant( - 'editor.record.resourceError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.resourceError.title' + ), + text: `${this.translateService.instant( + 'editor.record.resourceError.body' + )} ${error.message}`, + closeMessage: this.translateService.instant( + 'editor.record.resourceError.closeMessage' + ), + }, + undefined, + error + ) } } diff --git a/libs/feature/notifications/src/lib/notifications.service.ts b/libs/feature/notifications/src/lib/notifications.service.ts index cbf38e52c2..b7281989ff 100644 --- a/libs/feature/notifications/src/lib/notifications.service.ts +++ b/libs/feature/notifications/src/lib/notifications.service.ts @@ -10,7 +10,12 @@ type NotificationWithIdentity = NotificationContent & { id: number } export class NotificationsService { notifications$ = new BehaviorSubject([]) - showNotification(content: NotificationContent, timeoutMs?: number) { + showNotification( + content: NotificationContent, + timeoutMs?: number, + error?: Error + ) { + error && console.error(error) const id = Math.floor(Math.random() * 1000000) this.notifications$.next([...this.notifications$.value, { ...content, id }]) if (typeof timeoutMs === 'undefined') return diff --git a/libs/feature/search/src/lib/results-table/results-table-container.component.spec.ts b/libs/feature/search/src/lib/results-table/results-table-container.component.spec.ts index 85e63b4d85..6504bea923 100644 --- a/libs/feature/search/src/lib/results-table/results-table-container.component.spec.ts +++ b/libs/feature/search/src/lib/results-table/results-table-container.component.spec.ts @@ -120,12 +120,16 @@ describe('ResultsTableContainerComponent', () => { throwError(() => 'oopsie') ) component.handleDeleteRecord(datasetRecordsFixture()[0]) - expect(notificationsService.showNotification).toHaveBeenCalledWith({ - type: 'error', - title: 'editor.record.deleteError.title', - text: 'editor.record.deleteError.body oopsie', - closeMessage: 'editor.record.deleteError.closeMessage', - }) + expect(notificationsService.showNotification).toHaveBeenCalledWith( + { + type: 'error', + title: 'editor.record.deleteError.title', + text: 'editor.record.deleteError.body oopsie', + closeMessage: 'editor.record.deleteError.closeMessage', + }, + undefined, + 'oopsie' + ) }) }) diff --git a/libs/feature/search/src/lib/results-table/results-table-container.component.ts b/libs/feature/search/src/lib/results-table/results-table-container.component.ts index 43afbe95bc..b2f75f483b 100644 --- a/libs/feature/search/src/lib/results-table/results-table-container.component.ts +++ b/libs/feature/search/src/lib/results-table/results-table-container.component.ts @@ -79,18 +79,22 @@ export class ResultsTableContainerComponent implements OnDestroy { ) }, error: (error) => { - this.notificationsService.showNotification({ - type: 'error', - title: this.translateService.instant( - 'editor.record.deleteError.title' - ), - text: `${this.translateService.instant( - 'editor.record.deleteError.body' - )} ${error}`, - closeMessage: this.translateService.instant( - 'editor.record.deleteError.closeMessage' - ), - }) + this.notificationsService.showNotification( + { + type: 'error', + title: this.translateService.instant( + 'editor.record.deleteError.title' + ), + text: `${this.translateService.instant( + 'editor.record.deleteError.body' + )} ${error}`, + closeMessage: this.translateService.instant( + 'editor.record.deleteError.closeMessage' + ), + }, + undefined, + error + ) }, }) )