1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import multiMonthPlugin from '@fullcalendar/multimonth';
import { makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { dateRangeStrToDates } from '../../../../Utils';
import { Doc } from '../../../../fields/Doc';
import { StrCast } from '../../../../fields/Types';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { FieldView, FieldViewProps } from '../FieldView';
type CalendarView = 'month' | 'multi-month' | 'week';
@observer
export class CalendarBox extends ViewBoxBaseComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string = 'calendar') {
return FieldView.LayoutString(CalendarBox, fieldKey);
}
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
}
componentDidMount(): void {}
componentWillUnmount(): void {}
_calendarRef = React.createRef<HTMLElement>();
get dateRangeStr() {
return StrCast(this.Document.date_range);
}
// Choose a calendar view based on the date range
get calendarViewType(): CalendarView {
const [fromDate, toDate] = dateRangeStrToDates(this.dateRangeStr);
if (fromDate.getFullYear() !== toDate.getFullYear() || fromDate.getMonth() !== toDate.getMonth()) return 'multi-month';
if (Math.abs(fromDate.getDay() - toDate.getDay()) > 7) return 'month';
return 'week';
}
get calendarStartDate() {
return this.dateRangeStr.split('|')[0];
}
get calendarToDate() {
return this.dateRangeStr.split('|')[1];
}
get childDocs(): Doc[] {
return this.childDocs; // get all sub docs for a calendar
}
docBackgroundColor(type: string): string {
// TODO: Return a different color based on the event type
return 'blue';
}
get calendarEvents(): EventSourceInput | undefined {
if (this.childDocs.length === 0) return undefined;
return this.childDocs.map((doc, idx) => {
const docTitle = StrCast(doc.title);
const docDateRange = StrCast(doc.date_range);
const [startDate, endDate] = dateRangeStrToDates(docDateRange);
const docType = doc.type;
const docDescription = doc.description ? StrCast(doc.description) : '';
return {
title: docTitle,
start: startDate,
end: endDate,
allDay: false,
classNames: [StrCast(docType)], // will determine the style
editable: false, // subject to change in the future
backgroundColor: this.docBackgroundColor(StrCast(doc.type)),
color: 'white',
extendedProps: {
description: docDescription,
},
};
});
}
handleEventClick = (arg: EventClickArg) => {
// TODO: open popover with event description, option to open CalendarManager and change event date, delete event, etc.
};
calendarEl: HTMLElement = document.getElementById('calendar-box-v1')!;
// https://fullcalendar.io
get calendar() {
return new Calendar(this.calendarEl, {
plugins: [this.calendarViewType === 'multi-month' ? multiMonthPlugin : dayGridPlugin],
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek',
},
initialDate: this.calendarStartDate,
navLinks: true,
editable: false,
displayEventTime: false,
displayEventEnd: false,
events: this.calendarEvents,
eventClick: this.handleEventClick,
});
}
render() {
return (
<div className="calendar-box-conatiner">
<div id="calendar-box-v1"></div>
</div>
);
}
}
|