mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 19:12:27 +08:00
feat(calendar_view): allow resizing & fix date offset
This commit is contained in:
parent
e71f0cb091
commit
22c8cf3bee
@ -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,38 +58,40 @@ 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);
|
|
||||||
const noteId = e.event.extendedProps.noteId;
|
|
||||||
|
|
||||||
// Fullcalendar end date is exclusive, not inclusive but we store it the other way around.
|
|
||||||
if (endDate) {
|
|
||||||
const endDateParsed = new Date(endDate);
|
|
||||||
endDateParsed.setDate(endDateParsed.getDate() - 1);
|
|
||||||
endDate = endDateParsed.toISOString().substring(0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't store the end date if it's empty.
|
|
||||||
if (endDate === startDate) {
|
|
||||||
endDate = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update start date
|
|
||||||
const note = await froca.getNote(noteId);
|
|
||||||
if (!note) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CalendarView.#setAttribute(note, "label", "startDate", startDate);
|
|
||||||
CalendarView.#setAttribute(note, "label", "endDate", endDate);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
calendar.render();
|
calendar.render();
|
||||||
|
|
||||||
return this.$root;
|
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;
|
||||||
|
|
||||||
|
// Fullcalendar end date is exclusive, not inclusive but we store it the other way around.
|
||||||
|
if (endDate) {
|
||||||
|
const endDateParsed = new Date(endDate);
|
||||||
|
endDateParsed.setDate(endDateParsed.getDate() - 1);
|
||||||
|
endDate = CalendarView.#formatDateToLocalISO(endDateParsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't store the end date if it's empty.
|
||||||
|
if (endDate === startDate) {
|
||||||
|
endDate = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update start date
|
||||||
|
const note = await froca.getNote(noteId);
|
||||||
|
if (!note) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarView.#setAttribute(note, "label", "startDate", startDate);
|
||||||
|
CalendarView.#setAttribute(note, "label", "endDate", endDate);
|
||||||
|
}
|
||||||
|
|
||||||
static async #buildEvents(noteIds: string[]) {
|
static async #buildEvents(noteIds: string[]) {
|
||||||
const notes = await froca.getNotes(noteIds);
|
const notes = await froca.getNotes(noteIds);
|
||||||
const events: EventSourceInput = [];
|
const events: EventSourceInput = [];
|
||||||
@ -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];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user