diff options
-rw-r--r-- | package-lock.json | 18 | ||||
-rw-r--r-- | package.json | 7 | ||||
-rw-r--r-- | src/client/views/nodes/calendarBox/CalendarBox.scss | 3 | ||||
-rw-r--r-- | src/client/views/nodes/calendarBox/CalendarBox.tsx | 141 |
4 files changed, 102 insertions, 67 deletions
diff --git a/package-lock.json b/package-lock.json index 28b81dbc7..a8752cb5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,9 +28,10 @@ "@fortawesome/free-regular-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/react-fontawesome": "^0.2.2", - "@fullcalendar/core": "^6.1.15", - "@fullcalendar/daygrid": "^6.1.10", - "@fullcalendar/multimonth": "^6.1.10", + "@fullcalendar/core": "^6.1.17", + "@fullcalendar/daygrid": "^6.1.17", + "@fullcalendar/multimonth": "^6.1.17", + "@fullcalendar/react": "^6.1.17", "@fullcalendar/timegrid": "^6.1.15", "@internationalized/date": "^3.5.0", "@mozilla/readability": "^0.6.0", @@ -4581,6 +4582,17 @@ "@fullcalendar/core": "~6.1.17" } }, + "node_modules/@fullcalendar/react": { + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@fullcalendar/react/-/react-6.1.17.tgz", + "integrity": "sha512-AA8soHhlfRH5dUeqHnfAtzDiXa2vrgWocJSK/F5qzw/pOxc9MqpuoS/nQBROWtHHg6yQUg3DoGqOOhi7dmylXQ==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.17", + "react": "^16.7.0 || ^17 || ^18 || ^19", + "react-dom": "^16.7.0 || ^17 || ^18 || ^19" + } + }, "node_modules/@fullcalendar/timegrid": { "version": "6.1.17", "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.17.tgz", diff --git a/package.json b/package.json index 6a579efd2..382c71aed 100644 --- a/package.json +++ b/package.json @@ -112,9 +112,10 @@ "@fortawesome/free-regular-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/react-fontawesome": "^0.2.2", - "@fullcalendar/core": "^6.1.15", - "@fullcalendar/daygrid": "^6.1.10", - "@fullcalendar/multimonth": "^6.1.10", + "@fullcalendar/core": "^6.1.17", + "@fullcalendar/daygrid": "^6.1.17", + "@fullcalendar/multimonth": "^6.1.17", + "@fullcalendar/react": "^6.1.17", "@fullcalendar/timegrid": "^6.1.15", "@internationalized/date": "^3.5.0", "@mozilla/readability": "^0.6.0", diff --git a/src/client/views/nodes/calendarBox/CalendarBox.scss b/src/client/views/nodes/calendarBox/CalendarBox.scss index f8ac4b2d1..e3e0bae4b 100644 --- a/src/client/views/nodes/calendarBox/CalendarBox.scss +++ b/src/client/views/nodes/calendarBox/CalendarBox.scss @@ -3,7 +3,8 @@ width: 100%; height: 100%; transform-origin: top left; - .calendarBox-wrapper { + overflow: auto; + > div { width: 100%; height: 100%; .fc-timegrid-body { diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx index c1198f328..2d6c8c9a4 100644 --- a/src/client/views/nodes/calendarBox/CalendarBox.tsx +++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx @@ -3,13 +3,14 @@ import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; import multiMonthPlugin from '@fullcalendar/multimonth'; import timeGrid from '@fullcalendar/timegrid'; -import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; +import FullCalendar from '@fullcalendar/react'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction, trace, untracked } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { dateRangeStrToDates } from '../../../../ClientUtils'; import { Doc } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; -import { BoolCast, NumCast, StrCast } from '../../../../fields/Types'; +import { BoolCast, StrCast } from '../../../../fields/Types'; import { DocServer } from '../../../DocServer'; import { DragManager } from '../../../util/DragManager'; import { CollectionSubView, SubCollectionViewProps } from '../../collections/CollectionSubView'; @@ -23,7 +24,7 @@ type CalendarView = 'multiMonth' | 'dayGridMonth' | 'timeGridWeek' | 'timeGridDa @observer export class CalendarBox extends CollectionSubView() { - _calendarRef: HTMLDivElement | null = null; + _calendarRef: FullCalendar | null = null; _calendar: Calendar | undefined; _observer: ResizeObserver | undefined; _eventsDisposer: IReactionDisposer | undefined; @@ -148,56 +149,85 @@ export class CalendarBox extends CollectionSubView() { }; // https://fullcalendar.io - renderCalendar = () => { - const cal = !this._calendarRef - ? null - : (this._calendar = new Calendar(this._calendarRef, { - plugins: [multiMonthPlugin, dayGridPlugin, timeGrid, interactionPlugin], - headerToolbar: { - left: 'prev,next today', - center: 'title', - right: 'multiMonth dayGridMonth timeGridWeek timeGridDay', - }, - selectable: true, - initialView: this.calendarViewType === 'multiMonth' ? undefined : this.calendarViewType, - initialDate: this.dateSelect.start, - navLinks: true, - editable: false, - displayEventTime: false, - displayEventEnd: false, - select: info => { - const start = dateRangeStrToDates(info.startStr).start.toISOString(); - const end = info.allDay ? start : dateRangeStrToDates(info.endStr).start.toISOString(); - this.dataDoc.date = start + '|' + end; - }, - aspectRatio: NumCast(this.Document.width) / NumCast(this.Document.height), - events: this.calendarEvents, - eventClick: this.handleEventClick, - eventDrop: this.handleEventDrop, - eventDidMount: arg => { - arg.el.addEventListener('pointerdown', ev => { - ev.button && ev.stopPropagation(); - }); - if (navigator.userAgent.includes('Macintosh')) { - arg.el.addEventListener('pointerup', ev => { - ev.button && ev.stopPropagation(); - ev.button && this.handleEventContextMenu(ev.pageX, ev.pageY, arg.event._def.groupId); - }); - } - arg.el.addEventListener('contextmenu', ev => { - if (!navigator.userAgent.includes('Macintosh')) { - this.handleEventContextMenu(ev.pageX, ev.pageY, arg.event._def.groupId); + @computed get renderCalendar() { + const availableWidth = this._props.PanelWidth() / (this._props.DocumentView?.().UIBtnScaling ?? 1); + const btn = (text: string, view: string | (() => void), hint: string) => ({ text, hint, click: typeof view === 'string' ? () => this._calendarRef?.getApi().changeView(view) : view }); + return ( + <FullCalendar + ref={r => (this._calendarRef = r)} + customButtons={{ + nowBtn: btn('Now', () => this._calendarRef?.getApi().gotoDate(new Date()), 'Go to Today'), + multiBtn: btn('M+', 'multiMonth', 'Multiple Month View'), + monthBtn: btn('M', 'dayGridMonth', 'Month View'), + weekBtn: btn('W', 'timeGridWeek', 'Week View'), + dayBtn: btn('D', 'timeGridDay', 'Day View'), + }} + headerToolbar={ + availableWidth > 450 + ? { + left: 'prev,next nowBtn', + center: 'title', + right: 'multiBtn monthBtn weekBtn dayBtn', } - ev.stopPropagation(); - ev.preventDefault(); - }); - }, - })); - cal?.render(); - setTimeout(() => cal?.view.calendar.select(this.dateSelect.start, this.dateSelect.end)); - }; + : availableWidth > 300 + ? { + left: 'prev,next', + center: 'title', + right: '', + } + : { + left: '', + center: 'title', + right: '', + } + } + selectable={true} + initialView={this.calendarViewType === 'multiMonth' ? undefined : this.calendarViewType} + initialDate={untracked(() => this.dateSelect.start)} + navLinks={true} + editable={false} + // expandRows={true} + // handleWindowResize={true} + displayEventTime={false} + displayEventEnd={false} + plugins={[multiMonthPlugin, dayGridPlugin, timeGrid, interactionPlugin]} + aspectRatio={this._props.PanelWidth() / this._props.PanelHeight()} + weekends={false} + events={this.calendarEvents} + eventClick={this.handleEventClick} + eventDrop={this.handleEventDrop} + unselectAuto={false} + // unselect={() => {}} + select={info => { + const start = dateRangeStrToDates(info.startStr).start.toISOString(); + const end = info.allDay ? start : dateRangeStrToDates(info.endStr).start.toISOString(); + this.dataDoc.date = start + '|' + end; + }} + // eventContent={() => { + // return null; + // }} + eventDidMount={arg => { + arg.el.addEventListener('pointerdown', ev => ev.button && ev.stopPropagation()); + if (navigator.userAgent.includes('Macintosh')) { + arg.el.addEventListener('pointerup', ev => { + ev.button && ev.stopPropagation(); + ev.button && this.handleEventContextMenu(ev.pageX, ev.pageY, arg.event._def.groupId); + }); + } + arg.el.addEventListener('contextmenu', ev => { + if (!navigator.userAgent.includes('Macintosh')) { + this.handleEventContextMenu(ev.pageX, ev.pageY, arg.event._def.groupId); + } + ev.stopPropagation(); + ev.preventDefault(); + }); + }} + /> + ); + } render() { + trace(); return ( <div key={this.calendarViewType} @@ -221,17 +251,8 @@ export class CalendarBox extends CollectionSubView() { ref={r => { this.createDashEventsTarget(r); this.fixWheelEvents(r, this._props.isContentActive); - - if (r) { - this._observer?.disconnect(); - (this._observer = new ResizeObserver(() => { - this._calendar?.setOption('aspectRatio', NumCast(this.Document.width) / NumCast(this.Document.height)); - this._calendar?.updateSize(); - })).observe(r); - this.renderCalendar(); - } }}> - <div className="calendarBox-wrapper" ref={r => (this._calendarRef = r)} /> + {this.renderCalendar} </div> ); } |