You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.8 KiB
TypeScript

import * as React from 'react';
import BigCalendar, { View } from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import * as moment from 'moment';
import * as ICAL from 'ical.js';
import { EventType } from '../pim-types';
import './Calendar.css';
const calendarLocalizer = BigCalendar.momentLocalizer(moment);
const MAX_RECURRENCE_DATE = ICAL.Time.now();
MAX_RECURRENCE_DATE.adjust(800, 0, 0, 0);
function eventPropGetter(event: EventType) {
return {
style: {
backgroundColor: event.color,
},
};
}
function agendaHeaderFormat(date: {start: Date, end: Date}, culture: string, localizer: any) {
const format = 'll';
return localizer.format(date.start, format) + ' - ' + localizer.format(date.end, format);
}
interface PropsType {
entries: EventType[];
onItemClick: (contact: EventType) => void;
onSlotClick?: (start: Date, end: Date) => void;
}
class Calendar extends React.PureComponent<PropsType> {
public state: {
currentDate?: Date;
view?: View;
};
constructor(props: any) {
super(props);
this.state = {};
this.onNavigate = this.onNavigate.bind(this);
this.onView = this.onView.bind(this);
this.slotClicked = this.slotClicked.bind(this);
}
public render() {
const entries = [] as EventType[];
this.props.entries.forEach((event) => {
entries.push(event);
if (event.isRecurring()) {
const recur = event.iterator();
let next = recur.next(); // Skip the first one
while ((next = recur.next())) {
if (next.compare(MAX_RECURRENCE_DATE) > 0) {
break;
}
const shift = next.subtractDateTz(event.startDate);
const ev = event.clone();
ev.startDate.addDuration(shift);
ev.endDate.addDuration(shift);
entries.push(ev);
}
}
});
return (
<div style={{width: '100%', height: 'calc(100vh - 230px)', minHeight: 500}}>
<BigCalendar
defaultDate={new Date()}
localizer={calendarLocalizer}
events={entries}
selectable
onSelectEvent={this.props.onItemClick as any}
onSelectSlot={this.slotClicked as any}
formats={{agendaHeaderFormat: agendaHeaderFormat as any}}
eventPropGetter={eventPropGetter}
date={this.state.currentDate}
onNavigate={this.onNavigate}
view={this.state.view}
onView={this.onView}
/>
</div>
);
}
private onNavigate(currentDate: Date) {
this.setState({currentDate});
}
private onView(view: string) {
this.setState({view});
}
private slotClicked(slotInfo: {start: Date, end: Date}) {
if (this.props.onSlotClick) {
this.props.onSlotClick(slotInfo.start, slotInfo.end);
}
}
}
export default Calendar;