import isEqual from 'lodash/isEqual'; import isNil from 'lodash/isNil'; import isNumber from 'lodash/isNumber'; import merge from 'lodash/merge'; import pick from 'lodash/pick'; import {parseDate} from '../../../util/date'; import {ApiDateRange, DateRangeType, TimeUnit, TimeWindow} from './types'; const DATE_RANGE_ATTRIBUTES: Array = [ `type`, `from`, `to`, `window`, ]; export default class DateRange { public type: DateRangeType; public from?: string; public to?: string; public window?: TimeWindow; constructor(attributes: Partial = {}) { attributes = attributes || {}; this.type = attributes.type || DateRangeType.RelativeAfter; switch (this.type) { case DateRangeType.RelativeAfter: case DateRangeType.RelativeBefore: { if (attributes.window) { this.window = attributes.window; } else { this.window = this.getDefaultWindow(); } break; } case DateRangeType.On: case DateRangeType.Between: { this.from = attributes.from; this.to = attributes.to; break; } case DateRangeType.Since: { this.from = attributes.from; break; } default: { break; } } } public getDefaultWindow(): TimeWindow { return { unit: TimeUnit.Hour, value: 96, }; } public getDateRangeTypeOptions(): Array { return [ DateRangeType.RelativeAfter, DateRangeType.Between, DateRangeType.Since, DateRangeType.On, ]; } public getTimeUnitOptions(): Array { return [ TimeUnit.Hour, TimeUnit.Day, TimeUnit.Week, TimeUnit.Month, ]; } public getAttributes(): Partial { return pick(this, DATE_RANGE_ATTRIBUTES); } public mergeAttributes(attributes: Partial): this { return new (this.constructor as any)(merge(this.getAttributes(), attributes)); } public equals(otherRange: DateRange): boolean { return ( this.type === otherRange.type && this.from === otherRange.from && this.to === otherRange.to && isEqual(this.window, otherRange.window) ); } public isValid(): boolean { if (!this.getDateRangeTypeOptions().includes(this.type)) { return false; } switch (this.type) { case DateRangeType.On: case DateRangeType.Since: return !isNil(parseDate(this.from)); case DateRangeType.Between: return !isNil(parseDate(this.from)) && !isNil(parseDate(this.to)); case DateRangeType.RelativeBefore: case DateRangeType.RelativeAfter: { const {value, unit} = this.window; return this.getTimeUnitOptions().includes(unit) && isNumber(value) && value >= 1; } default: return false; } } public getApiFormat(): ApiDateRange { switch (this.type) { case DateRangeType.RelativeAfter: { return {window: this.window}; } case DateRangeType.RelativeBefore: { return {before: true, window: this.window}; } case DateRangeType.On: case DateRangeType.Between: { return { from_date: this.from, to_date: this.to, }; } case DateRangeType.Since: { return {from_date: this.from}; } default: { return null; } } } public getCalendarMaxDate(): string { return null; } }