aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/calendarBox
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/calendarBox')
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
new file mode 100644
index 000000000..748c3322e
--- /dev/null
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -0,0 +1,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>
+ );
+ }
+}