import { Observable } from 'rxjs' import { combineEpics, ActionsObservable } from 'redux-observable' import { Store, Action } from 'redux' import * as PopupActions from '../popup/actions' import * as SettingsActions from '../settings/actions' import * as AuthActions from '../auth/actions' import * as AuthSelectors from '../auth/selectors' import { ISubmitLoginSuccess } from '../auth/interfaces' import * as actions from './actions' import * as api from './api' import { ready, userId, traits } from './selectors' import { ITrackSendEmailProperties, ISentEmail } from './interfaces' interface Analytics { identify: (userId: string, traits?: any) => void, track: (event: string, properties?: any) => void, reset: () => void, } declare const analytics: Analytics export const loginEpic = (action$: ActionsObservable, { getState }: Store) => { return action$.ofType(AuthActions.submitLoginSuccess.toString()) .filter(() => ready(getState())) .pluck('payload') .mergeMap(({ username }: ISubmitLoginSuccess) => { try { username && analytics.track('submitLoginSuccess', { username }) } catch (e) { console.error('track failed', e) } return Observable.empty() }) } export const identifyEpic = (action$: ActionsObservable, { getState }: Store) => { return action$.ofType(AuthActions.fetchUserSuccess.toString()) .filter(() => ready(getState())) .mergeMap(() => { try { analytics.identify(userId(getState()), traits(getState())) } catch (e) { console.error('identify failed', e) } return Observable.empty() }) } export const resetEpic = (action$: ActionsObservable) => { return action$.ofType(AuthActions.logout.toString()) .mergeMap(() => { try { analytics.reset() } catch (e) { console.error('reset failed', e) } return Observable.empty() }) } export const trackPopupEpic = (action$: ActionsObservable, { getState }: Store) => { return action$.ofType(PopupActions.popupOpen.toString()) .filter(() => ready(getState())) .mergeMap(() => { try { analytics.track('popup') } catch (e) { console.error('track failed', e) } return Observable.empty() }) } const generateTrackEpic = (param: string, action: Action) => (action$: ActionsObservable, { getState }: Store) => { return action$.ofType(action.toString()) .filter(() => ready(getState())) .pluck('payload') .mergeMap((properties: any) => { try { analytics.track(param, properties) } catch (e) { console.error('track failed', e) } return Observable.empty() }) } export const extractGmailIdFailedEpic = generateTrackEpic('extractGmailIdFailed', actions.extractGmailIdFailed) export const extensionInstalledEpic = generateTrackEpic('extensionInstalled', actions.extensionInstalled) export const socketErrorState = generateTrackEpic('socketErrorState', actions.socketErrorState) export const sentEmailEpic = (action$: ActionsObservable, { getState }: Store) => { return action$.ofType(actions.sentEmail.toString()) .filter(() => ready(getState())) .pluck('payload') .mergeMap((payload: ISentEmail) => { const accessToken = AuthSelectors.accessToken(getState()) try { analytics.track('sendEmail', { to: payload.endUserEmail } as ITrackSendEmailProperties) } catch (e) { console.error('track failed', e) } return api.sentEmail(payload, accessToken) .map(() => actions.sentEmailSuccess()) }) } export const trackSettingsEpic = (action$: ActionsObservable, { getState }: Store) => { return action$.ofType( PopupActions.popupOpen.toString(), SettingsActions.setSettingStatus.toString(), SettingsActions.updateDomainMuteList.toString(), SettingsActions.addEmailToMuteList.toString(), SettingsActions.removeEmailFromMuteList.toString(), SettingsActions.addDomainToMuteList.toString(), SettingsActions.removeDomainFromMuteList.toString(), SettingsActions.setInboxesToRunExtensionOn.toString(), ) .debounceTime(1000) .switchMap(() => { try { const state = getState() analytics.track('settingsChanged', state.settings) } catch (e) { console.error('track failed', e) } return Observable.empty() }) } export const epic = combineEpics( loginEpic, identifyEpic, resetEpic, trackPopupEpic, extractGmailIdFailedEpic, extensionInstalledEpic, sentEmailEpic, trackSettingsEpic, socketErrorState, )