Merge pull request #4324 from 4Science/task/main/DURACOM-367

Fix matomo SSR error on bitstream download page
This commit is contained in:
Tim Donohue
2025-05-12 12:17:59 -05:00
committed by GitHub
4 changed files with 45 additions and 21 deletions

View File

@@ -60,7 +60,7 @@ export class FooterComponent implements OnInit {
}
showCookieSettings() {
if (hasValue(this.cookies)) {
if (hasValue(this.cookies) && this.cookies.showSettings instanceof Function) {
this.cookies.showSettings();
}
return false;

View File

@@ -4,7 +4,7 @@ import { Observable } from 'rxjs';
/**
* Abstract class representing a service for handling Orejime consent preferences and UI
*/
@Injectable()
@Injectable({ providedIn: 'root' })
export abstract class OrejimeService {
/**
* Initializes the service

View File

@@ -1,3 +1,7 @@
import {
Injector,
runInInjectionContext,
} from '@angular/core';
import {
fakeAsync,
TestBed,
@@ -53,6 +57,7 @@ describe('MatomoService', () => {
{ provide: OrejimeService, useValue: orejimeService },
{ provide: NativeWindowService, useValue: nativeWindowService },
{ provide: ConfigurationDataService, useValue: configService },
{ provide: Injector, useValue: TestBed },
],
});
@@ -70,11 +75,13 @@ describe('MatomoService', () => {
});
it('should call setConsentGiven when consent is true', () => {
service.matomoTracker = matomoTracker;
service.changeMatomoConsent(true);
expect(matomoTracker.setConsentGiven).toHaveBeenCalled();
});
it('should call forgetConsentGiven when consent is false', () => {
service.matomoTracker = matomoTracker;
service.changeMatomoConsent(false);
expect(matomoTracker.forgetConsentGiven).toHaveBeenCalled();
});
@@ -91,7 +98,10 @@ describe('MatomoService', () => {
configService.findByPropertyName.withArgs(MATOMO_SITE_ID).and.returnValue(
createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] })));
orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true }));
service.init();
runInInjectionContext(TestBed, () => {
service.init();
});
expect(matomoTracker.setConsentGiven).toHaveBeenCalled();
expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({
@@ -100,7 +110,7 @@ describe('MatomoService', () => {
});
});
it('should initialize tracker with REST configuration correct parameters in production', () => {
it('should initialize tracker with REST configuration correct parameters in production', fakeAsync(() => {
environment.production = true;
environment.matomo = { trackerUrl: '' };
configService.findByPropertyName.withArgs(MATOMO_TRACKER_URL).and.returnValue(
@@ -113,19 +123,25 @@ describe('MatomoService', () => {
createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] })));
orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true }));
service.init();
runInInjectionContext(TestBed, () => {
service.init();
});
tick();
expect(matomoTracker.setConsentGiven).toHaveBeenCalled();
expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({
siteId: '1',
trackerUrl: 'http://example.com',
});
});
}));
it('should not initialize tracker if not in production', () => {
environment.production = false;
service.init();
runInInjectionContext(TestBed, () => {
service.init();
});
expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled();
});
@@ -143,7 +159,9 @@ describe('MatomoService', () => {
createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] })));
orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true }));
service.init();
runInInjectionContext(TestBed, () => {
service.init();
});
expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled();
});
@@ -151,6 +169,7 @@ describe('MatomoService', () => {
describe('with visitorId set', () => {
beforeEach(() => {
matomoTracker.getVisitorId.and.returnValue(Promise.resolve('12345'));
service.matomoTracker = matomoTracker;
});
it('should add trackerId parameter', fakeAsync(() => {

View File

@@ -1,6 +1,8 @@
import {
EnvironmentInjector,
inject,
Injectable,
runInInjectionContext,
} from '@angular/core';
import {
MatomoInitializerService,
@@ -11,12 +13,10 @@ import {
from as fromPromise,
Observable,
of,
switchMap,
} from 'rxjs';
import {
map,
take,
tap,
} from 'rxjs/operators';
import { environment } from '../../environments/environment';
@@ -47,10 +47,10 @@ export const MATOMO_ENABLED = 'matomo.enabled';
export class MatomoService {
/** Injects the MatomoInitializerService to initialize the Matomo tracker. */
matomoInitializer = inject(MatomoInitializerService);
matomoInitializer: MatomoInitializerService;
/** Injects the MatomoTracker to manage Matomo tracking operations. */
matomoTracker = inject(MatomoTracker);
matomoTracker: MatomoTracker;
/** Injects the OrejimeService to manage cookie consent preferences. */
orejimeService = inject(OrejimeService);
@@ -61,6 +61,10 @@ export class MatomoService {
/** Injects the ConfigurationService. */
configService = inject(ConfigurationDataService);
constructor(private injector: EnvironmentInjector) {
}
/**
* Initializes the Matomo tracker if in production environment.
* Sets up the changeMatomoConsent function on the native window object.
@@ -74,14 +78,15 @@ export class MatomoService {
if (environment.production) {
const preferences$ = this.orejimeService.getSavedPreferences();
preferences$
.pipe(
tap(preferences => this.changeMatomoConsent(preferences?.matomo)),
switchMap(_ => combineLatest([this.isMatomoEnabled$(), this.getSiteId$(), this.getTrackerUrl$()])),
)
.subscribe(([isMatomoEnabled, siteId, trackerUrl]) => {
combineLatest([preferences$, this.isMatomoEnabled$(), this.getSiteId$(), this.getTrackerUrl$()])
.subscribe(([preferences, isMatomoEnabled, siteId, trackerUrl]) => {
if (isMatomoEnabled && siteId && trackerUrl) {
runInInjectionContext(this.injector, () => {
this.matomoTracker = inject(MatomoTracker);
this.matomoInitializer = inject(MatomoInitializerService);
});
this.matomoInitializer.initializeTracker({ siteId, trackerUrl });
this.changeMatomoConsent(preferences?.matomo);
}
});
}
@@ -93,9 +98,9 @@ export class MatomoService {
*/
changeMatomoConsent = (consent: boolean) => {
if (consent) {
this.matomoTracker.setConsentGiven();
this.matomoTracker?.setConsentGiven();
} else {
this.matomoTracker.forgetConsentGiven();
this.matomoTracker?.forgetConsentGiven();
}
};
@@ -105,7 +110,7 @@ export class MatomoService {
* @returns An Observable that emits the URL with the visitor ID appended.
*/
appendVisitorId(url: string): Observable<string> {
return fromPromise(this.matomoTracker.getVisitorId())
return fromPromise(this.matomoTracker?.getVisitorId())
.pipe(
map(visitorId => this.appendTrackerId(url, visitorId)),
take(1),