diff --git a/package.json b/package.json index de80678..d8107f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.63.4", + "version": "1.63.5", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "main": "index.js", "scripts": { diff --git a/src/lib/outlook-calendar.ts b/src/lib/outlook-calendar.ts index 79e511f..bdf71c4 100644 --- a/src/lib/outlook-calendar.ts +++ b/src/lib/outlook-calendar.ts @@ -341,44 +341,54 @@ export const updateEvent = async ( eventId: string, event: any ) => { - const response = await fetch(`${GRAPH_ENDPOINT}/me/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`, { - method: 'PATCH', - headers: { - 'Authorization': `Bearer ${accessToken}`, - 'Content-Type': 'application/json' + const body = JSON.stringify({ + subject: event.summary, + body: { + contentType: 'HTML', + content: event.description || '' }, - body: JSON.stringify({ - subject: event.summary, - body: { - contentType: 'HTML', - content: event.description || '' - }, - start: ensureTimeZone(event.start), - end: ensureTimeZone(event.end), - isAllDay: event.allDay !== undefined ? !!event.allDay : undefined, - location: { - displayName: event.location || '' - }, - ...(event.recurrence ? { recurrence: event.recurrence } : {}), - ...(event.reminders?.length ? { - isReminderOn: true, - reminderMinutesBeforeStart: event.reminders[0].minutes, - } : {}), - ...(event.busyStatus ? { showAs: event.busyStatus === 'oof' ? 'oof' : event.busyStatus } : {}), - ...(event.visibility ? { - sensitivity: event.visibility === 'private' ? 'private' - : event.visibility === 'confidential' ? 'confidential' - : 'normal' - } : {}), - ...(event.attendees?.length ? { - attendees: event.attendees.map((a: any) => ({ - emailAddress: { address: a.email, name: a.displayName || a.email }, - type: 'required', - })), - } : {}), - }) + start: ensureTimeZone(event.start), + end: ensureTimeZone(event.end), + isAllDay: event.allDay !== undefined ? !!event.allDay : undefined, + location: { + displayName: event.location || '' + }, + ...(event.recurrence ? { recurrence: event.recurrence } : {}), + ...(event.reminders?.length ? { + isReminderOn: true, + reminderMinutesBeforeStart: event.reminders[0].minutes, + } : {}), + ...(event.busyStatus ? { showAs: event.busyStatus === 'oof' ? 'oof' : event.busyStatus } : {}), + ...(event.visibility ? { + sensitivity: event.visibility === 'private' ? 'private' + : event.visibility === 'confidential' ? 'confidential' + : 'normal' + } : {}), + ...(event.attendees?.length ? { + attendees: event.attendees.map((a: any) => ({ + emailAddress: { address: a.email, name: a.displayName || a.email }, + type: 'required', + })), + } : {}), }); + const patchHeaders = { + 'Authorization': `Bearer ${accessToken}`, + 'Content-Type': 'application/json' + }; + + // Try calendar-scoped endpoint first + let response = await fetch(`${GRAPH_ENDPOINT}/me/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`, { + method: 'PATCH', headers: patchHeaders, body + }); + + if (!response.ok && response.status === 404) { + // Fallback: try non-calendar-scoped endpoint + response = await fetch(`${GRAPH_ENDPOINT}/me/events/${encodeURIComponent(eventId)}`, { + method: 'PATCH', headers: patchHeaders, body + }); + } + if (!response.ok) { const err = await response.text(); throw new Error(`Failed to update Outlook event: ${err}`); @@ -404,13 +414,24 @@ export const deleteEvent = async ( calendarId: string, eventId: string ) => { - const response = await fetch(`${GRAPH_ENDPOINT}/me/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`, { + // Try calendar-scoped endpoint first + let response = await fetch(`${GRAPH_ENDPOINT}/me/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${accessToken}` } }); + if (!response.ok && response.status === 404) { + // Fallback: try non-calendar-scoped endpoint (works better for series master IDs) + response = await fetch(`${GRAPH_ENDPOINT}/me/events/${encodeURIComponent(eventId)}`, { + method: 'DELETE', + headers: { + 'Authorization': `Bearer ${accessToken}` + } + }); + } + if (!response.ok) { const err = await response.text(); throw new Error(`Failed to delete Outlook event: ${err}`);