From df5217eea01b6ee3ce03ceede030306d05f19c58 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 4 Sep 2024 17:48:13 -0400
Subject: updated calendars to support times of events and to render evdnts at
 the correct time.

---
 src/client/views/nodes/calendarBox/CalendarBox.tsx | 85 ++++++++++++++++------
 1 file changed, 61 insertions(+), 24 deletions(-)

(limited to 'src/client/views/nodes/calendarBox/CalendarBox.tsx')

diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 0d50f3382..9452cc10a 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -1,4 +1,4 @@
-import { Calendar, EventSourceInput } from '@fullcalendar/core';
+import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core';
 import dayGridPlugin from '@fullcalendar/daygrid';
 import multiMonthPlugin from '@fullcalendar/multimonth';
 import timeGrid from '@fullcalendar/timegrid';
@@ -7,11 +7,17 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { dateRangeStrToDates } from '../../../../ClientUtils';
 import { Doc } from '../../../../fields/Doc';
-import { NumCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { CollectionSubView, SubCollectionViewProps } from '../../collections/CollectionSubView';
 import './CalendarBox.scss';
+import { Id } from '../../../../fields/FieldSymbols';
+import { DocServer } from '../../../DocServer';
+import { DocumentView } from '../DocumentView';
+import { OpenWhere } from '../OpenWhere';
+import { DragManager } from '../../../util/DragManager';
+import { DocData } from '../../../../fields/DocSymbols';
 
-type CalendarView = 'month' | 'multi-month' | 'week';
+type CalendarView = 'multiMonth' | 'dayGridMonth' | 'timeGridWeek' | 'timeGridDay';
 
 @observer
 export class CalendarBox extends CollectionSubView() {
@@ -27,8 +33,10 @@ export class CalendarBox extends CollectionSubView() {
     }
 
     @observable _multiMonth = 0;
+    isMultiMonth: boolean | undefined;
 
     componentDidMount(): void {
+        this._props.setContentViewBox?.(this);
         this._eventsDisposer = reaction(
             () => this.calendarEvents,
             events => this._calendar?.setOption('events', events),
@@ -42,14 +50,14 @@ export class CalendarBox extends CollectionSubView() {
     @computed get calendarEvents(): EventSourceInput | undefined {
         return this.childDocs.map(doc => {
             const { startDate: start, endDate: end } = dateRangeStrToDates(StrCast(doc.date_range));
-
             return {
                 title: StrCast(doc.title),
                 start,
                 end,
+                groupId: doc[Id],
                 startEditable: true,
                 endEditable: true,
-                allDay: false,
+                allDay: BoolCast(doc.allDay),
                 classNames: ['mother'], // will determine the style
                 editable: true, // subject to change in the future
                 backgroundColor: this.eventToColor(doc),
@@ -67,22 +75,40 @@ export class CalendarBox extends CollectionSubView() {
 
     // Choose a calendar view based on the date range
     @computed get calendarViewType(): CalendarView {
+        if (this.dataDoc[this.fieldKey + '_calendarType']) return StrCast(this.dataDoc[this.fieldKey + '_calendarType']) as CalendarView;
+        if (this.isMultiMonth) return 'multiMonth';
         const { startDate, endDate } = this.dateRangeStrDates;
-
-        if (startDate.getFullYear() !== endDate.getFullYear() || startDate.getMonth() !== endDate.getMonth()) return 'multi-month';
-
-        if (Math.abs(startDate.getDay() - endDate.getDay()) > 7) return 'month';
-        return 'week';
+        if (startDate.getFullYear() !== endDate.getFullYear() || startDate.getMonth() !== endDate.getMonth()) return 'multiMonth';
+        if (Math.abs(startDate.getDay() - endDate.getDay()) > 7) return 'dayGridMonth';
+        return 'timeGridWeek';
     }
 
+    // TODO: Return a different color based on the event type
     eventToColor(event: Doc): string {
-        // TODO: Return a different color based on the event type
-        console.log(event.title);
         return 'blue';
     }
 
-    handleEventClick = (/* arg: EventClickArg */) => {
-        // TODO: open popover with event description, option to open CalendarManager and change event date, delete event, etc.
+    internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData) {
+        if (!super.onInternalDrop(e, de)) return false;
+        de.complete.docDragData?.droppedDocuments.forEach(doc => {
+            const today = new Date().toISOString();
+            if (!doc.date_range) doc[DocData].date_range = `${today}|${today}`;
+        });
+        return true;
+    }
+
+    onInternalDrop = (e: Event, de: DragManager.DropEvent): boolean => {
+        if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData);
+        return false;
+    };
+
+    handleEventClick = (arg: EventClickArg) => {
+        const doc = DocServer.GetCachedRefField(arg.event._def.groupId ?? '');
+        DocumentView.DeselectAll();
+        if (doc) {
+            DocumentView.showDocument(doc, { openLocation: OpenWhere.lightboxAlways });
+            arg.jsEvent.stopPropagation();
+        }
     };
 
     // https://fullcalendar.io
@@ -94,8 +120,9 @@ export class CalendarBox extends CollectionSubView() {
                   headerToolbar: {
                       left: 'prev,next today',
                       center: 'title',
-                      right: 'multiMonth,dayGridMonth,timeGridWeek,timeGridDay',
+                      right: 'multiMonth dayGridMonth timeGridWeek timeGridDay',
                   },
+                  initialView: this.calendarViewType === 'multiMonth' ? undefined : this.calendarViewType,
                   initialDate: this.dateRangeStrDates.startDate,
                   navLinks: true,
                   editable: false,
@@ -110,19 +137,29 @@ export class CalendarBox extends CollectionSubView() {
 
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
     render() {
-        this._multiMonth;
         return (
             <div
-                key={this._multiMonth}
+                key={StrCast(this.dataDoc[this.fieldKey + '_calendarType'])}
                 className="calendarBox"
-                onPointerDown={action(e =>
-                    setTimeout(() => {
-                        if ((e.nativeEvent.target as HTMLButtonElement)?.className?.includes('multiMonth-button')) {
-                            this._multiMonth = this._multiMonth + 1;
-                        }
-                    })
-                )}
+                onPointerDown={e =>
+                    setTimeout(
+                        action(() => {
+                            const cname = (e.nativeEvent.target as HTMLButtonElement)?.className ?? '';
+                            if (cname.includes('multiMonth')) this.dataDoc[this.fieldKey + '_calendarType'] = 'multiMonth';
+                            if (cname.includes('dayGridMonth')) this.dataDoc[this.fieldKey + '_calendarType'] = 'dayGridMonth';
+                            if (cname.includes('timeGridWeek')) this.dataDoc[this.fieldKey + '_calendarType'] = 'timeGridWeek';
+                            if (cname.includes('timeGridDay')) this.dataDoc[this.fieldKey + '_calendarType'] = 'timeGridDay';
+                        })
+                    )
+                }
+                style={{
+                    width: this._props.PanelWidth() / this._props.ScreenToLocalTransform().Scale,
+                    height: this._props.PanelHeight() / this._props.ScreenToLocalTransform().Scale,
+                    transform: `scale(${this._props.ScreenToLocalTransform().Scale})`,
+                    transformOrigin: 'top left',
+                }}
                 ref={r => {
+                    this.createDashEventsTarget(r);
                     this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
                     this._oldWheel = r;
                     // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-- 
cgit v1.2.3-70-g09d2

