From 51627555bf356c8ec663f4d2f43f2f013eadbce4 Mon Sep 17 00:00:00 2001 From: Tim Baek Date: Mon, 20 Apr 2026 03:35:17 -0400 Subject: [PATCH] refac --- backend/open_webui/models/calendar.py | 1 + backend/open_webui/routers/calendar.py | 10 ++ src/lib/apis/calendar/index.ts | 1 + .../calendar/CalendarSidebar.svelte | 99 +++++++++++++++---- src/routes/(app)/calendar/+page.svelte | 17 ++++ 5 files changed, 108 insertions(+), 20 deletions(-) diff --git a/backend/open_webui/models/calendar.py b/backend/open_webui/models/calendar.py index 4841e7b2dd..dbb070013e 100644 --- a/backend/open_webui/models/calendar.py +++ b/backend/open_webui/models/calendar.py @@ -109,6 +109,7 @@ class CalendarModel(BaseModel): name: str color: Optional[str] = None is_default: bool = False + is_system: bool = False data: Optional[dict] = None meta: Optional[dict] = None diff --git a/backend/open_webui/routers/calendar.py b/backend/open_webui/routers/calendar.py index cde2ea0484..152b932234 100644 --- a/backend/open_webui/routers/calendar.py +++ b/backend/open_webui/routers/calendar.py @@ -101,6 +101,7 @@ async def get_calendars(request: Request, user: UserModel = Depends(get_verified name='Scheduled Tasks', color='#8b5cf6', is_default=False, + is_system=True, created_at=now, updated_at=now, ) @@ -360,12 +361,21 @@ async def update_calendar( @router.delete('/{calendar_id}/delete') async def delete_calendar(request: Request, calendar_id: str, user: UserModel = Depends(get_verified_user)): await check_calendar_permission(request, user) + + # Block deletion of the virtual Scheduled Tasks calendar + if calendar_id == SCHEDULED_TASKS_CALENDAR_ID: + raise HTTPException(status_code=400, detail='System calendars cannot be deleted') + cal = await _check_calendar_access(calendar_id, user, 'write') # Only owner/admin can delete if cal.user_id != user.id and user.role != 'admin': raise HTTPException(status_code=403, detail='Only owner can delete calendar') + # Block deletion of default calendar + if cal.is_default: + raise HTTPException(status_code=400, detail='Default calendar cannot be deleted') + result = await Calendars.delete_calendar_by_id(calendar_id) if not result: raise HTTPException(status_code=500, detail='Failed to delete') diff --git a/src/lib/apis/calendar/index.ts b/src/lib/apis/calendar/index.ts index b496a42bc2..b3148e6c18 100644 --- a/src/lib/apis/calendar/index.ts +++ b/src/lib/apis/calendar/index.ts @@ -6,6 +6,7 @@ export type CalendarModel = { name: string; color: string | null; is_default: boolean; + is_system: boolean; data: Record | null; meta: Record | null; access_grants: any[]; diff --git a/src/lib/components/calendar/CalendarSidebar.svelte b/src/lib/components/calendar/CalendarSidebar.svelte index dc98df05e0..7ffec382ea 100644 --- a/src/lib/components/calendar/CalendarSidebar.svelte +++ b/src/lib/components/calendar/CalendarSidebar.svelte @@ -1,6 +1,7 @@ + +
@@ -148,27 +179,55 @@
{#each calendars as cal (cal.id)} - + + + {cal.name} + + + + {#if isDeletable(cal)} + + {/if} +
{/each} diff --git a/src/routes/(app)/calendar/+page.svelte b/src/routes/(app)/calendar/+page.svelte index 0e19127fd8..ec61a27eb9 100644 --- a/src/routes/(app)/calendar/+page.svelte +++ b/src/routes/(app)/calendar/+page.svelte @@ -6,6 +6,7 @@ import { getCalendars, getCalendarEvents, + deleteCalendar, type CalendarModel, type CalendarEventModel } from '$lib/apis/calendar'; @@ -111,6 +112,21 @@ visibleCalendarIds = next; } + async function handleDeleteCalendar(id: string) { + try { + const result = await deleteCalendar(localStorage.token, id); + if (result) { + toast.success($i18n.t('Calendar deleted')); + await loadCalendars(); + await refresh(); + } else { + toast.error($i18n.t('Failed to delete calendar')); + } + } catch (err) { + toast.error(`${err}`); + } + } + function handleCreateEvent(e: CustomEvent<{ start_at: number }>) { editEvent = null; defaultStartAt = e.detail.start_at; @@ -334,6 +350,7 @@ {visibleCalendarIds} {currentDate} onToggle={toggleCalendar} + onDeleteCalendar={handleDeleteCalendar} onDateSelect={handleDateSelect} />