aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-09-04 17:48:13 -0400
committerbobzel <zzzman@gmail.com>2024-09-04 17:48:13 -0400
commitdf5217eea01b6ee3ce03ceede030306d05f19c58 (patch)
treebc78c59a43055c162a81016d59b9f725169c29fe
parentc674b67913ecfae6f99749db411d39f8f0d5b164 (diff)
updated calendars to support times of events and to render evdnts at the correct time.
-rw-r--r--src/ClientUtils.ts9
-rw-r--r--src/client/util/DocumentManager.ts4
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx85
3 files changed, 69 insertions, 29 deletions
diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
index 51ad55c07..d149c2eae 100644
--- a/src/ClientUtils.ts
+++ b/src/ClientUtils.ts
@@ -651,18 +651,21 @@ export function dateRangeStrToDates(dateStr: string) {
// dateStr in yyyy-mm-dd format
const dateRangeParts = dateStr.split('|'); // splits into from and to date
if (dateRangeParts.length < 2) return { startDate: new Date(), endDate: new Date() };
+ return { startDate: new Date(dateRangeParts[0]), endDate: new Date(dateRangeParts[1]) };
const fromParts = dateRangeParts[0].split('-');
const toParts = dateRangeParts[1].split('-');
const fromYear = parseInt(fromParts[0]);
const fromMonth = parseInt(fromParts[1]) - 1;
- const fromDay = parseInt(fromParts[2]);
+ const fromDay = parseInt(fromParts[2]?.split('T')[0]);
+ const fromHour = parseInt(fromParts[2]?.split('T')[1]?.split(':')[0] || '12');
const toYear = parseInt(toParts[0]);
const toMonth = parseInt(toParts[1]) - 1;
- const toDay = parseInt(toParts[2]);
+ const toDay = parseInt(toParts[2]?.split('T')[0]);
+ const toHour = parseInt(fromParts[2]?.split('T')[1]?.split(':')[0] || '12');
- return { startDate: new Date(fromYear, fromMonth, fromDay), endDate: new Date(toYear, toMonth, toDay) };
+ return { startDate: new Date(fromYear, fromMonth, fromDay, fromHour), endDate: new Date(toYear, toMonth, toDay, toHour) };
}
function replaceCanvases(oldDiv: HTMLElement, newDiv: HTMLElement) {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 83b83240e..5ae292760 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -269,8 +269,8 @@ export class DocumentManager {
if (options.openLocation?.includes(OpenWhere.lightbox)) {
// even if we found the document view, if the target is a lightbox, we try to open it in the lightbox to preserve lightbox semantics (eg, there's only one active doc in the lightbox)
const target = DocCast(targetDoc.annotationOn, targetDoc);
- const contextView = this.getDocumentView(DocCast(target.embedContainer));
- if (contextView?.ComponentView?.addDocTab?.(target, options.openLocation)) {
+ const compView = this.getDocumentView(DocCast(target.embedContainer))?.ComponentView;
+ if ((compView?.addDocTab ?? compView?._props.addDocTab)?.(target, options.openLocation)) {
await new Promise<void>(waitres => {
setTimeout(() => waitres());
});
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