UNPKG

@causalfoundry/js-sdk

Version:

Causal Foundry WEB SDK (JS/TS)

200 lines (170 loc) 5.31 kB
import { Event, EventTeaser, ExceptionObject } from "../core/typings"; import { debug } from "../logging"; import CfSender from "./CfSender"; import { ContentBlock } from "../modules/Navigation/typings"; import ImpressionsDetector from "./impressions"; import { ImpressionEventType } from "./impressions/typings"; import CfExceptionHandler from "./CfExceptionHandler"; import { getLocalStorageUserId } from "../drivers/CfSystem"; import { CatalogItemModel } from "../modules/typings"; import CfNetwork from "../drivers/network/CfNetwork"; import { isOnline } from "../drivers/network/helper"; export default class CfCore { private static instance: CfCore; private deviceId: string; private sender: CfSender; private isUsingAsInternalWrapper: boolean; private impressionDetectorClass; private impressionsDetectors: { [key: string]: ImpressionsDetector; } = {}; private defaultBlock; private debug; private currentBlock; private user_id = ""; private constructor( sender: CfSender, impressionDetector, debugging: boolean, defaultBlock: ContentBlock, deviceId: string, isUsingAsInternalWrapper: boolean ) { this.sender = sender; this.impressionDetectorClass = impressionDetector; this.deviceId = deviceId; this.defaultBlock = defaultBlock; this.debug = debug(debugging); this.isUsingAsInternalWrapper = isUsingAsInternalWrapper; } public static createInstance( sender: CfSender, impressionDetectorClass, debugging: boolean, defaultBlock: ContentBlock, deviceId: string, isUsingAsInternalWrapper: boolean ) { if (CfCore.instance) { return CfCore.instance; } CfCore.instance = new CfCore( sender, impressionDetectorClass, debugging, defaultBlock, deviceId, isUsingAsInternalWrapper ); return CfCore.instance; } public static getInstance(): CfCore { if (!CfCore.instance) { new CfExceptionHandler().throwAndLogError( "CfLog", "CfLog instance not created" ); } return CfCore.instance; } public login(userId: string) { this.user_id = userId; } private resolveModule(module: ContentBlock): ContentBlock { // logPageEvents are triggered automatically by the system. We do not // know whether the web application calls setCurrentBlock before or after that: const delta = 50; if (module === ContentBlock.Core) { // in this case the event could be triggered by several modules // so the SDK must decide which one must be included in the event // sent to server (i.e.: page or media events) if (this.currentBlock) { return this.currentBlock; } else { return this.defaultBlock; } } else { // specific module (i.e.: triggered by the ELearning module) return module; } } private resolveUserId( overWrittedUserId: string, user_id: string, device_id: string ): string { if (overWrittedUserId && overWrittedUserId.length !== 0) { return overWrittedUserId; } return user_id || getLocalStorageUserId() || device_id; } public async trackEvent( eventTeaser: EventTeaser, overWrittedUserId: string, sendNow: boolean, eventTime?: string ): Promise<void> { const event: Event = { ...eventTeaser, time: eventTime || new Date().toISOString(), }; // Ensure ctx exists and add ol property event.ctx = event.ctx || {}; event.ctx.__ol = isOnline(); this.sender.add( this.resolveUserId(overWrittedUserId, this.user_id, this.deviceId), this.deviceId, event, sendNow, this.isUsingAsInternalWrapper ); } public async trackCatalog(catalogItem: CatalogItemModel): Promise<void> { this.sender.addCatalogItem(catalogItem); } public startTrackingImpressions( impressionHandler, containerClassname, itemClassname ) { this.impressionsDetectors[containerClassname] = new this.impressionDetectorClass({ intersectionThreshold: 0.5 }); this.impressionsDetectors[containerClassname].on( ImpressionEventType.Impression, impressionHandler ); this.impressionsDetectors[containerClassname].start( containerClassname, itemClassname, {} ); } public stopTrackingImpressions(containerClassname) { if (!containerClassname) { Object.values(this.impressionsDetectors).forEach((detector) => detector.stop() ); return; } if (!this.impressionsDetectors[containerClassname]) { return; } this.impressionsDetectors[containerClassname].stop(); } public restartTrackingImpressions(containerClassname) { if (!containerClassname || !this.impressionsDetectors[containerClassname]) { console.error( "Impossible to restart impression to unknown containerClassname" ); throw new Error("unknown-container"); } this.impressionsDetectors[containerClassname].restart({}); } public setCurrentBlock(block: ContentBlock) { // the reason of this delay is that the page event is triggered // 10 miliseconds after it really happens to wait for the title setTimeout(() => { this.currentBlock = block; }, 15); } }