import { Injectable } from '@angular/core'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/map'; import { Observable } from 'rxjs/Observable'; import { getFullYear, getMonth } from '../../chronos/utils/date-getters'; import { BsDatepickerAbstractComponent } from '../base/bs-datepicker-container'; import { BsDatepickerConfig } from '../bs-datepicker.config'; import { BsDatepickerViewMode, BsNavigationEvent, CalendarCellViewModel, CellHoverEvent, DatepickerRenderOptions, DaysCalendarViewModel, DayViewModel, MonthsCalendarViewModel, YearsCalendarViewModel } from '../models/index'; import { BsDatepickerActions } from './bs-datepicker.actions'; import { BsDatepickerStore } from './bs-datepicker.store'; import { Subscription } from 'rxjs/Subscription'; import { BsLocaleService } from '../bs-locale.service'; @Injectable() export class BsDatepickerEffects { viewMode: Observable; daysCalendar: Observable; monthsCalendar: Observable; yearsCalendar: Observable; options: Observable; private _store: BsDatepickerStore; private _subs: Subscription[] = []; constructor(private _actions: BsDatepickerActions, private _localeService: BsLocaleService) {} init(_bsDatepickerStore: BsDatepickerStore): BsDatepickerEffects { this._store = _bsDatepickerStore; return this; } /** setters */ setValue(value: Date): void { this._store.dispatch(this._actions.select(value)); } setRangeValue(value: Date[]): void { this._store.dispatch(this._actions.selectRange(value)); } setMinDate(value: Date): BsDatepickerEffects { this._store.dispatch(this._actions.minDate(value)); return this; } setMaxDate(value: Date): BsDatepickerEffects { this._store.dispatch(this._actions.maxDate(value)); return this; } setDisabled(value: boolean): BsDatepickerEffects { this._store.dispatch(this._actions.isDisabled(value)); return this; } /* Set rendering options */ setOptions(_config: BsDatepickerConfig): BsDatepickerEffects { const _options = Object.assign({locale: this._localeService.currentLocale}, _config); this._store.dispatch(this._actions.setOptions(_options)); return this; } /** view to mode bindings */ setBindings(container: BsDatepickerAbstractComponent): BsDatepickerEffects { container.daysCalendar = this._store .select(state => state.flaggedMonths) .filter(months => !!months); // month calendar container.monthsCalendar = this._store .select(state => state.flaggedMonthsCalendar) .filter(months => !!months); // year calendar container.yearsCalendar = this._store .select(state => state.yearsCalendarFlagged) .filter(years => !!years); container.viewMode = this._store.select(state => state.view.mode); container.options = this._store .select(state => state.showWeekNumbers) .map(showWeekNumbers => ({showWeekNumbers})); return this; } /** event handlers */ setEventHandlers(container: BsDatepickerAbstractComponent): BsDatepickerEffects { container.setViewMode = (event: BsDatepickerViewMode): void => { this._store.dispatch(this._actions.changeViewMode(event)); }; container.navigateTo = (event: BsNavigationEvent): void => { this._store.dispatch(this._actions.navigateStep(event.step)); }; container.dayHoverHandler = (event: CellHoverEvent): void => { const _cell = event.cell as DayViewModel; if (_cell.isOtherMonth || _cell.isDisabled) { return; } this._store.dispatch(this._actions.hoverDay(event)); _cell.isHovered = event.isHovered; }; container.monthHoverHandler = (event: CellHoverEvent): void => { event.cell.isHovered = event.isHovered; }; container.yearHoverHandler = (event: CellHoverEvent): void => { event.cell.isHovered = event.isHovered; }; /** select handlers */ // container.daySelectHandler = (day: DayViewModel): void => { // if (day.isOtherMonth || day.isDisabled) { // return; // } // this._store.dispatch(this._actions.select(day.date)); // }; container.monthSelectHandler = (event: CalendarCellViewModel): void => { if (event.isDisabled) { return; } this._store.dispatch( this._actions.navigateTo({ unit: {month: getMonth(event.date)}, viewMode: 'day' }) ); }; container.yearSelectHandler = (event: CalendarCellViewModel): void => { if (event.isDisabled) { return; } this._store.dispatch( this._actions.navigateTo({ unit: {year: getFullYear(event.date)}, viewMode: 'month' }) ); }; return this; } registerDatepickerSideEffects(): BsDatepickerEffects { this._subs.push( this._store.select(state => state.view).subscribe(view => { this._store.dispatch(this._actions.calculate()); }) ); // format calendar values on month model change this._subs.push( this._store .select(state => state.monthsModel) .filter(monthModel => !!monthModel) .subscribe(month => this._store.dispatch(this._actions.format())) ); // flag day values this._subs.push( this._store .select(state => state.formattedMonths) .filter(month => !!month) .subscribe(month => this._store.dispatch(this._actions.flag())) ); // flag day values this._subs.push( this._store .select(state => state.selectedDate) .filter(selectedDate => !!selectedDate) .subscribe(selectedDate => this._store.dispatch(this._actions.flag())) ); // flag for date range picker this._subs.push( this._store .select(state => state.selectedRange) .filter(selectedRange => !!selectedRange) .subscribe(selectedRange => this._store.dispatch(this._actions.flag())) ); // monthsCalendar this._subs.push( this._store .select(state => state.monthsCalendar) .subscribe(() => this._store.dispatch(this._actions.flag())) ); // years calendar this._subs.push( this._store .select(state => state.yearsCalendarModel) .filter(state => !!state) .subscribe(() => this._store.dispatch(this._actions.flag())) ); // on hover this._subs.push( this._store .select(state => state.hoveredDate) .filter(hoveredDate => !!hoveredDate) .subscribe(hoveredDate => this._store.dispatch(this._actions.flag())) ); // on locale change this._subs.push( this._localeService.localeChange .subscribe(locale => this._store.dispatch(this._actions.setLocale(locale))) ) return this; } destroy(): void { for (const sub of this._subs) { sub.unsubscribe(); } } }