1- import { Injectable } from '@angular/core' ;
1+ import { Injectable } from '@angular/core' ;
22import * as Klaro from 'klaro' ;
3- import { combineLatest as observableCombineLatest , Observable , of as observableOf } from 'rxjs' ;
4- import { AuthService } from '../../core/auth/auth.service' ;
5- import { TranslateService } from '@ngx-translate/core' ;
6- import { environment } from '../../../environments/environment' ;
7- import { catchError , switchMap , take } from 'rxjs/operators' ;
8- import { EPerson } from '../../core/eperson/models/eperson.model' ;
9- import { KlaroService } from './klaro.service' ;
10- import { hasValue , isEmpty , isNotEmpty } from '../empty.util' ;
11- import { CookieService } from '../../core/services/cookie.service' ;
12- import { EPersonDataService } from '../../core/eperson/eperson-data.service' ;
13- import { cloneDeep , debounce } from 'lodash' ;
14- import { ANONYMOUS_STORAGE_NAME_KLARO , klaroConfiguration } from './klaro-configuration' ;
15- import { Operation } from 'fast-json-patch' ;
16- import { getFirstCompletedRemoteData } from '../../core/shared/operators' ;
17- import { ConfigurationDataService } from '../../core/data/configuration-data.service' ;
3+ import { combineLatest as observableCombineLatest , Observable , of as observableOf } from 'rxjs' ;
4+ import { AuthService } from '../../core/auth/auth.service' ;
5+ import { TranslateService } from '@ngx-translate/core' ;
6+ import { environment } from '../../../environments/environment' ;
7+ import { map , switchMap , take } from 'rxjs/operators' ;
8+ import { EPerson } from '../../core/eperson/models/eperson.model' ;
9+ import { KlaroService } from './klaro.service' ;
10+ import { hasValue , isEmpty , isNotEmpty } from '../empty.util' ;
11+ import { CookieService } from '../../core/services/cookie.service' ;
12+ import { EPersonDataService } from '../../core/eperson/eperson-data.service' ;
13+ import { cloneDeep , debounce } from 'lodash' ;
14+ import { ANONYMOUS_STORAGE_NAME_KLARO , klaroConfiguration } from './klaro-configuration' ;
15+ import { Operation } from 'fast-json-patch' ;
16+ import { getFirstCompletedRemoteData } from '../../core/shared/operators' ;
17+ import { ConfigurationDataService } from '../../core/data/configuration-data.service' ;
18+ import { RemoteData } from "../../core/data/remote-data" ;
19+ import { ConfigurationProperty } from "../../core/shared/configuration-property.model" ;
1820
1921/**
2022 * Metadata field to store a user's cookie consent preferences in
@@ -40,15 +42,21 @@ const cookiePurposeMessagePrefix = 'cookies.consent.purpose.';
4042 * Update request debounce in ms
4143 */
4244const updateDebounce = 300 ;
45+
4346/**
4447 * Browser implementation for the KlaroService, representing a service for handling Klaro consent preferences and UI
4548 */
4649@Injectable ( )
4750export class BrowserKlaroService extends KlaroService {
51+
52+ private readonly GOOGLE_ANALYTICS_KEY = 'google.analytics.key' ;
53+
54+ private readonly GOOGLE_ANALYTICS_SERVICE_NAME = 'google-analytics' ;
55+
4856 /**
4957 * Initial Klaro configuration
5058 */
51- klaroConfig = klaroConfiguration ;
59+ klaroConfig = cloneDeep ( klaroConfiguration ) ;
5260
5361 constructor (
5462 private translateService : TranslateService ,
@@ -58,6 +66,7 @@ export class BrowserKlaroService extends KlaroService {
5866 private cookieService : CookieService ) {
5967 super ( ) ;
6068 }
69+
6170 /**
6271 * Initializes the service:
6372 * - Retrieves the current authenticated user
@@ -71,23 +80,22 @@ export class BrowserKlaroService extends KlaroService {
7180 this . klaroConfig . translations . en . consentNotice . description = 'cookies.consent.content-notice.description.no-privacy' ;
7281 }
7382
74- this . configService . findByPropertyName ( 'google.analytics.key' ) . pipe (
75- getFirstCompletedRemoteData ( ) ,
76- ) . subscribe ( ( remoteData ) => {
77- // make sure we got a success response from the backend
78- if ( ! remoteData . hasSucceeded || ! remoteData . payload || isEmpty ( remoteData . payload . values ) ) {
79- this . removeGoogleAnalytics ( ) ;
80- }
81- } ) ;
83+ const configurationToHide$ : Observable < Pick < typeof klaroConfiguration , 'name' > [ ] > =
84+ this . configService . findByPropertyName ( this . GOOGLE_ANALYTICS_KEY )
85+ . pipe (
86+ getFirstCompletedRemoteData ( ) ,
87+ map ( remoteData => this . mapInvalidConfiguration ( remoteData , this . GOOGLE_ANALYTICS_SERVICE_NAME ) ) ,
88+ take ( 1 )
89+ ) ;
8290
8391 this . translateService . setDefaultLang ( environment . defaultLanguage ) ;
8492
8593 const user$ : Observable < EPerson > = this . getUser$ ( ) ;
8694
8795 const translationServiceReady$ = this . translateService . get ( 'loading.default' ) . pipe ( take ( 1 ) ) ;
8896
89- observableCombineLatest ( [ user$ , translationServiceReady$ ] )
90- . subscribe ( ( [ user , translation ] : [ EPerson , string ] ) => {
97+ observableCombineLatest ( [ user$ , translationServiceReady$ , configurationToHide$ ] )
98+ . subscribe ( ( [ user , translation , servicesToHide ] : [ EPerson , string , Pick < typeof klaroConfiguration , 'name' > [ ] ] ) => {
9199 user = cloneDeep ( user ) ;
92100
93101 if ( hasValue ( user ) ) {
@@ -105,10 +113,28 @@ export class BrowserKlaroService extends KlaroService {
105113 * Show the configuration if the configuration has not been confirmed
106114 */
107115 this . translateConfiguration ( ) ;
116+
117+ this . klaroConfig . services = this . filterConfigServices ( servicesToHide ) ;
118+
108119 Klaro . setup ( this . klaroConfig ) ;
109120 } ) ;
110121 }
111122
123+ private mapInvalidConfiguration (
124+ remoteData : RemoteData < ConfigurationProperty > ,
125+ configurationName : string
126+ ) : Pick < typeof klaroConfiguration , 'name' > [ ] {
127+ if ( this . isEmptyOrInvalid ( remoteData ) ) {
128+ return [ { name : configurationName } ]
129+ } else {
130+ return [ ] ;
131+ }
132+ }
133+
134+ private isEmptyOrInvalid ( remoteData : RemoteData < ConfigurationProperty > ) : boolean {
135+ return ! remoteData . hasSucceeded || ! remoteData . payload || isEmpty ( remoteData . payload . values ) ;
136+ }
137+
112138 /**
113139 * Initialize configuration for the logged in user
114140 * @param user The authenticated user
@@ -180,7 +206,10 @@ export class BrowserKlaroService extends KlaroService {
180206 */
181207 addAppMessages ( ) {
182208 this . klaroConfig . services . forEach ( ( app ) => {
183- this . klaroConfig . translations . en [ app . name ] = { title : this . getTitleTranslation ( app . name ) , description : this . getDescriptionTranslation ( app . name ) } ;
209+ this . klaroConfig . translations . en [ app . name ] = {
210+ title : this . getTitleTranslation ( app . name ) ,
211+ description : this . getDescriptionTranslation ( app . name )
212+ } ;
184213 app . purposes . forEach ( ( purpose ) => {
185214 this . klaroConfig . translations . en . purposes [ purpose ] = this . getPurposeTranslation ( purpose ) ;
186215 } ) ;
@@ -273,8 +302,7 @@ export class BrowserKlaroService extends KlaroService {
273302 /**
274303 * remove the google analytics from the services
275304 */
276- removeGoogleAnalytics ( ) {
277- this . klaroConfig . services = klaroConfiguration . services . filter ( config => config . name !== 'google-analytics' ) ;
278- return this . klaroConfig . services ;
305+ private filterConfigServices ( servicesToHide : Pick < typeof klaroConfiguration , 'name' > [ ] ) : Pick < typeof klaroConfiguration , 'services' > [ ] {
306+ return this . klaroConfig . services . filter ( service => ! servicesToHide . some ( el => el . name === service . name ) ) ;
279307 }
280308}
0 commit comments