Add recurrence error handling

This commit is contained in:
BeatLink 2026-02-27 10:47:56 -05:00
parent 9b45639148
commit bfcbfac5bb
3 changed files with 31 additions and 8 deletions

View File

@ -22,8 +22,8 @@
"@fullcalendar/interaction": "6.1.20", "@fullcalendar/interaction": "6.1.20",
"@fullcalendar/list": "6.1.20", "@fullcalendar/list": "6.1.20",
"@fullcalendar/multimonth": "6.1.20", "@fullcalendar/multimonth": "6.1.20",
"@fullcalendar/timegrid": "6.1.20",
"@fullcalendar/rrule": "6.1.20", "@fullcalendar/rrule": "6.1.20",
"@fullcalendar/timegrid": "6.1.20",
"@maplibre/maplibre-gl-leaflet": "0.1.3", "@maplibre/maplibre-gl-leaflet": "0.1.3",
"@mermaid-js/layout-elk": "0.2.0", "@mermaid-js/layout-elk": "0.2.0",
"@mind-elixir/node-menu": "5.0.1", "@mind-elixir/node-menu": "5.0.1",
@ -64,6 +64,7 @@
"react-i18next": "16.5.4", "react-i18next": "16.5.4",
"react-window": "2.2.7", "react-window": "2.2.7",
"reveal.js": "5.2.1", "reveal.js": "5.2.1",
"rrule": "2.8.1",
"svg-pan-zoom": "3.6.2", "svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1", "tabulator-tables": "6.3.1",
"vanilla-js-wheel-zoom": "9.0.4" "vanilla-js-wheel-zoom": "9.0.4"

View File

@ -1,9 +1,11 @@
import { EventInput, EventSourceFuncArg, EventSourceInput } from "@fullcalendar/core/index.js"; import { EventInput, EventSourceFuncArg, EventSourceInput } from "@fullcalendar/core/index.js";
import clsx from "clsx"; import clsx from "clsx";
import * as rruleLib from 'rrule';
import FNote from "../../../entities/fnote"; import FNote from "../../../entities/fnote";
import froca from "../../../services/froca"; import froca from "../../../services/froca";
import server from "../../../services/server"; import server from "../../../services/server";
import toastService from "../../../services/toast";
import { formatDateToLocalISO, getCustomisableLabel, getMonthsInDateRange, offsetDate } from "./utils"; import { formatDateToLocalISO, getCustomisableLabel, getMonthsInDateRange, offsetDate } from "./utils";
interface Event { interface Event {
@ -122,13 +124,30 @@ export async function buildEvent(note: FNote, { startDate, endDate, startTime, e
} }
if (recurrence) { if (recurrence) {
delete eventData.end; // Generate rrule string
eventData.rrule = `DTSTART:${startDate.replace(/[-:]/g, "")}\n${recurrence}`; const rruleString = `DTSTART:${startDate.replace(/[-:]/g, "")}\n${recurrence}`;
if (endDate){
const diffMs = new Date(endDate).getTime() - new Date(startDate).getTime(); // Validate rrule string
const hours = Math.floor(diffMs / 3600000); let rruleValid = true;
const minutes = Math.floor((diffMs / 60000) % 60); try {
eventData.duration = `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`; rruleLib.rrulestr(rruleString, { forceset: true }) as rruleLib.RRuleSet;
} catch {
rruleValid = false;
}
if (rruleValid) {
delete eventData.end;
eventData.rrule = rruleString;
if (endDate){
const diffMs = new Date(endDate).getTime() - new Date(startDate).getTime();
const hours = Math.floor(diffMs / 3600000);
const minutes = Math.floor((diffMs / 60000) % 60);
eventData.duration = `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
}
} else {
const errorMessage = `Note "${note.noteId} ${note.title}" has an invalid #recurrence string. This note will not recur.`;
toastService.showError(errorMessage);
console.error(errorMessage);
} }
} }
events.push(eventData); events.push(eventData);

3
pnpm-lock.yaml generated
View File

@ -326,6 +326,9 @@ importers:
reveal.js: reveal.js:
specifier: 5.2.1 specifier: 5.2.1
version: 5.2.1 version: 5.2.1
rrule:
specifier: 2.8.1
version: 2.8.1
svg-pan-zoom: svg-pan-zoom:
specifier: 3.6.2 specifier: 3.6.2
version: 3.6.2 version: 3.6.2