feat(calendar_view): allow resizing & fix date offset

This commit is contained in:
Elian Doran 2025-02-15 12:26:58 +02:00
parent e71f0cb091
commit 22c8cf3bee
No known key found for this signature in database

View File

@ -1,9 +1,10 @@
import type { EventSourceInput, PluginDef } from "@fullcalendar/core"; import type { EventChangeArg, EventDropArg, EventSourceInput, PluginDef } from "@fullcalendar/core";
import froca from "../../services/froca.js"; import froca from "../../services/froca.js";
import ViewMode, { type ViewModeArgs } from "./view_mode.js"; import ViewMode, { type ViewModeArgs } from "./view_mode.js";
import type FNote from "../../entities/fnote.js"; import type FNote from "../../entities/fnote.js";
import server from "../../services/server.js"; import server from "../../services/server.js";
import ws from "../../services/ws.js"; import ws from "../../services/ws.js";
import type { EventDragStopArg, EventResizeDoneArg } from "@fullcalendar/interaction";
const TPL = ` const TPL = `
<div class="calendar-view"> <div class="calendar-view">
@ -57,16 +58,23 @@ export default class CalendarView extends ViewMode {
initialView: "dayGridMonth", initialView: "dayGridMonth",
events: await CalendarView.#buildEvents(this.noteIds), events: await CalendarView.#buildEvents(this.noteIds),
editable, editable,
eventDragStop: async (e) => { eventChange: (e) => this.#onEventMoved(e),
const startDate = e.event.start?.toISOString().substring(0, 10); });
let endDate = e.event.end?.toISOString().substring(0, 10); calendar.render();
return this.$root;
}
async #onEventMoved(e: EventChangeArg) {
const startDate = CalendarView.#formatDateToLocalISO(e.event.start);
let endDate = CalendarView.#formatDateToLocalISO(e.event.end);
const noteId = e.event.extendedProps.noteId; const noteId = e.event.extendedProps.noteId;
// Fullcalendar end date is exclusive, not inclusive but we store it the other way around. // Fullcalendar end date is exclusive, not inclusive but we store it the other way around.
if (endDate) { if (endDate) {
const endDateParsed = new Date(endDate); const endDateParsed = new Date(endDate);
endDateParsed.setDate(endDateParsed.getDate() - 1); endDateParsed.setDate(endDateParsed.getDate() - 1);
endDate = endDateParsed.toISOString().substring(0, 10); endDate = CalendarView.#formatDateToLocalISO(endDateParsed);
} }
// Don't store the end date if it's empty. // Don't store the end date if it's empty.
@ -83,11 +91,6 @@ export default class CalendarView extends ViewMode {
CalendarView.#setAttribute(note, "label", "startDate", startDate); CalendarView.#setAttribute(note, "label", "startDate", startDate);
CalendarView.#setAttribute(note, "label", "endDate", endDate); CalendarView.#setAttribute(note, "label", "endDate", endDate);
} }
});
calendar.render();
return this.$root;
}
static async #buildEvents(noteIds: string[]) { static async #buildEvents(noteIds: string[]) {
const notes = await froca.getNotes(noteIds); const notes = await froca.getNotes(noteIds);
@ -114,7 +117,7 @@ export default class CalendarView extends ViewMode {
if (endDate) { if (endDate) {
// Fullcalendar end date is exclusive, not inclusive. // Fullcalendar end date is exclusive, not inclusive.
endDate.setDate(endDate.getDate() + 1); endDate.setDate(endDate.getDate() + 1);
eventData.end = endDate.toISOString().substring(0, 10); eventData.end = CalendarView.#formatDateToLocalISO(endDate);
} }
events.push(eventData); events.push(eventData);
@ -159,7 +162,7 @@ export default class CalendarView extends ViewMode {
await server.put(`notes/${note.noteId}/set-attribute`, { type, name, value }); await server.put(`notes/${note.noteId}/set-attribute`, { type, name, value });
} else { } else {
// Remove the attribute if it exists on the server but we don't define a value for it. // Remove the attribute if it exists on the server but we don't define a value for it.
const attributeId = note.getAttribute(type, name); const attributeId = note.getAttribute(type, name)?.attributeId;
if (attributeId) { if (attributeId) {
await server.remove(`notes/${note.noteId}/attributes/${attributeId}`); await server.remove(`notes/${note.noteId}/attributes/${attributeId}`);
} }
@ -167,4 +170,14 @@ export default class CalendarView extends ViewMode {
await ws.waitForMaxKnownEntityChangeId(); await ws.waitForMaxKnownEntityChangeId();
} }
static #formatDateToLocalISO(date: Date | null | undefined) {
if (!date) {
return undefined;
}
const offset = date.getTimezoneOffset();
const localDate = new Date(date.getTime() - offset * 60 * 1000);
return localDate.toISOString().split('T')[0];
}
} }