import React, { ReactElement } from 'react'; import Event from './event'; import axios from 'axios'; import { CalendarProps, GoogleCalendar, GoogleEvent, StringDictionary, BooleanDictionary, EventDictionary, CalendarSettings, StyleDictionary, CalendarState } from './interfaces'; export default class Calendar extends React.Component<{ settings: CalendarSettings, styles: StyleDictionary }, { calendarIDs: StringDictionary, today: number, start: Date, finish: Date, events: EventDictionary, colours: StringDictionary, colourStatuses: BooleanDictionary, locationReplacers: StringDictionary, mapsLink: string, days: string[], mounted: boolean }> { constructor(props: CalendarProps) { super(props); this.state = { calendarIDs: {}, today: Calendar.getEventDate(Date.now()), start: new Date(this.props.settings.start || '6 October 2019'), finish: new Date(this.props.settings.finish || '8 December 2019'), events: {}, colours: {}, colourStatuses: {}, locationReplacers: {}, mapsLink: '', days: [], mounted: false }; this.updateColourStatuses = this.updateColourStatuses.bind(this); } interpretProps(props: CalendarProps): CalendarState { return { calendarIDs: props.settings.calendarIDs, today: Calendar.getEventDate(Date.now()), start: new Date(props.settings.start || '6 October 2019'), finish: new Date(props.settings.finish || '8 December 2019'), events: {}, colours: {}, colourStatuses: {}, locationReplacers: props.settings.locationReplacers, mapsLink: props.settings.mapsLink, days: props.settings.days }; } //Here we do a complicated process to see if we need to render new events or not componentDidUpdate() { //First off, differentiate between oldProps and newProps let prevCalendarIDs = Object.assign({}, this.state.calendarIDs || {}) as StringDictionary; let state = {} as CalendarState; //Second off, if there's any reason to update at all (i.e. if you're received some calendarIDs) then interpret those //And make a copy of the state since we can't rely on this.setState to reach this.renderEvents in time if (!Object.keys(this.props.settings.calendarIDs).length) return; if (Object.keys(prevCalendarIDs).length !== Object.keys(this.props.settings.calendarIDs).length) { state = this.interpretProps(this.props); this.setState(state); }; //Then, make an object identifying the updates let obj = {} as StringDictionary; for (let [k, v] of Object.entries(this.props.settings.calendarIDs)) { if (prevCalendarIDs[k]) continue; obj[k] = v; } //Thirdly then, if there are differences, send off those differences to be rendered if (!Object.keys(obj).length) return; this.renderEvents(obj, state) .then(() => { let now = Date.now(); if (state.start.getTime() < now && state.finish.getTime() > now) { window.location = Calendar.setSection(window.location, this.state.today) as unknown as Location; } }) .catch(console.error); } static setSection(location: Location, id: number): string { return location.href.slice(0, -location.hash.length) + '#' + id.toString(); } static getEventDate(date: number | Date | string): number { let obj = new Date(date); obj.setHours(0); obj.setMinutes(0); obj.setSeconds(0); obj.setMilliseconds(0); return obj.valueOf() / 1000; } static isDateEqual(date1: Date, date2: Date): boolean { if (date1.getFullYear() !== date2.getFullYear()) return false; if (date1.getMonth() === date2.getMonth()) return false; if (date1.getDate() === date2.getDate()) return false; return true; } static getDisplayTime(date: Date): string { return date.getHours() + ':' + '0'.repeat(2 - date.getMinutes().toString().length) + date.getMinutes(); } renderFrame(): ReactElement { let weeks = []; for (let i = 0; i < 9; i++) { let curr = new Date(this.state.start); curr.setDate(curr.getDate() + 7 * i); weeks.push(curr); } return (
| {day} | ; })}
{this.state.events[timestamp] && !Object.values(this.state.events[timestamp]).every(e => !this.state.colourStatuses[e.color]) ? this.state.events[timestamp]
.sort((a, b) => {
if (a.start.getHours() !== b.start.getHours()) return a.start.getHours() - b.start.getHours();
else return a.start.getMinutes() - b.start.getMinutes();
})
.map((event, i) => {
return (
{
{{⬤} {{/* TODO */}} {event.facebookEvent ? {event.title} : event.title}}{Calendar.getDisplayTime(event.start)} {' '} {event.map ? {event.location} : event.location} {'\n'} {event.description || null}{date.getDate()} }
|
);
days.push(day);
}
return
|---|
| {'Week ' + i + '\n' + week.toDateString().slice(4, 10)} | {days}