From 464a9514b89985498a7dd5422928cc24057dc9f4 Mon Sep 17 00:00:00 2001 From: Mel <97147377+MelissaAutumn@users.noreply.github.com> Date: Tue, 30 Apr 2024 08:06:43 -0700 Subject: [PATCH] Adjusted calendar settings flow (#381) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adjusted calendar settings flow: * You can now disconnect connected calendars without nuking them. * You can now remove (delete) calendars that are unconnected. * Sync still brings them back if they're from a google account. * Schedule Settings will become inactive if the connected calendar is disconnected. * Schedule Settings will be deleted if an unconnected calendar that is associated is deleted. (Cascade all from models.Calendar) * Schedule Settings becomes active if a previously unconnected calendar becomes connected again. * 🌐 Update lang strings --------- Co-authored-by: Andreas Müller --- .../src/appointment/database/repo/schedule.py | 6 +++++ backend/src/appointment/database/schemas.py | 1 + backend/src/appointment/routes/api.py | 15 ++++++++--- backend/src/appointment/routes/schedule.py | 6 +++++ .../src/components/CalendarManagement.vue | 2 +- frontend/src/components/ConfirmationModal.vue | 2 +- frontend/src/components/ScheduleCreation.vue | 8 +++++- frontend/src/components/SettingsCalendar.vue | 26 ++++++++++++++++--- frontend/src/locales/de.json | 22 ++++++++++++++-- frontend/src/locales/en.json | 24 ++++++++--------- 10 files changed, 88 insertions(+), 24 deletions(-) diff --git a/backend/src/appointment/database/repo/schedule.py b/backend/src/appointment/database/repo/schedule.py index cb98c749b..f91381b67 100644 --- a/backend/src/appointment/database/repo/schedule.py +++ b/backend/src/appointment/database/repo/schedule.py @@ -44,6 +44,12 @@ def exists(db: Session, schedule_id: int): return True if get(db, schedule_id) is not None else False +def is_calendar_connected(db: Session, schedule_id: int) -> bool: + """true if the schedule's calendar is connected""" + schedule: models.Schedule = get(db, schedule_id) + return schedule.calendar and schedule.calendar.connected + + def update(db: Session, schedule: schemas.ScheduleBase, schedule_id: int): """update existing schedule by id""" db_schedule = get(db, schedule_id) diff --git a/backend/src/appointment/database/schemas.py b/backend/src/appointment/database/schemas.py index 7249e1ace..18b5588d2 100644 --- a/backend/src/appointment/database/schemas.py +++ b/backend/src/appointment/database/schemas.py @@ -179,6 +179,7 @@ class Schedule(ScheduleBase): time_created: datetime | None = None time_updated: datetime | None = None availabilities: list[Availability] = [] + calendar: 'CalendarBase' class Config: from_attributes = True diff --git a/backend/src/appointment/routes/api.py b/backend/src/appointment/routes/api.py index bf82179d9..0e00a7351 100644 --- a/backend/src/appointment/routes/api.py +++ b/backend/src/appointment/routes/api.py @@ -1,6 +1,7 @@ import logging import os import secrets +from typing import Annotated import requests.exceptions import validators @@ -18,7 +19,7 @@ # authentication from ..controller.calendar import CalDavConnector, Tools, GoogleConnector -from fastapi import APIRouter, Depends, HTTPException, Body, BackgroundTasks +from fastapi import APIRouter, Depends, HTTPException, Body, BackgroundTasks, Query, Request from datetime import timedelta, timezone from ..controller.apis.google_client import GoogleClient from ..controller.auth import signed_url_by_subscriber @@ -194,19 +195,25 @@ def update_my_calendar( @router.post("/cal/{id}/connect", response_model=schemas.CalendarOut) -def connect_my_calendar( +@router.post("/cal/{id}/disconnect", response_model=schemas.CalendarOut) +def change_my_calendar_connection( + request: Request, id: int, db: Session = Depends(get_db), subscriber: Subscriber = Depends(get_subscriber), ): - """endpoint to update an existing calendar connection for authenticated subscriber""" + """endpoint to update an existing calendar connection for authenticated subscriber + note this function handles both disconnect and connect (the double route is not a typo.)""" if not repo.calendar.exists(db, calendar_id=id): raise validation.CalendarNotFoundException() if not repo.calendar.is_owned(db, calendar_id=id, subscriber_id=subscriber.id): raise validation.CalendarNotAuthorizedException() + # If our path ends with /connect then connect the calendar, otherwise disconnect the calendar + connect = request.scope.get('path', '').endswith('/connect') + try: - cal = repo.calendar.update_connection(db=db, calendar_id=id, is_connected=True) + cal = repo.calendar.update_connection(db=db, calendar_id=id, is_connected=connect) except HTTPException as e: raise HTTPException(status_code=e.status_code, detail=e.detail) return schemas.CalendarOut(id=cal.id, title=cal.title, color=cal.color, connected=cal.connected) diff --git a/backend/src/appointment/routes/schedule.py b/backend/src/appointment/routes/schedule.py index 2305f37b0..8a2d5a814 100644 --- a/backend/src/appointment/routes/schedule.py +++ b/backend/src/appointment/routes/schedule.py @@ -78,6 +78,8 @@ def update_schedule( """endpoint to update an existing calendar connection for authenticated subscriber""" if not repo.schedule.exists(db, schedule_id=id): raise validation.ScheduleNotFoundException() + if not repo.calendar.is_connected(db, calendar_id=schedule.calendar_id): + raise validation.CalendarNotConnectedException() if not repo.schedule.is_owned(db, schedule_id=id, subscriber_id=subscriber.id): raise validation.ScheduleNotAuthorizedException() if schedule.meeting_link_provider == MeetingLinkProviderType.zoom and subscriber.get_external_connection(ExternalConnectionType.zoom) is None: @@ -108,6 +110,10 @@ def read_schedule_availabilities( if not schedule.active: raise validation.ScheduleNotActive() + # check if calendar is connected, if its not then its a schedule not active error + if not schedule.calendar or not schedule.calendar.connected: + raise validation.ScheduleNotActive() + calendars = repo.calendar.get_by_subscriber(db, subscriber.id, False) if not calendars or len(calendars) == 0: diff --git a/frontend/src/components/CalendarManagement.vue b/frontend/src/components/CalendarManagement.vue index 9a761fede..35b2517ab 100644 --- a/frontend/src/components/CalendarManagement.vue +++ b/frontend/src/components/CalendarManagement.vue @@ -47,7 +47,7 @@ {{ t('label.editCalendar') }}