feat: add calendar drag-and-drop rescheduling and iCalendar import
- Drag events in week/day views to reschedule (15-min snap intervals) - Drag events in month view to change date (preserves time) - Visual snap indicators with time labels during drag - iCalendar (.ics) file import via JMAP CalendarEvent/parse - Import modal with file upload, event preview, calendar selector - File validation (5MB max), bulk import with progress tracking
This commit is contained in:
@@ -2059,6 +2059,36 @@ export class JMAPClient {
|
||||
throw new Error("Failed to update calendar event");
|
||||
}
|
||||
|
||||
async parseCalendarEvents(accountId: string, blobId: string): Promise<Partial<CalendarEvent>[]> {
|
||||
const response = await this.request([
|
||||
["CalendarEvent/parse", {
|
||||
accountId,
|
||||
blobIds: [blobId],
|
||||
}, "0"]
|
||||
], this.calendarUsing());
|
||||
|
||||
if (response.methodResponses?.[0]?.[0] === "CalendarEvent/parse") {
|
||||
const result = response.methodResponses[0][1];
|
||||
|
||||
if (result.notParsable && result.notParsable.includes(blobId)) {
|
||||
throw new Error("Invalid calendar file format");
|
||||
}
|
||||
|
||||
if (result.notFound && result.notFound.includes(blobId)) {
|
||||
throw new Error("Uploaded file not found");
|
||||
}
|
||||
|
||||
const parsed = result.parsed?.[blobId];
|
||||
if (parsed) {
|
||||
return Array.isArray(parsed) ? parsed : [parsed];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
throw new Error("Failed to parse calendar file");
|
||||
}
|
||||
|
||||
async deleteCalendarEvent(eventId: string, sendSchedulingMessages?: boolean): Promise<void> {
|
||||
const accountId = this.getCalendarsAccountId();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user