import pick from 'lodash/pick'; import sum from 'lodash/sum'; import {removeByIndex, replaceByIndex} from '../../../util/array'; import EventSelector from './event-selector'; import {LabelPart, MPEvent, SerializedCustomEvent} from './types'; export default class MPCustomEvent { public static fromSerializedCustomEvent({alternatives, name, id}: SerializedCustomEvent): MPCustomEvent { const eventSelectors = alternatives.map(alternative => EventSelector.fromAlternative(alternative)); return new MPCustomEvent({id, name, eventSelectors}); } public id?: number; public name: string; public eventSelectors: Array; public custom = true; constructor(options: Partial = {}) { const {id, name = ``, eventSelectors = null} = options; if (id) { this.id = id; } this.name = name; this.eventSelectors = eventSelectors ? eventSelectors.map(s => new EventSelector(s)) : [new EventSelector()]; } static get CUSTOM_EVENT_PREFIX(): string { return `$custom_event:`; } public getSerializedName(): string { return `${MPCustomEvent.CUSTOM_EVENT_PREFIX}${this.id}`; } public getLabelParts(): Array { return this.eventSelectors.reduce((parts, selector, index, arr) => { const operator = index !== arr.length - 1 ? [{label: `\nOR`, highlight: false}] : []; return [...parts, ...selector.getLabelParts(), ...operator]; }, []); } public toSerializedCustomEvent(): SerializedCustomEvent { const alternatives = this.eventSelectors .filter(eventSelector => eventSelector.isValid()) .map(eventSelector => eventSelector.toAlternative()); return { ...pick(this, [`id`]), alternatives, name: this.name.trim(), }; } public isValid(): boolean { return ( this.eventSelectors.some(eventSelector => eventSelector.isValid()) && this.eventSelectors.every((eventSelector, idx, arr) => eventSelector.isValid() || idx === arr.length - 1) ); } public addEventSelector(): MPCustomEvent { return new MPCustomEvent({ ...this.getAttrs(), eventSelectors: [...this.eventSelectors, new EventSelector()], }); } public updateEventSelectorAtIndex(eventSelector: EventSelector, idx: number): MPCustomEvent { return new MPCustomEvent({ ...this.getAttrs(), eventSelectors: replaceByIndex(this.eventSelectors, idx, eventSelector), }); } public updateEventAtIndex(event: MPEvent, idx: number): MPCustomEvent { const eventSelector = this.eventSelectors[idx].updateEvent(event); return new MPCustomEvent({ ...this.getAttrs(), eventSelectors: replaceByIndex(this.eventSelectors, idx, eventSelector), }); } public removeEventSelectorAtIndex(idx: number): MPCustomEvent { return new MPCustomEvent({ ...this.getAttrs(), eventSelectors: removeByIndex(this.eventSelectors, idx), }); } public updateName(name: string): MPCustomEvent { return new MPCustomEvent({...this.getAttrs(), name}); } public toTrackingData(): object { return { '# alternatives': this.eventSelectors.length, '# property filters': sum(this.eventSelectors.map(selector => selector.propertyFilters.length)), 'custom event id': this.id, 'name': this.name, }; } public getAttrs(): Partial { return pick(this, [ `eventSelectors`, `id`, `name`, ]); } }