novo-elements
Version:
Bullhorn's NOVO Element Repository for Angular 2
212 lines (185 loc) • 6.04 kB
text/typescript
import { Component, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef, OnInit, OnDestroy, LOCALE_ID, Inject, TemplateRef } from '@angular/core';
import { CalendarEvent, WeekDay, MonthView, MonthViewDay, CalendarEventTimesChangedEvent, getWeekViewHeader, getMonthView } from '../../../utils/calendar-utils/CalendarUtils';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import * as dateFns from 'date-fns';
/**
* Shows all events on a given month. Example usage:
*
* ```
* <novo-calendar-month-view
* [viewDate]="viewDate"
* [events]="events">
* </novo-calendar-month-view>
* ```
*/
export class NovoCalendarMonthViewElement implements OnChanges, OnInit, OnDestroy {
/**
* The current view date
*/
viewDate: Date;
/**
* An array of events to display on view
*/
events: CalendarEvent[] = [];
/**
* An array of day indexes (0 = sunday, 1 = monday etc) that will be hidden on the view
*/
excludeDays: number[] = [];
/**
* A function that will be called before each cell is rendered. The first argument will contain the calendar cell.
* If you add the `cssClass` property to the cell it will add that class to the cell in the template
*/
dayModifier: Function;
/**
* An observable that when emitted on will re-render the current view
*/
refresh: Subject<any>;
/**
* The locale used to format dates
*/
locale: string = 'en-US';
/**
* The placement of the event tooltip
*/
tooltipPosition: string = 'top';
/**
* The start number of the week
*/
weekStartsOn: number;
/**
* A custom template to use to replace the header
*/
headerTemplate: TemplateRef<any>;
/**
* A custom template to use to replace the day cell
*/
cellTemplate: TemplateRef<any>;
/**
* Called when the day cell is clicked
*/
dayClicked: EventEmitter<{ day: MonthViewDay }> = new EventEmitter<{ day: MonthViewDay }>();
/**
* Called when the event title is clicked
*/
eventClicked: EventEmitter<{ event: CalendarEvent }> = new EventEmitter<{ event: CalendarEvent }>();
/**
* Called when an event is dragged and dropped
*/
eventTimesChanged: EventEmitter<CalendarEventTimesChangedEvent> = new EventEmitter<CalendarEventTimesChangedEvent>();
viewDateChange: EventEmitter<Date> = new EventEmitter<Date>();
/**
* @hidden
*/
columnHeaders: WeekDay[];
/**
* @hidden
*/
view: MonthView;
/**
* @hidden
*/
refreshSubscription: Subscription;
/**
* @hidden
*/
constructor(private cdr: ChangeDetectorRef, locale: string) {
this.locale = locale;
}
/**
* @hidden
*/
ngOnInit(): void {
if (this.refresh) {
this.refreshSubscription = this.refresh.subscribe(() => {
this.refreshAll();
this.cdr.markForCheck();
});
}
}
/**
* @hidden
*/
ngOnChanges(changes: any): void {
if (changes.viewDate || changes.excludeDays) {
this.refreshHeader();
}
if (changes.viewDate || changes.events || changes.excludeDays) {
this.refreshBody();
}
}
/**
* @hidden
*/
ngOnDestroy(): void {
if (this.refreshSubscription) {
this.refreshSubscription.unsubscribe();
}
}
/**
* @hidden
*/
eventDropped(day: MonthViewDay, event: CalendarEvent): void {
const year: number = dateFns.getYear(day.date);
const month: number = dateFns.getMonth(day.date);
const date: number = dateFns.getDate(day.date);
const newStart: Date = dateFns.setYear(dateFns.setMonth(dateFns.setDate(event.start, date), month), year);
let newEnd: Date;
if (event.end) {
const secondsDiff: number = dateFns.differenceInSeconds(newStart, event.start);
newEnd = dateFns.addSeconds(event.end, secondsDiff);
}
this.eventTimesChanged.emit({ event, newStart, newEnd });
}
private refreshHeader(): void {
this.columnHeaders = getWeekViewHeader({
viewDate: this.viewDate,
weekStartsOn: this.weekStartsOn,
excluded: this.excludeDays
});
}
private refreshBody(): void {
this.view = getMonthView({
events: this.events,
viewDate: this.viewDate,
weekStartsOn: this.weekStartsOn,
excluded: this.excludeDays
});
if (this.dayModifier) {
this.view.days.forEach(day => this.dayModifier(day));
}
}
public refreshAll(): void {
this.refreshHeader();
this.refreshBody();
this.viewDateChange.emit(this.viewDate);
}
}