aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-09-04 22:58:40 -0400
committerbobzel <zzzman@gmail.com>2024-09-04 22:58:40 -0400
commit9014cc474a039f0daef6cc0ee2011329da7703ac (patch)
tree12f45bb9b20d8ee435ad8d7dc9d1b505a493b03a /src
parentdf5217eea01b6ee3ce03ceede030306d05f19c58 (diff)
more fixes for calendarBox to preserve selection when view changes.
Diffstat (limited to 'src')
-rw-r--r--src/ClientUtils.ts22
-rw-r--r--src/client/views/collections/CollectionCalendarView.tsx4
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.scss1
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx56
4 files changed, 50 insertions, 33 deletions
diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
index d149c2eae..01eda7e98 100644
--- a/src/ClientUtils.ts
+++ b/src/ClientUtils.ts
@@ -648,24 +648,14 @@ export function DivWidth(ele: HTMLElement | null): number {
}
export function dateRangeStrToDates(dateStr: string) {
+ const toDate = (str: string) => {
+ return !str.includes('T') && str.includes('-') ? new Date(Number(str.split('-')[0]), Number(str.split('-')[1]) - 1, Number(str.split('-')[2])) : new Date(str);
+ };
// 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]?.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]?.split('T')[0]);
- const toHour = parseInt(fromParts[2]?.split('T')[1]?.split(':')[0] || '12');
-
- return { startDate: new Date(fromYear, fromMonth, fromDay, fromHour), endDate: new Date(toYear, toMonth, toDay, toHour) };
+ if (dateRangeParts.length < 2 && !dateRangeParts[0]) return { start: new Date(), end: new Date() };
+ if (dateRangeParts.length < 2) return { start: toDate(dateRangeParts[0]), end: toDate(dateRangeParts[0]) };
+ return { start: new Date(dateRangeParts[0]), end: new Date(dateRangeParts[1]) };
}
function replaceCanvases(oldDiv: HTMLElement, newDiv: HTMLElement) {
diff --git a/src/client/views/collections/CollectionCalendarView.tsx b/src/client/views/collections/CollectionCalendarView.tsx
index c1f0b314b..30fd9fc2b 100644
--- a/src/client/views/collections/CollectionCalendarView.tsx
+++ b/src/client/views/collections/CollectionCalendarView.tsx
@@ -38,8 +38,8 @@ export class CollectionCalendarView extends CollectionSubView() {
const aDateRangeStr = StrCast(DocListCast(calendarA.data).lastElement()?.date_range);
const bDateRangeStr = StrCast(DocListCast(calendarB.data).lastElement()?.date_range);
- const { startDate: aFromDate, endDate: aToDate } = dateRangeStrToDates(aDateRangeStr);
- const { startDate: bFromDate, endDate: bToDate } = dateRangeStrToDates(bDateRangeStr);
+ const { start: aFromDate, end: aToDate } = dateRangeStrToDates(aDateRangeStr);
+ const { start: bFromDate, end: bToDate } = dateRangeStrToDates(bDateRangeStr);
if (aFromDate > bFromDate) {
return -1; // a comes first
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.scss b/src/client/views/nodes/calendarBox/CalendarBox.scss
index df6ce3e64..f8ac4b2d1 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.scss
+++ b/src/client/views/nodes/calendarBox/CalendarBox.scss
@@ -2,6 +2,7 @@
display: flex;
width: 100%;
height: 100%;
+ transform-origin: top left;
.calendarBox-wrapper {
width: 100%;
height: 100%;
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 9452cc10a..678b7dd0b 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -1,7 +1,8 @@
-import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core';
+import { Calendar, DateInput, EventClickArg, EventSourceInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import multiMonthPlugin from '@fullcalendar/multimonth';
import timeGrid from '@fullcalendar/timegrid';
+import interactionPlugin from '@fullcalendar/interaction';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -26,6 +27,7 @@ export class CalendarBox extends CollectionSubView() {
_oldWheel: HTMLElement | null = null;
_observer: ResizeObserver | undefined;
_eventsDisposer: IReactionDisposer | undefined;
+ _selectDisposer: IReactionDisposer | undefined;
constructor(props: SubCollectionViewProps) {
super(props);
@@ -38,18 +40,32 @@ export class CalendarBox extends CollectionSubView() {
componentDidMount(): void {
this._props.setContentViewBox?.(this);
this._eventsDisposer = reaction(
- () => this.calendarEvents,
- events => this._calendar?.setOption('events', events),
+ () => ({ events: this.calendarEvents }),
+ ({ events }) => this._calendar?.setOption('events', events),
+ { fireImmediately: true }
+ );
+ this._selectDisposer = reaction(
+ () => ({ initialDate: this.dateSelect }),
+ ({ initialDate }) => {
+ const state = this._calendar?.getCurrentData();
+ state &&
+ this._calendar?.dispatch({
+ type: 'CHANGE_DATE',
+ dateMarker: state.dateEnv.createMarker(initialDate.start),
+ });
+ setTimeout(() => (initialDate.start.toISOString() !== initialDate.end.toISOString() ? this._calendar?.select(initialDate.start, initialDate.end) : this._calendar?.select(initialDate.start)));
+ },
{ fireImmediately: true }
);
}
componentWillUnmount(): void {
this._eventsDisposer?.();
+ this._selectDisposer?.();
}
@computed get calendarEvents(): EventSourceInput | undefined {
return this.childDocs.map(doc => {
- const { startDate: start, endDate: end } = dateRangeStrToDates(StrCast(doc.date_range));
+ const { start, end } = dateRangeStrToDates(StrCast(doc.date_range));
return {
title: StrCast(doc.title),
start,
@@ -61,6 +77,7 @@ export class CalendarBox extends CollectionSubView() {
classNames: ['mother'], // will determine the style
editable: true, // subject to change in the future
backgroundColor: this.eventToColor(doc),
+ borderColor: this.eventToColor(doc),
color: 'white',
extendedProps: {
description: StrCast(doc.description),
@@ -72,20 +89,23 @@ export class CalendarBox extends CollectionSubView() {
@computed get dateRangeStrDates() {
return dateRangeStrToDates(StrCast(this.Document.date_range));
}
+ get dateSelect() {
+ return dateRangeStrToDates(StrCast(this.Document.date));
+ }
// 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 'multiMonth';
- if (Math.abs(startDate.getDay() - endDate.getDay()) > 7) return 'dayGridMonth';
+ const { start, end } = this.dateRangeStrDates;
+ if (start.getFullYear() !== end.getFullYear() || start.getMonth() !== end.getMonth()) return 'multiMonth';
+ if (Math.abs(start.getDay() - end.getDay()) > 7) return 'dayGridMonth';
return 'timeGridWeek';
}
// TODO: Return a different color based on the event type
eventToColor(event: Doc): string {
- return 'blue';
+ return 'red';
}
internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData) {
@@ -116,32 +136,39 @@ export class CalendarBox extends CollectionSubView() {
const cal = !this._calendarRef
? null
: (this._calendar = new Calendar(this._calendarRef, {
- plugins: [multiMonthPlugin, dayGridPlugin, timeGrid],
+ 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.dateRangeStrDates.startDate,
+ initialDate: this.dateSelect.start,
navLinks: true,
editable: false,
displayEventTime: false,
displayEventEnd: false,
+ select: info => {
+ const start = dateRangeStrToDates(info.startStr).start.toISOString();
+ const end = 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,
}));
cal?.render();
+ setTimeout(() => cal?.view.calendar.select(this.dateSelect.start, this.dateSelect.end));
};
onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
render() {
return (
<div
- key={StrCast(this.dataDoc[this.fieldKey + '_calendarType'])}
+ key={this.calendarViewType}
className="calendarBox"
- onPointerDown={e =>
+ onPointerDown={e => {
setTimeout(
action(() => {
const cname = (e.nativeEvent.target as HTMLButtonElement)?.className ?? '';
@@ -150,13 +177,12 @@ export class CalendarBox extends CollectionSubView() {
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);