Add calendar invites panel to Calendar TUI sidebar
- Create InvitesPanel widget showing pending invites from Microsoft Graph - Add fetch_pending_invites() and respond_to_invite() API functions - Invites load asynchronously in background on app mount - Display invite subject, date/time, and organizer - Add 'i' keybinding to focus invites panel - Style: tentative invites shown in warning color
This commit is contained in:
@@ -468,3 +468,76 @@ async def sync_local_calendar_changes(
|
||||
)
|
||||
|
||||
return created_count, deleted_count
|
||||
|
||||
|
||||
async def fetch_pending_invites(headers, days_forward=30):
|
||||
"""
|
||||
Fetch calendar invites that need a response (pending/tentative).
|
||||
|
||||
Args:
|
||||
headers (dict): Headers including authentication.
|
||||
days_forward (int): Number of days to look forward.
|
||||
|
||||
Returns:
|
||||
list: List of invite dictionaries with response status info.
|
||||
"""
|
||||
start_date = datetime.now()
|
||||
end_date = start_date + timedelta(days=days_forward)
|
||||
|
||||
start_date_str = start_date.strftime("%Y-%m-%dT00:00:00Z")
|
||||
end_date_str = end_date.strftime("%Y-%m-%dT23:59:59Z")
|
||||
|
||||
# Fetch events with response status
|
||||
calendar_url = (
|
||||
f"https://graph.microsoft.com/v1.0/me/calendarView?"
|
||||
f"startDateTime={start_date_str}&endDateTime={end_date_str}&"
|
||||
f"$select=id,subject,organizer,start,end,location,isAllDay,responseStatus,isCancelled&"
|
||||
f"$filter=responseStatus/response eq 'notResponded' or responseStatus/response eq 'tentativelyAccepted'&"
|
||||
f"$orderby=start/dateTime"
|
||||
)
|
||||
|
||||
invites = []
|
||||
|
||||
try:
|
||||
response_data = await fetch_with_aiohttp(calendar_url, headers)
|
||||
invites.extend(response_data.get("value", []))
|
||||
|
||||
# Handle pagination
|
||||
next_link = response_data.get("@odata.nextLink")
|
||||
while next_link:
|
||||
response_data = await fetch_with_aiohttp(next_link, headers)
|
||||
invites.extend(response_data.get("value", []))
|
||||
next_link = response_data.get("@odata.nextLink")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error fetching pending invites: {e}")
|
||||
|
||||
return invites
|
||||
|
||||
|
||||
async def respond_to_invite(headers, event_id, response):
|
||||
"""
|
||||
Respond to a calendar invite.
|
||||
|
||||
Args:
|
||||
headers (dict): Authentication headers
|
||||
event_id (str): The ID of the event to respond to
|
||||
response (str): Response type - 'accept', 'tentativelyAccept', or 'decline'
|
||||
|
||||
Returns:
|
||||
bool: True if response was successful
|
||||
"""
|
||||
valid_responses = ["accept", "tentativelyAccept", "decline"]
|
||||
if response not in valid_responses:
|
||||
print(f"Invalid response type: {response}. Must be one of {valid_responses}")
|
||||
return False
|
||||
|
||||
try:
|
||||
response_url = (
|
||||
f"https://graph.microsoft.com/v1.0/me/events/{event_id}/{response}"
|
||||
)
|
||||
status = await post_with_aiohttp(response_url, headers, {})
|
||||
return status in (200, 202)
|
||||
except Exception as e:
|
||||
print(f"Error responding to invite: {e}")
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user