import { BehaviorSubject, combineLatest, debounceTime, map, Observable } from 'rxjs'; import { CookieHandler } from '../cookie-handler'; export type BeslistConsentType = 'necessary' | 'functional' | 'analytics' | 'performance' | 'marketing'; export type ConsentTypeMapping = { necessary: T, functional: T, analytics: T, performance: T, marketing: T, } export type ConsentStatus = 'granted' | 'denied'; export interface ConsentStatusData { necessary?: ConsentStatus, functional?: ConsentStatus, analytics?: ConsentStatus, performance?: ConsentStatus, marketing?: ConsentStatus, } export abstract class AbstractConsentHandler { public currentConsent: Observable<{ consent: ConsentStatusData, handler: string, }>; public currentNecessaryConsent: BehaviorSubject; public currentFunctionalConsent: BehaviorSubject; public currentAnalyticsConsent: BehaviorSubject; public currentPerformanceConsent: BehaviorSubject; public currentMarketingConsent: BehaviorSubject; constructor() { const initialConsent = this.getInitialConsent(); this.currentNecessaryConsent = new BehaviorSubject(initialConsent.necessary || 'denied'); this.currentFunctionalConsent = new BehaviorSubject(initialConsent.functional || 'denied'); this.currentAnalyticsConsent = new BehaviorSubject(initialConsent.analytics || 'denied'); this.currentPerformanceConsent = new BehaviorSubject(initialConsent.performance || 'denied'); this.currentMarketingConsent = new BehaviorSubject(initialConsent.marketing || 'denied'); this.currentConsent = combineLatest([ this.currentNecessaryConsent, this.currentFunctionalConsent, this.currentAnalyticsConsent, this.currentPerformanceConsent, this.currentMarketingConsent, ]).pipe( debounceTime(1), map(([necessary, functional, analytics, performance, marketing]) => { return { consent: { necessary: necessary, functional: functional, analytics: analytics, performance: performance, marketing: marketing, }, handler: this.getConsentHandlerName(), }; }) ); } public initialize(): void { this.initializeConsentUpdateListener(); } public abstract initializeConsentUpdateListener(): void; protected abstract getInitialConsent(): ConsentStatusData; protected abstract getConsentHandlerName(): string; protected abstract getConsentTypeMapping(): ConsentTypeMapping; protected abstract getCookieNameMapping(): ConsentTypeMapping; protected abstract parseConsentCookieValue(consentType: BeslistConsentType, cookieValue: string): boolean | undefined; protected updateConsent(consentData: ConsentStatusData): void { if (consentData.necessary) { this.currentNecessaryConsent.next(consentData.necessary); } if (consentData.functional) { this.currentFunctionalConsent.next(consentData.functional); } if (consentData.analytics) { this.currentAnalyticsConsent.next(consentData.analytics); } if (consentData.performance) { this.currentPerformanceConsent.next(consentData.performance); } if (consentData.marketing) { this.currentMarketingConsent.next(consentData.marketing); } } protected mapConsentType(consentType: BeslistConsentType): string { return this.getConsentTypeMapping()[consentType]; } protected mapCookieName(consentType: BeslistConsentType): string | undefined { return this.getCookieNameMapping()[consentType]; } protected getConsentFromCookie(consentType: BeslistConsentType): boolean | undefined { const cookieName = this.mapCookieName(consentType); if (!cookieName) { return undefined; } const consentCookieValue = CookieHandler.getCookie(cookieName); if (!consentCookieValue) { return undefined; } return this.parseConsentCookieValue(consentType, consentCookieValue); } }