@causalfoundry/js-sdk
Version:
Causal Foundry WEB SDK (JS/TS)
157 lines (133 loc) • 5.86 kB
text/typescript
import {CTAType, INudgesRepository, Nudge} from './repositories/nudges/typings'
import { EventEmitter } from 'events';
import { NotificationAction, NotificationDispatcher } from '../drivers/notifications/typings'
import { DateTime } from 'luxon'
import { INudgeManager, NudgeManagerAction } from './CfNudgeManager.typings';
import {ExceptionObject} from "./typings";
import {toISOLocal} from "../utils";
import CfCore from "./CfCore";
import CfExceptionHandler from "./CfExceptionHandler";
import Navigation from "../modules/Navigation/index";
import {NudgeAction} from "../modules/Navigation/typings";
import {NudgeScreenType} from "./commonTypes";
interface IndexedNudge {
[key: string]: Nudge
}
export default class NudgeManager extends EventEmitter implements INudgeManager {
private timersId = []
private notificationDispatcher
private nudgesRepository
private refreshInterval = 5 * 60 * 1000
private isOneTimeOnly = false
private nudgeScreenType = NudgeScreenType.None
private indexedNudges: IndexedNudge = {}
public constructor(
userId: string,
notificationDispatcher: NotificationDispatcher,
nudgesRepository: INudgesRepository,
nudgeScreenType = NudgeScreenType.None,
isOneTimeOnly = false,
refreshInterval = 5 * 60 * 1000
) {
super()
this.notificationDispatcher = notificationDispatcher
this.nudgesRepository = nudgesRepository
this.refreshInterval = refreshInterval
this.nudgeScreenType = nudgeScreenType
this.isOneTimeOnly = isOneTimeOnly
/*
- nudges are retrieved periodically, each 5min.
- in the future this timeout will be configurable
- dispatched_at will be:
- current time less 1 hour the first time
- time of last shown nudge, if exists, or current time next times
*/
this.notificationDispatcher.on(NotificationAction.Open, (id) => {
this.emit(NudgeManagerAction.Open, this.indexedNudges[id].ref, this.indexedNudges[id].time)
if (!this.indexedNudges[id]) {
return
}
const hasActions = () => {
return (this.indexedNudges[id].nd.cta !== CTAType.None &&
this.indexedNudges[id].extra && this.indexedNudges[id].extra.item_pair &&
this.indexedNudges[id].extra.item_pair.ids.length == 2 &&
this.indexedNudges[id].nd.message.tmpl_cfg &&
this.indexedNudges[id].nd.message.tmpl_cfg.item_pair_cfg &&
this.indexedNudges[id].nd.message.tmpl_cfg.tmpl_type === "item_pair" &&
this.indexedNudges[id].extra.item_pair.ids.length === 2)
}
if (!hasActions()) {
return
}
const ctaObject = {
type: this.indexedNudges[id].nd.cta.toLowerCase(),
cta_resource: {
type: this.indexedNudges[id].nd.message.tmpl_cfg.item_pair_cfg.item_type,
id: this.indexedNudges[id].extra.item_pair.ids[0]
}
}
this.emit(
NudgeManagerAction.Action,
ctaObject)
})
this.notificationDispatcher.on(NotificationAction.Discard, id => {
this.emit(NudgeManagerAction.Discard, this.indexedNudges[id].ref, this.indexedNudges[id].time)
})
this.notificationDispatcher.on(NotificationAction.Block, id => {
this.emit(NudgeManagerAction.Block, this.indexedNudges[id].ref, this.indexedNudges[id].time)
})
this.notificationDispatcher.on(NotificationAction.Shown, id => {
this.emit(NudgeManagerAction.Shown, this.indexedNudges[id].ref, this.indexedNudges[id].time)
})
const oneHourAgo = new Date()
oneHourAgo.setHours(oneHourAgo.getHours() - 1)
// get nudge item:
this.fetchNudges(userId, this.nudgeScreenType)
if(!this.isOneTimeOnly){
setInterval(() => {
this.fetchNudges(userId, this.nudgeScreenType)
}, this.refreshInterval)
}
}
private async fetchNudges(userId: string, nudgeScreenType : NudgeScreenType) {
let nudges;
try {
nudges = await this.nudgesRepository.getNudges(userId, nudgeScreenType)
} catch (e) {
console.error('Error fetching nudges: ', e)
return
}
nudges
// .filter(({ ref }) => {
// const alreadyShown = this.nudgesRepository.haveBeenAlreadyShown(ref)
// return !alreadyShown
// })
.forEach((nudge, index) => {
nudge.internalId = index
this.indexedNudges[index] = nudge
this.processNudge(nudge)
})
}
private processNudge(nudge: Nudge) {
if(!nudge.expire_at){
nudge.expire_at = "0001-01-01T00:00:00Z"
}
const expirationNotDefined = nudge.expire_at === "0001-01-01T00:00:00Z"
const notExpired = nudge.expire_at > new Date().toISOString()
if (nudge.nd.message.tmpl_cfg.tmpl_type !== "item_pair" &&
nudge.nd.message.tmpl_cfg.tmpl_type !== "traits" &&
nudge.nd.message.tmpl_cfg.tmpl_type !== "") {
new CfExceptionHandler().throwNudgeException("Invalid template type provided", nudge)
return
}
if (notExpired || expirationNotDefined) {
this.notificationDispatcher.show(nudge, nudge.internalId)
}else{
Navigation.logPushNotificationEvent({
ref: nudge.ref,
response: NudgeAction.Expired,
time: nudge.time
})
}
}
}