aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-05-15 13:34:56 -0400
committerbobzel <zzzman@gmail.com>2025-05-15 13:34:56 -0400
commit3f144d7bad65af2424d27e2e3a58eecd0d0e114b (patch)
treed1b6497ba17573afa569d76d093ebc441d6955ea /src
parentfb10b16134f1d556247daadf61409b0830eb2f49 (diff)
cleaned up calendarBox to have a more reactive UI and to fix some bugs with selecting and autoscroling.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.scss3
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx141
2 files changed, 83 insertions, 61 deletions
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>
);
}