diff --git a/src/app/globals.css b/src/app/globals.css
index 3aebe8c..146f1b9 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -967,35 +967,45 @@ h3 {
color: var(--weekly-text);
}
-/* Action Buttons Styling */
+/* Action Buttons Styling - Float above task on hover to avoid overlap */
.task-actions {
display: flex;
align-items: center;
gap: 2px;
position: absolute;
right: 0;
- top: 0;
- bottom: 0;
- z-index: 10;
- padding-left: 8px;
- padding-right: 4px;
+ top: -26px; /* Position above the task item */
+ background: var(--weekly-bg, white);
+ border: 1px solid var(--weekly-border, #e0e0e0);
+ border-radius: 6px;
+ box-shadow: 0 2px 8px rgba(0,0,0,0.12);
+ z-index: 100;
+ padding: 2px 4px;
flex-wrap: nowrap;
+ pointer-events: auto;
}
-/* Time-grid tasks: show actions below task text as a dropdown toolbar */
+/* Time-grid tasks: show actions above task text as a floating toolbar on hover */
.time-slot-task > .task-actions {
position: absolute;
- top: auto;
- bottom: auto;
+ top: -28px; /* Float above the task */
left: 0;
right: auto;
margin-top: 0;
background: var(--weekly-bg, white);
border: 1px solid var(--weekly-border, #e0e0e0);
border-radius: 6px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.12);
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
padding: 2px 4px;
- z-index: 20;
+ z-index: 100; /* Ensure it stays above everything */
+ display: flex !important; /* Force flex even if default is hidden */
+ pointer-events: auto;
+}
+
+/* Ensure actions don't get clipped by the scrolling container */
+.time-slots-container {
+ overflow-y: auto;
+ overflow-x: visible;
}
.dark .time-slot-task > .task-actions {
diff --git a/src/components/GridTaskBlock.tsx b/src/components/GridTaskBlock.tsx
index c242328..a56dafd 100644
--- a/src/components/GridTaskBlock.tsx
+++ b/src/components/GridTaskBlock.tsx
@@ -331,8 +331,8 @@ export function GridTaskBlock({
)}
diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx
index 022cfa6..304ad52 100644
--- a/src/components/WeeklyView.tsx
+++ b/src/components/WeeklyView.tsx
@@ -5854,7 +5854,7 @@ function TaskItem({
-
+
diff --git a/src/lib/apple-calendar.ts b/src/lib/apple-calendar.ts
index c7c905a..ea431f9 100644
--- a/src/lib/apple-calendar.ts
+++ b/src/lib/apple-calendar.ts
@@ -11,6 +11,7 @@ export interface AppleCalendarEvent {
endDate: string;
description?: string;
location?: string;
+ url?: string;
}
export interface AppleCalendar {
@@ -165,7 +166,8 @@ export const getUpcomingEvents = async (
startDate: exIsAllDay ? exStart.toISOString().slice(0, 10) : exStart.toISOString(),
endDate: exIsAllDay ? exEnd.toISOString().slice(0, 10) : exEnd.toISOString(),
description: exEvent.description,
- location: exEvent.location
+ location: exEvent.location,
+ url: exVevent.getFirstPropertyValue('url')?.toString() || undefined
});
}
});
@@ -197,7 +199,8 @@ export const getUpcomingEvents = async (
startDate: isAllDayRecurring ? occStart.toISOString().slice(0, 10) : occStart.toISOString(),
endDate: isAllDayRecurring ? occEnd.toISOString().slice(0, 10) : occEnd.toISOString(),
description: event.description,
- location: event.location
+ location: event.location,
+ url: vevent.getFirstPropertyValue('url')?.toString() || undefined
});
}
} catch (expandErr: any) {
@@ -217,7 +220,8 @@ export const getUpcomingEvents = async (
startDate: isAllDay ? start.toISOString().slice(0, 10) : start.toISOString(),
endDate: isAllDay ? end.toISOString().slice(0, 10) : end.toISOString(),
description: event.description,
- location: event.location
+ location: event.location,
+ url: vevent.getFirstPropertyValue('url')?.toString() || undefined
});
}
});
@@ -338,7 +342,8 @@ END:VCALENDAR`;
startDate: eventData.start.dateTime || eventData.start.date || '',
endDate: eventData.end.dateTime || eventData.end.date || '',
description: eventData.description,
- location: eventData.location
+ location: eventData.location,
+ url: eventData.url
};
} catch (error) {
console.error('[APPLE CALENDAR] Error creating event:', error);
@@ -553,7 +558,8 @@ export const updateEvent = async (
startDate: event.startDate.toString(),
endDate: event.endDate.toString(),
description: event.description,
- location: event.location
+ location: event.location,
+ url: vevent.getFirstPropertyValue('url')?.toString() || undefined
};
} catch (error) {
diff --git a/src/lib/calendar-events.ts b/src/lib/calendar-events.ts
index 847eebb..27441be 100644
--- a/src/lib/calendar-events.ts
+++ b/src/lib/calendar-events.ts
@@ -56,9 +56,9 @@ function toOutlookRecurrence(recurrence?: string, startDate?: Date): any {
case 'daily':
return { pattern: { type: 'daily', interval: 1 }, range };
case 'weekly':
- return { pattern: { type: 'weekly', interval: 1, daysOfWeek: [['sunday','monday','tuesday','wednesday','thursday','friday','saturday'][start.getDay()]] }, range };
+ return { pattern: { type: 'weekly', interval: 1, daysOfWeek: [['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'][start.getDay()]] }, range };
case 'biweekly':
- return { pattern: { type: 'weekly', interval: 2, daysOfWeek: [['sunday','monday','tuesday','wednesday','thursday','friday','saturday'][start.getDay()]] }, range };
+ return { pattern: { type: 'weekly', interval: 2, daysOfWeek: [['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'][start.getDay()]] }, range };
case 'monthly':
return { pattern: { type: 'absoluteMonthly', interval: 1, dayOfMonth: start.getDate() }, range };
case 'yearly':
@@ -360,6 +360,7 @@ export const getCalendarEvents = async (
date: startIsAllDay ? event.endDate : undefined,
},
location: event.location,
+ url: event.url,
source: 'apple' as const,
calendarId,
calendarTitle: calendars.find(c => c.id === calendarId)?.title || 'Apple Calendar',
@@ -751,6 +752,7 @@ export const updateCalendarEvent = async (
start: { dateTime: updatedEvent.startDate },
end: { dateTime: updatedEvent.endDate },
location: updatedEvent.location,
+ url: updatedEvent.url,
source: 'apple',
calendarId,
calendarTitle: '',