UNPKG

@bemit/consent-ui

Version:

© 2022 [bemit](https://bemit.eu)

130 lines 3.99 kB
import { EventAware } from '@bemit/consent-ui/EventAware'; const consentState = { current: undefined }; export class ConsentUiState extends EventAware { initialized = false; hasChosen = false; acceptedVersion = undefined; tag = undefined; userPrefers = undefined; trackersState = {}; trackersActivatedHistory = {}; trackers = undefined; constructor(settings) { super(); this.version = settings.version; this.localKey = settings.localKey; this.trackers = settings.trackers; } init() { const tag = this.readTag(); if (tag) { this.hasChosen = Boolean(tag.prefers); this.acceptedVersion = tag.version; this.tag = tag.tag; this.userPrefers = tag.prefers; this.dispatchPreferences(); } this.initialized = true; } dispatchPreferences() { const userPrefers = this.userPrefers; if (userPrefers) { const trackerInfoRaw = this.trackers?.map((tracker, id) => { const trackerShouldBeActive = tracker.shouldBe(userPrefers); const currentStatus = this.trackersState[id]; return { status: trackerShouldBeActive ? currentStatus ? 'still-active' : 'to-activate' : !currentStatus ? 'still-inactive' : 'was-active', id, tracker }; }) || []; const trackerInfo = trackerInfoRaw.filter(ti => ti.status !== 'still-active' && ti.status !== 'still-inactive'); const trackerInfoToDestroy = trackerInfo.filter(ti => ti.status === 'was-active'); const trackerInfoToActivate = trackerInfo.filter(ti => ti.status === 'to-activate'); const needsRefresh = trackerInfoToDestroy.reduce((needsRefresh, ti) => { const destroyed = ti.tracker.destroy(); delete this.trackersState[ti.id]; return Boolean(needsRefresh || destroyed?.requiresRefresh); }, false); if (needsRefresh) { window.location.reload(true); return; } trackerInfoToActivate.forEach(ti => { ti.tracker.create(Boolean(this.trackersActivatedHistory[ti.id])); this.trackersState[ti.id] = true; this.trackersActivatedHistory[ti.id] = true; }); } } readTag() { const tagRaw = window.localStorage.getItem(this.localKey); if (!tagRaw) return undefined; let tag = window.localStorage.getItem(this.localKey); try { tag = JSON.parse(tagRaw); } catch (_e) {} return { version: tag?.version || undefined, tag: tag?.tag || undefined, prefers: tag?.version === this.version ? tag.prefers || undefined : undefined }; } giveConsent(preferences = {}) { this.hasChosen = true; this.acceptedVersion = this.version; this.userPrefers = preferences; this.persistConsent(); this.call('consent', this.version); this.dispatchPreferences(); } updateConsent(type, id, prefer) { if (!this.hasChosen || !this.userPrefers) return; const p = { ...this.userPrefers }; p[type] = { ...(p[type] || {}), [id]: prefer }; this.userPrefers = p; this.persistConsent(); this.call('consent', this.version); this.dispatchPreferences(); } persistConsent() { window.localStorage.setItem(this.localKey, JSON.stringify({ version: this.acceptedVersion, tag: this.tag, prefers: this.userPrefers })); } onConsent(cb) { const evtId = this.on('consent', cb); return () => this.off('consent', evtId); } toState() { return { ready: this.initialized, hasChosen: this.hasChosen, consent: this.acceptedVersion, tag: this.tag, userPrefers: this.userPrefers }; } } export const defineConsent = options => { const ui = new ConsentUiState({ version: options.version, localKey: options.localKey, trackers: options.trackers }); consentState.current = ui; return ui.init(); }; export const prepareConsent = defineConsent; export const consentUi = () => { return consentState.current; };