Fix notes popup positioning, reposition task actions to avoid overlap, and improve Apple Calendar sync

This commit is contained in:
mARTin 2026-02-24 12:58:19 +01:00
parent 368928c016
commit 279d1a4c49
5 changed files with 41 additions and 23 deletions

View File

@ -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 {

View File

@ -331,8 +331,8 @@ export function GridTaskBlock({
)}
<button className="task-action-btn delete text-red-500 hover:text-red-700 hover:bg-red-100/50 dark:hover:bg-red-900/30 rounded" onClick={(e) => { e.stopPropagation(); deleteTask(task.id); }} title="Delete">
<svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round">
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
</div>

View File

@ -5854,7 +5854,7 @@ function TaskItem({
</span>
</span>
<div className="task-actions absolute right-0 top-0 bottom-0 flex items-center bg-white/95 dark:bg-gray-800/95 pl-2 pr-1 shadow-[-12px_0_12px_-4px_rgba(255,255,255,0.95)] dark:shadow-[-12px_0_12px_-4px_rgba(31,41,55,0.95)] z-20">
<div className="task-actions z-20">
{/* Complete */}
<button
className={`task-action-btn ${task.completed ? "active text-green-600 dark:text-green-500" : ""}`}
@ -6028,8 +6028,8 @@ function TaskItem({
strokeLinecap="round"
strokeLinejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
</div>

View File

@ -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) {

View File

@ -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: '',