fix: Outlook UTC date parsing and event deduplication
- Outlook returns dateTime without Z suffix despite timeZone being UTC, causing JS to parse as local time (1h shift). Now appends Z for UTC dates. - Added frontend deduplication to prevent stacked rendering of duplicate events. - Added Outlook event debug logging for recurring event investigation. v1.62.3 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c302a036bb
commit
8abbf4a286
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "my-weekly-todo-list",
|
"name": "my-weekly-todo-list",
|
||||||
"version": "1.62.2",
|
"version": "1.62.3",
|
||||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1607,9 +1607,14 @@ export default function WeeklyView() {
|
|||||||
type WeatherHour = { temp: number; code: number; feelsLike?: number; wind?: number; gusts?: number; precipProb?: number; precip?: number; humidity?: number; uv?: number };
|
type WeatherHour = { temp: number; code: number; feelsLike?: number; wind?: number; gusts?: number; precipProb?: number; precip?: number; humidity?: number; uv?: number };
|
||||||
const [weatherData, setWeatherData] = useState<Record<string, WeatherHour>>({});
|
const [weatherData, setWeatherData] = useState<Record<string, WeatherHour>>({});
|
||||||
|
|
||||||
// Extend events with editable flag from connections
|
// Extend events with editable flag from connections, deduplicate by id
|
||||||
const calendarEvents = useMemo(() => {
|
const calendarEvents = useMemo(() => {
|
||||||
return rawCalendarEvents.map((event) => {
|
const seen = new Set<string>();
|
||||||
|
return rawCalendarEvents.filter((event) => {
|
||||||
|
if (seen.has(event.id)) return false;
|
||||||
|
seen.add(event.id);
|
||||||
|
return true;
|
||||||
|
}).map((event) => {
|
||||||
let isEditable = false;
|
let isEditable = false;
|
||||||
if (event.calendarId) {
|
if (event.calendarId) {
|
||||||
for (const conn of connections) {
|
for (const conn of connections) {
|
||||||
|
|||||||
@ -620,6 +620,8 @@ export const getCalendarEvents = async (
|
|||||||
|
|
||||||
const calendarData = calendars.find(c => c.id === calendarId);
|
const calendarData = calendars.find(c => c.id === calendarId);
|
||||||
|
|
||||||
|
console.log(`[CALENDAR] Outlook calendar ${calendarId}: ${outlookEvents.length} events`, outlookEvents.map((e: any) => ({ id: e.id?.slice(-10), title: e.summary, start: e.start?.dateTime?.slice(0, 16), recurring: e.isRecurring })));
|
||||||
|
|
||||||
events = events.concat(outlookEvents.map((event: any) => ({
|
events = events.concat(outlookEvents.map((event: any) => ({
|
||||||
id: event.id,
|
id: event.id,
|
||||||
title: event.summary || '(No Title)',
|
title: event.summary || '(No Title)',
|
||||||
|
|||||||
@ -212,16 +212,21 @@ export const getUpcomingEvents = async (
|
|||||||
'normal': 'default', 'personal': 'default', 'private': 'private', 'confidential': 'confidential',
|
'normal': 'default', 'personal': 'default', 'private': 'private', 'confidential': 'confidential',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Outlook returns dateTime without Z suffix even when timeZone is UTC.
|
||||||
|
// Append Z so JS Date parsing treats it as UTC (not local time).
|
||||||
|
const fixUtc = (dt: string, tz: string) =>
|
||||||
|
dt && tz === 'UTC' && !dt.endsWith('Z') ? dt + 'Z' : dt;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: event.seriesMasterId ? `${event.seriesMasterId}::${event.id}` : event.id,
|
id: event.seriesMasterId ? `${event.seriesMasterId}::${event.id}` : event.id,
|
||||||
summary: event.subject,
|
summary: event.subject,
|
||||||
description: event.body?.content || event.bodyPreview,
|
description: event.body?.content || event.bodyPreview,
|
||||||
start: {
|
start: {
|
||||||
dateTime: event.start.dateTime,
|
dateTime: fixUtc(event.start.dateTime, event.start.timeZone),
|
||||||
timeZone: event.start.timeZone
|
timeZone: event.start.timeZone
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
dateTime: event.end.dateTime,
|
dateTime: fixUtc(event.end.dateTime, event.end.timeZone),
|
||||||
timeZone: event.end.timeZone
|
timeZone: event.end.timeZone
|
||||||
},
|
},
|
||||||
location: event.location?.displayName,
|
location: event.location?.displayName,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user