diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b77d53c81d4..d9c85a24d83 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -12,6 +12,7 @@ import { import { NavigationCancel, NavigationEnd, + NavigationError, NavigationStart, Router, } from '@angular/router'; @@ -122,7 +123,8 @@ export class AppComponent implements OnInit, AfterViewInit { distinctNext(this.isRouteLoading$, true); } else if ( event instanceof NavigationEnd || - event instanceof NavigationCancel + event instanceof NavigationCancel || + event instanceof NavigationError ) { distinctNext(this.isRouteLoading$, false); } diff --git a/src/app/core/submission/resolver/submission-links-to-follow.ts b/src/app/core/submission/resolver/submission-links-to-follow.ts index b4aa3586ebe..b05cc2dc418 100644 --- a/src/app/core/submission/resolver/submission-links-to-follow.ts +++ b/src/app/core/submission/resolver/submission-links-to-follow.ts @@ -9,6 +9,13 @@ import { WorkspaceItem } from '../models/workspaceitem.model'; * Needs to be in a separate file to prevent circular dependencies in webpack. */ export const SUBMISSION_LINKS_TO_FOLLOW: FollowLinkConfig[] = [ - followLink('item'), + followLink('item', {}, + followLink('owningCollection', {}, + followLink('parentCommunity', {}, + followLink('parentCommunity')), + ), + followLink('version', {}, followLink('versionhistory')), + followLink('thumbnail'), + ), followLink('collection'), ]; diff --git a/src/app/core/submission/resolver/submission-object.resolver.ts b/src/app/core/submission/resolver/submission-object.resolver.ts index b059b69e4d2..d09c96d54e7 100644 --- a/src/app/core/submission/resolver/submission-object.resolver.ts +++ b/src/app/core/submission/resolver/submission-object.resolver.ts @@ -26,7 +26,7 @@ export class SubmissionObjectResolver implements Resolve> { */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { const itemRD$ = this.dataService.findById(route.params.id, - true, + false, false, ...SUBMISSION_LINKS_TO_FOLLOW, ).pipe( diff --git a/src/app/item-page/item.resolver.ts b/src/app/item-page/item.resolver.ts index c5225675991..e3cb87ddf6d 100644 --- a/src/app/item-page/item.resolver.ts +++ b/src/app/item-page/item.resolver.ts @@ -51,7 +51,7 @@ export class ItemResolver implements Resolve> { */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { const itemRD$ = this.itemService.findById(route.params.id, - true, + false, true, ...getItemPageLinksToFollow(), ).pipe( diff --git a/src/app/item-page/versions/notice/item-versions-notice.component.ts b/src/app/item-page/versions/notice/item-versions-notice.component.ts index 37f81976132..fe6e5182dc9 100644 --- a/src/app/item-page/versions/notice/item-versions-notice.component.ts +++ b/src/app/item-page/versions/notice/item-versions-notice.component.ts @@ -89,8 +89,6 @@ export class ItemVersionsNoticeComponent implements OnInit { map((isLatest) => isLatest != null && !isLatest), startWith(false), ); - } - // Compute the destination URL from latestVersion$ with the namespace this.destinationUrl$ = this.latestVersion$.pipe( switchMap(latestVersion => latestVersion?.item || of(null)), @@ -110,7 +108,11 @@ export class ItemVersionsNoticeComponent implements OnInit { return finalUrl; }) - ); + ); + } else { + this.showLatestVersionNotice$ = of(false); + this.destinationUrl$ = of(this.document.location.pathname); + } } } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts index a26fbaaf57c..2b5396edca1 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts @@ -78,6 +78,13 @@ describe('ItemMyDSpaceResultListElementComponent', () => { }); it('should have correct badge context', () => { + expect(component.badgeContext).toEqual(Context.Any); + }); + + it('should show archived badge context when item is archived', () => { + component.dso = Object.assign(new Item(), mockResultObject.indexableObject, { isArchived: true }); + component.ngOnInit(); + expect(component.badgeContext).toEqual(Context.MyDSpaceArchived); }); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts index 39dc208bf4a..579f5c6ec1f 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts @@ -22,7 +22,7 @@ export class ItemSearchResultListElementSubmissionComponent extends SearchResult /** * Represents the badge context */ - public badgeContext = Context.MyDSpaceArchived; + public badgeContext = Context.Any; /** @@ -33,6 +33,14 @@ export class ItemSearchResultListElementSubmissionComponent extends SearchResult ngOnInit() { super.ngOnInit(); + + // Show the Archived badge only for items that are actually archived. + if (this.dso?.isArchived) { + this.badgeContext = Context.MyDSpaceArchived; + } else { + this.badgeContext = Context.Any; + } + this.showThumbnails = this.appConfig.browseBy.showThumbnails; } } diff --git a/src/app/shared/theme-support/themed.component.ts b/src/app/shared/theme-support/themed.component.ts index 2e2585f7774..df4037e0f6e 100644 --- a/src/app/shared/theme-support/themed.component.ts +++ b/src/app/shared/theme-support/themed.component.ts @@ -119,6 +119,9 @@ export abstract class ThemedComponent implements AfterViewInit, OnDestroy, On this.lazyLoadSub = this.lazyLoadObs.subscribe(([simpleChanges, constructor]: [SimpleChanges, GenericConstructor]) => { this.destroyComponentInstance(); + if (!this.vcr || !this.themedElementContent) { + return; + } this.compRef = this.vcr.createComponent(constructor, { projectableNodes: [this.themedElementContent.nativeElement.childNodes], }); diff --git a/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.spec.ts b/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.spec.ts index d1b598c7025..269fa838755 100644 --- a/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.spec.ts +++ b/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.spec.ts @@ -93,7 +93,7 @@ describe('ViewTrackerResolverService', () => { expect(emittedEvent.properties.dc_identifier).toBeUndefined(); }); - it('should handle missing dso gracefully (dc_identifier undefined)', () => { + it('should not emit tracking event when dso is missing', () => { const routeSnapshot = { data: { dso: { @@ -111,9 +111,7 @@ describe('ViewTrackerResolverService', () => { service.resolve(routeSnapshot, stateSnapshot); routerEvents$.next(new ResolveEnd(1, '/', '/', {} as any)); - expect(emittedEvent).toBeDefined(); - expect(emittedEvent.action).toBe('page_view'); - expect(emittedEvent.properties.dc_identifier).toBeUndefined(); + expect(emittedEvent).toBeUndefined(); }); it('should use custom dsoPath from route data when provided', () => { diff --git a/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.ts b/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.ts index 40afc6d2c5c..318049457dd 100644 --- a/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.ts +++ b/src/app/statistics/angulartics/dspace/view-tracker-resolver.service.ts @@ -1,6 +1,6 @@ import { Injectable, } from '@angular/core'; import { Angulartics2 } from 'angulartics2'; -import { switchMap } from 'rxjs'; +import { EMPTY, map, switchMap } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { ReferrerService } from '../../../core/services/referrer.service'; @@ -26,10 +26,17 @@ export class ViewTrackerResolverService { this.router.events.pipe( filter(event => event instanceof ResolveEnd), take(1), - switchMap(() => - this.referrerService.getReferrer().pipe(take(1)))) - .subscribe((referrer: string) => { + switchMap(() => { const object = this.getNestedProperty(routeSnapshot.data, dsoPath); + if (!object) { + return EMPTY; + } + return this.referrerService.getReferrer().pipe( + take(1), + map((referrer: string) => ({ object, referrer })), + ); + })) + .subscribe(({ object, referrer }: { object: any, referrer: string }) => { const dc_identifier = object?.firstMetadataValue?.('dc.identifier.uri'); this.angulartics2.eventTrack.next({ action: 'page_view',