Agenda refactor
This commit is contained in:
parent
946a110054
commit
fd24dfbd21
@ -242,35 +242,65 @@ export default async function CalendarPage() {
|
||||
console.log(`[AGENDA] Invalid calendar URL detected (${existingSync.externalCalendarUrl}), attempting to rediscover...`);
|
||||
try {
|
||||
const { discoverInfomaniakCalendars } = await import('@/lib/services/caldav-sync');
|
||||
const externalCalendars = await discoverInfomaniakCalendars(
|
||||
account.email,
|
||||
account.password!
|
||||
);
|
||||
|
||||
if (externalCalendars.length > 0) {
|
||||
const mainCalendar = externalCalendars[0];
|
||||
console.log(`[AGENDA] Updating sync with correct calendar URL: ${mainCalendar.url}`);
|
||||
await prisma.calendarSync.update({
|
||||
where: { id: existingSync.id },
|
||||
data: {
|
||||
externalCalendarId: mainCalendar.id,
|
||||
externalCalendarUrl: mainCalendar.url,
|
||||
lastSyncError: null, // Clear error since we're fixing the URL
|
||||
}
|
||||
});
|
||||
// Reload the sync config
|
||||
const updatedSync = await prisma.calendarSync.findUnique({
|
||||
where: { id: existingSync.id },
|
||||
include: { calendar: true }
|
||||
});
|
||||
if (updatedSync) {
|
||||
existingSync = updatedSync;
|
||||
}
|
||||
if (!account.password) {
|
||||
console.error(`[AGENDA] Cannot rediscover calendars: missing password for ${account.email}`);
|
||||
} else {
|
||||
console.log(`[AGENDA] No calendars found during rediscovery for ${account.email}`);
|
||||
const externalCalendars = await discoverInfomaniakCalendars(
|
||||
account.email,
|
||||
account.password
|
||||
);
|
||||
|
||||
console.log(`[AGENDA] Rediscovery result: found ${externalCalendars.length} calendars for ${account.email}`);
|
||||
|
||||
if (externalCalendars.length > 0) {
|
||||
const mainCalendar = externalCalendars[0];
|
||||
console.log(`[AGENDA] Updating sync with correct calendar URL: ${mainCalendar.url} (name: ${mainCalendar.name})`);
|
||||
await prisma.calendarSync.update({
|
||||
where: { id: existingSync.id },
|
||||
data: {
|
||||
externalCalendarId: mainCalendar.id,
|
||||
externalCalendarUrl: mainCalendar.url,
|
||||
lastSyncError: null, // Clear error since we're fixing the URL
|
||||
}
|
||||
});
|
||||
// Reload the sync config
|
||||
const updatedSync = await prisma.calendarSync.findUnique({
|
||||
where: { id: existingSync.id },
|
||||
include: { calendar: true }
|
||||
});
|
||||
if (updatedSync) {
|
||||
existingSync = updatedSync;
|
||||
console.log(`[AGENDA] Sync config updated successfully, new URL: ${updatedSync.externalCalendarUrl}`);
|
||||
}
|
||||
} else {
|
||||
console.warn(`[AGENDA] No calendars found during rediscovery for ${account.email}. This may indicate:`);
|
||||
console.warn(` - Authentication issue (wrong password)`);
|
||||
console.warn(` - No calendars exist for this account`);
|
||||
console.warn(` - CalDAV server issue`);
|
||||
// Mark sync as having an error so user knows something is wrong
|
||||
await prisma.calendarSync.update({
|
||||
where: { id: existingSync.id },
|
||||
data: {
|
||||
lastSyncError: `No calendars found during rediscovery. Please check your Infomaniak account credentials and calendar access.`,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (rediscoverError) {
|
||||
console.error(`[AGENDA] Error rediscovering calendars:`, rediscoverError);
|
||||
} catch (rediscoverError: any) {
|
||||
console.error(`[AGENDA] Error rediscovering calendars for ${account.email}:`, {
|
||||
error: rediscoverError?.message || String(rediscoverError),
|
||||
stack: rediscoverError?.stack?.substring(0, 300),
|
||||
});
|
||||
// Mark sync as having an error
|
||||
await prisma.calendarSync.update({
|
||||
where: { id: existingSync.id },
|
||||
data: {
|
||||
lastSyncError: `Rediscovery failed: ${rediscoverError?.message || 'Unknown error'}`,
|
||||
}
|
||||
}).catch(() => {
|
||||
// Ignore update errors
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,18 +48,31 @@ export async function discoverInfomaniakCalendars(
|
||||
const client = await getInfomaniakCalDAVClient(email, password);
|
||||
|
||||
// List all calendars using PROPFIND on root
|
||||
logger.debug('Discovering Infomaniak calendars', { email });
|
||||
const items = await client.getDirectoryContents('/');
|
||||
|
||||
logger.debug('Found items in root directory', {
|
||||
email,
|
||||
itemsCount: items.length,
|
||||
items: items.map(item => ({ filename: item.filename, type: item.type })),
|
||||
});
|
||||
|
||||
const calendars: CalDAVCalendar[] = [];
|
||||
|
||||
for (const item of items) {
|
||||
// Skip non-directories, root, and special directories like /principals
|
||||
if (item.type !== 'directory' || item.filename === '/' || item.filename === '/principals') {
|
||||
logger.debug('Skipping item', {
|
||||
filename: item.filename,
|
||||
type: item.type,
|
||||
reason: item.type !== 'directory' ? 'not a directory' : 'special directory',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get calendar properties to verify it's actually a calendar
|
||||
try {
|
||||
logger.debug('Checking if item is a calendar', { filename: item.filename });
|
||||
const props = await client.customRequest(item.filename, {
|
||||
method: 'PROPFIND',
|
||||
headers: {
|
||||
@ -77,11 +90,23 @@ export async function discoverInfomaniakCalendars(
|
||||
});
|
||||
|
||||
// Check if this is actually a calendar (has <c:calendar> in resourcetype)
|
||||
const isCalendar = props.data && props.data.includes('<c:calendar');
|
||||
// Try multiple patterns to be more flexible with XML namespaces
|
||||
const dataStr = props.data || '';
|
||||
const isCalendar = dataStr.includes('<c:calendar') ||
|
||||
dataStr.includes('calendar') ||
|
||||
dataStr.includes('urn:ietf:params:xml:ns:caldav');
|
||||
|
||||
logger.debug('Calendar check result', {
|
||||
filename: item.filename,
|
||||
isCalendar,
|
||||
hasData: !!props.data,
|
||||
dataPreview: props.data ? props.data.substring(0, 500) : 'no data',
|
||||
});
|
||||
|
||||
if (!isCalendar) {
|
||||
logger.debug('Skipping non-calendar directory', {
|
||||
filename: item.filename,
|
||||
reason: 'resourcetype does not indicate calendar',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@ -90,12 +115,15 @@ export async function discoverInfomaniakCalendars(
|
||||
const displayName = extractDisplayName(props.data);
|
||||
const color = extractCalendarColor(props.data);
|
||||
|
||||
calendars.push({
|
||||
const calendar = {
|
||||
id: item.filename.replace(/^\//, '').replace(/\/$/, ''),
|
||||
name: displayName || item.basename || 'Calendrier',
|
||||
url: item.filename,
|
||||
color: color,
|
||||
});
|
||||
};
|
||||
|
||||
logger.debug('Found valid calendar', calendar);
|
||||
calendars.push(calendar);
|
||||
} catch (error) {
|
||||
logger.error('Error fetching calendar properties', {
|
||||
calendar: item.filename,
|
||||
@ -105,19 +133,23 @@ export async function discoverInfomaniakCalendars(
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Infomaniak calendar discovery completed', {
|
||||
email,
|
||||
calendarsFound: calendars.length,
|
||||
calendars: calendars.map(cal => ({ id: cal.id, name: cal.name, url: cal.url })),
|
||||
});
|
||||
|
||||
return calendars;
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
const errorDetails = error instanceof Error ? {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack?.substring(0, 200), // First 200 chars of stack
|
||||
stack: error.stack?.substring(0, 500), // More stack for debugging
|
||||
} : { raw: String(error) };
|
||||
|
||||
// Use logger.log instead of logger.error for non-critical errors
|
||||
// This prevents console.error from showing up in the browser console
|
||||
// The error is still logged server-side but won't appear as a red error in the browser
|
||||
logger.log('info', 'Infomaniak calendar discovery failed (non-critical)', {
|
||||
// Log as error for debugging, but don't throw to avoid breaking the page
|
||||
logger.error('Infomaniak calendar discovery failed', {
|
||||
email,
|
||||
error: errorMessage,
|
||||
errorDetails,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user