Week view flexibility: configurable day count, layout, and a CalDAV task list
Build and push server image / build-and-push (push) Successful in 52s
Build and push server image / build-and-push (push) Successful in 52s
- Day count (2-10, was fixed at 7) -- 5 days trims the weekend clutter without losing the grid format. - Layout choice: days side by side (original behavior) or stacked vertically as full agenda-style sections (reuses _draw_agenda_day, same approach _build_today_tomorrow already used for a fixed 2 days). - Optional task list (CalDAV VTODO collections only -- a plain ICS subscription doesn't meaningfully have one) that takes the space of one day slot instead of adding an extra one. Same owner-controls- their-own-data permission split as calendar sources: only the calendar's owner can point a frame's task list at it, but anyone linked to the frame can clear it. Browse-offset paging now moves by N days (was hardcoded to weeks), identical to the old behavior when days=7. Changing the day count resets the browse offset, same reasoning as changing views already did.
This commit is contained in:
@@ -44,6 +44,7 @@ from .common import (
|
||||
calendar_sources_for_frame,
|
||||
fetch_source_and_faces,
|
||||
get_or_refresh_calendar_events,
|
||||
get_or_refresh_tasks,
|
||||
get_or_refresh_weather,
|
||||
immich_client_for,
|
||||
immich_creds,
|
||||
@@ -101,8 +102,11 @@ def api_config_save(
|
||||
calendar_view: str | None = Form(None),
|
||||
calendar_photo_inlay: bool | None = Form(None),
|
||||
calendar_week_start: int | None = Form(None),
|
||||
calendar_week_days: int | None = Form(None),
|
||||
calendar_week_layout: str | None = Form(None),
|
||||
calendar_weather_enabled: bool | None = Form(None),
|
||||
calendar_weather_units: str | None = Form(None),
|
||||
calendar_tasks_enabled: bool | None = Form(None),
|
||||
frame: Frame = Depends(require_frame_control),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
@@ -180,6 +184,16 @@ def api_config_save(
|
||||
cfg.calendar_photo_inlay = calendar_photo_inlay
|
||||
if calendar_week_start is not None:
|
||||
cfg.calendar_week_start = max(0, min(6, calendar_week_start))
|
||||
if calendar_week_days is not None:
|
||||
new_days = max(2, min(10, calendar_week_days))
|
||||
if new_days != cfg.calendar_week_days:
|
||||
# A stale offset counts a different-sized page under the
|
||||
# old day count -- same reasoning as calendar_view's own
|
||||
# reset below.
|
||||
cfg.calendar_browse_offset = 0
|
||||
cfg.calendar_week_days = new_days
|
||||
if calendar_week_layout is not None:
|
||||
cfg.calendar_week_layout = calendar_week_layout if calendar_week_layout in ("horizontal", "vertical") else "horizontal"
|
||||
if calendar_weather_enabled is not None:
|
||||
cfg.calendar_weather_enabled = calendar_weather_enabled
|
||||
if calendar_weather_units is not None and calendar_weather_units in ("fahrenheit", "celsius"):
|
||||
@@ -188,6 +202,8 @@ def api_config_save(
|
||||
# rather than showing stale numbers under a new unit label.
|
||||
cfg.calendar_weather_checked_at = 0.0
|
||||
cfg.calendar_weather_units = calendar_weather_units
|
||||
if calendar_tasks_enabled is not None:
|
||||
cfg.calendar_tasks_enabled = calendar_tasks_enabled
|
||||
cfg.stats_config_saves += 1
|
||||
return {"status": "saved"}
|
||||
|
||||
@@ -548,15 +564,51 @@ def api_preview_calendar(frame: Frame = Depends(require_frame_view), db: Session
|
||||
photo_inlay = _calendar_photo_inlay(frame, db)
|
||||
view = frame.calendar_view if frame.calendar_view in calendar_render.CALENDAR_VIEWS else "agenda"
|
||||
weather_cities = get_or_refresh_weather(db, frame)
|
||||
tasks = get_or_refresh_tasks(db, frame) if (view == "week" and frame.calendar_tasks_enabled) else None
|
||||
png = calendar_render.render_calendar_preview_png(
|
||||
events, view=view, browse_offset=frame.calendar_browse_offset, orientation=frame.orientation,
|
||||
palette_rgb=frame.palette_rgb, timezone=frame.timezone, photo_inlay=photo_inlay, fetch_summary=summary,
|
||||
week_start=frame.calendar_week_start,
|
||||
weather_cities=weather_cities, weather_units=frame.calendar_weather_units,
|
||||
week_days=frame.calendar_week_days, week_layout=frame.calendar_week_layout, tasks=tasks,
|
||||
)
|
||||
return Response(content=png, media_type="image/png")
|
||||
|
||||
|
||||
class TasksSourceRequest(BaseModel):
|
||||
calendar_key: str | None # None clears the source
|
||||
|
||||
|
||||
@router.post("/api/frames/{frame_id}/tasks-source")
|
||||
def api_tasks_source(
|
||||
body: TasksSourceRequest,
|
||||
request: Request,
|
||||
frame: Frame = Depends(require_frame_view),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Points this frame's week-view task list at one of the calling
|
||||
user's own CalDAV calendars -- same owner-controls-their-own-data
|
||||
permission split as calendar-select's included=True, since this is
|
||||
volunteering personal calendar data, not a frame-wide display
|
||||
setting a controller should get to pick on someone else's behalf.
|
||||
None clears the source; clearing (unlike setting) isn't
|
||||
ownership-gated -- like muting a shared calendar, anyone linked to
|
||||
the frame can turn off a task list they'd rather not see, but only
|
||||
its owner can point the frame at one of their calendars to begin
|
||||
with."""
|
||||
user = require_user_api(request, db)
|
||||
with frame_locked(db, frame.id) as cfg:
|
||||
if body.calendar_key is None:
|
||||
cfg.calendar_tasks_user_id = None
|
||||
cfg.calendar_tasks_calendar_key = None
|
||||
cfg.calendar_tasks_cached = None
|
||||
else:
|
||||
cfg.calendar_tasks_user_id = user.id
|
||||
cfg.calendar_tasks_calendar_key = body.calendar_key
|
||||
cfg.calendar_tasks_checked_at = 0.0 # pick up the change promptly
|
||||
return {"status": "saved", "calendar_key": body.calendar_key}
|
||||
|
||||
|
||||
class WeatherCityAddRequest(BaseModel):
|
||||
name: str
|
||||
|
||||
|
||||
Reference in New Issue
Block a user