Week view: relative start-day offset for non-7-day counts; hide week-only settings elsewhere
Build and push server image / build-and-push (push) Successful in 53s
Build and push server image / build-and-push (push) Successful in 53s
calendar_week_start's fixed-weekday anchor ("start on the most recent
Monday") stops making sense once the view isn't a literal calendar
week, so a non-7-day week view now starts calendar_week_start_offset
days from today instead (0 = starts today, negative/positive = past/
future) -- calendar_week_start still governs at the default 7 days,
unchanged.
Also hides the Calendar tab's week-only fields (days to show, layout,
start offset) unless View is actually set to Week, and further hides
the new start-offset field specifically when Days to show is 7 (where
it has no effect). "Week starts on" stays visible for Month too, since
it actually still applies there.
This commit is contained in:
@@ -642,7 +642,8 @@ def _build_today_tomorrow(events: list[dict], browse_offset: int, orientation: s
|
|||||||
def _build_week(events: list[dict], browse_offset: int, orientation: str, tz: ZoneInfo,
|
def _build_week(events: list[dict], browse_offset: int, orientation: str, tz: ZoneInfo,
|
||||||
photo_inlay: Image.Image | None, week_start: int, palette_rgb: list | None = None,
|
photo_inlay: Image.Image | None, week_start: int, palette_rgb: list | None = None,
|
||||||
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
||||||
days: int = 7, layout: str = "horizontal", tasks: list[dict] | None = None) -> Image.Image:
|
days: int = 7, layout: str = "horizontal", tasks: list[dict] | None = None,
|
||||||
|
start_offset: int = 0) -> Image.Image:
|
||||||
"""`days` (2-10, see routers/api_frames.py's clamp) side-by-side
|
"""`days` (2-10, see routers/api_frames.py's clamp) side-by-side
|
||||||
columns (layout="horizontal", the original fixed-at-7 behavior
|
columns (layout="horizontal", the original fixed-at-7 behavior
|
||||||
generalized) or stacked bands (layout="vertical", reusing
|
generalized) or stacked bands (layout="vertical", reusing
|
||||||
@@ -650,7 +651,13 @@ def _build_week(events: list[dict], browse_offset: int, orientation: str, tz: Zo
|
|||||||
an arbitrary day count instead of a hardcoded 2). `tasks` (see
|
an arbitrary day count instead of a hardcoded 2). `tasks` (see
|
||||||
routers/common.py's get_or_refresh_tasks), if not None, takes the
|
routers/common.py's get_or_refresh_tasks), if not None, takes the
|
||||||
LAST slot instead of adding an extra one -- "N days" always means N
|
LAST slot instead of adding an extra one -- "N days" always means N
|
||||||
slots total, whether they're all days or N-1 days plus a task list."""
|
slots total, whether they're all days or N-1 days plus a task list.
|
||||||
|
|
||||||
|
At the default 7 days, the view anchors to week_start (a fixed
|
||||||
|
weekday, "start on the most recent Monday") exactly like before --
|
||||||
|
otherwise "start of the week" doesn't mean much for an arbitrary day
|
||||||
|
count, so it instead starts `start_offset` days from today (0 =
|
||||||
|
today, see routers/api_frames.py's api_config_save)."""
|
||||||
logical_w, logical_h = logical_render_size(orientation)
|
logical_w, logical_h = logical_render_size(orientation)
|
||||||
img = Image.new("RGB", (logical_w, logical_h), BG)
|
img = Image.new("RGB", (logical_w, logical_h), BG)
|
||||||
if photo_inlay is not None:
|
if photo_inlay is not None:
|
||||||
@@ -659,8 +666,11 @@ def _build_week(events: list[dict], browse_offset: int, orientation: str, tz: Zo
|
|||||||
draw = ImageDraw.Draw(img)
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
today = datetime.now(tz).date()
|
today = datetime.now(tz).date()
|
||||||
|
if days == 7:
|
||||||
days_since_start = (today.weekday() - week_start) % 7
|
days_since_start = (today.weekday() - week_start) % 7
|
||||||
week_first_day = today - timedelta(days=days_since_start) + timedelta(days=days * browse_offset)
|
week_first_day = today - timedelta(days=days_since_start) + timedelta(days=days * browse_offset)
|
||||||
|
else:
|
||||||
|
week_first_day = today + timedelta(days=start_offset) + timedelta(days=days * browse_offset)
|
||||||
day_count = days - 1 if tasks is not None else days
|
day_count = days - 1 if tasks is not None else days
|
||||||
owners_seen: list[str] = []
|
owners_seen: list[str] = []
|
||||||
|
|
||||||
@@ -802,7 +812,8 @@ def _build(events: list[dict], view: str, browse_offset: int, orientation: str,
|
|||||||
photo_inlay: Image.Image | None, fetch_summary: str, week_start: int,
|
photo_inlay: Image.Image | None, fetch_summary: str, week_start: int,
|
||||||
palette_rgb: list | None = None,
|
palette_rgb: list | None = None,
|
||||||
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
||||||
week_days: int = 7, week_layout: str = "horizontal", tasks: list[dict] | None = None) -> Image.Image:
|
week_days: int = 7, week_layout: str = "horizontal", tasks: list[dict] | None = None,
|
||||||
|
week_start_offset: int = 0) -> Image.Image:
|
||||||
tz = ZoneInfo(timezone) if timezone else ZoneInfo("UTC")
|
tz = ZoneInfo(timezone) if timezone else ZoneInfo("UTC")
|
||||||
if view == "agenda":
|
if view == "agenda":
|
||||||
img = _build_agenda(events, browse_offset, orientation, tz, photo_inlay, palette_rgb,
|
img = _build_agenda(events, browse_offset, orientation, tz, photo_inlay, palette_rgb,
|
||||||
@@ -812,7 +823,7 @@ def _build(events: list[dict], view: str, browse_offset: int, orientation: str,
|
|||||||
weather_cities, weather_units)
|
weather_cities, weather_units)
|
||||||
elif view == "week":
|
elif view == "week":
|
||||||
img = _build_week(events, browse_offset, orientation, tz, photo_inlay, week_start, palette_rgb,
|
img = _build_week(events, browse_offset, orientation, tz, photo_inlay, week_start, palette_rgb,
|
||||||
weather_cities, weather_units, week_days, week_layout, tasks)
|
weather_cities, weather_units, week_days, week_layout, tasks, week_start_offset)
|
||||||
elif view == "month":
|
elif view == "month":
|
||||||
# Never given weather or tasks -- no room for either at typical
|
# Never given weather or tasks -- no room for either at typical
|
||||||
# month-cell size, same reasoning that already keeps this view
|
# month-cell size, same reasoning that already keeps this view
|
||||||
@@ -839,7 +850,7 @@ def render_calendar(events: list[dict], view: str, browse_offset: int, orientati
|
|||||||
fetch_summary: str = "", manage: dict | None = None, week_start: int = 0,
|
fetch_summary: str = "", manage: dict | None = None, week_start: int = 0,
|
||||||
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
||||||
week_days: int = 7, week_layout: str = "horizontal",
|
week_days: int = 7, week_layout: str = "horizontal",
|
||||||
tasks: list[dict] | None = None) -> bytes:
|
tasks: list[dict] | None = None, week_start_offset: int = 0) -> bytes:
|
||||||
"""Renders one of CALENDAR_VIEWS to the panel's packed format. Always
|
"""Renders one of CALENDAR_VIEWS to the panel's packed format. Always
|
||||||
returns exactly EPD_WIDTH*EPD_HEIGHT/2 bytes, same invariant every
|
returns exactly EPD_WIDTH*EPD_HEIGHT/2 bytes, same invariant every
|
||||||
other renderer honors. weather_cities is routers/common.py's
|
other renderer honors. weather_cities is routers/common.py's
|
||||||
@@ -848,7 +859,7 @@ def render_calendar(events: list[dict], view: str, browse_offset: int, orientati
|
|||||||
get_or_refresh_tasks()'s cache, or None to omit the task list
|
get_or_refresh_tasks()'s cache, or None to omit the task list
|
||||||
entirely -- only ever drawn for view == "week", see _build_week."""
|
entirely -- only ever drawn for view == "week", see _build_week."""
|
||||||
img = _build(events, view, browse_offset, orientation, timezone, photo_inlay, fetch_summary, week_start,
|
img = _build(events, view, browse_offset, orientation, timezone, photo_inlay, fetch_summary, week_start,
|
||||||
palette_rgb, weather_cities, weather_units, week_days, week_layout, tasks)
|
palette_rgb, weather_cities, weather_units, week_days, week_layout, tasks, week_start_offset)
|
||||||
img = _apply_manage_overlay(img, manage)
|
img = _apply_manage_overlay(img, manage)
|
||||||
quantized = _quantize(img, palette_rgb, dither_strength=1.0)
|
quantized = _quantize(img, palette_rgb, dither_strength=1.0)
|
||||||
return _transpose_and_pack(quantized, orientation)
|
return _transpose_and_pack(quantized, orientation)
|
||||||
@@ -859,12 +870,12 @@ def render_calendar_preview_png(events: list[dict], view: str, browse_offset: in
|
|||||||
fetch_summary: str = "", manage: dict | None = None, week_start: int = 0,
|
fetch_summary: str = "", manage: dict | None = None, week_start: int = 0,
|
||||||
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
weather_cities: list[dict] | None = None, weather_units: str = "fahrenheit",
|
||||||
week_days: int = 7, week_layout: str = "horizontal",
|
week_days: int = 7, week_layout: str = "horizontal",
|
||||||
tasks: list[dict] | None = None) -> bytes:
|
tasks: list[dict] | None = None, week_start_offset: int = 0) -> bytes:
|
||||||
"""Same pipeline as render_calendar, but a normal browser-viewable
|
"""Same pipeline as render_calendar, but a normal browser-viewable
|
||||||
PNG in logical (upright) orientation -- mirrors
|
PNG in logical (upright) orientation -- mirrors
|
||||||
image_pipeline.render_preview_png's relationship to render_frame."""
|
image_pipeline.render_preview_png's relationship to render_frame."""
|
||||||
img = _build(events, view, browse_offset, orientation, timezone, photo_inlay, fetch_summary, week_start,
|
img = _build(events, view, browse_offset, orientation, timezone, photo_inlay, fetch_summary, week_start,
|
||||||
palette_rgb, weather_cities, weather_units, week_days, week_layout, tasks)
|
palette_rgb, weather_cities, weather_units, week_days, week_layout, tasks, week_start_offset)
|
||||||
img = _apply_manage_overlay(img, manage)
|
img = _apply_manage_overlay(img, manage)
|
||||||
quantized = _quantize(img, palette_rgb, dither_strength=1.0)
|
quantized = _quantize(img, palette_rgb, dither_strength=1.0)
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
|
|||||||
@@ -189,6 +189,16 @@ def _migration_12(conn) -> None:
|
|||||||
conn.execute(text("ALTER TABLE frames ADD COLUMN calendar_tasks_cached TEXT"))
|
conn.execute(text("ALTER TABLE frames ADD COLUMN calendar_tasks_cached TEXT"))
|
||||||
|
|
||||||
|
|
||||||
|
def _migration_13(conn) -> None:
|
||||||
|
"""A day-count-relative start offset for the week view
|
||||||
|
(calendar_week_start_offset), used instead of calendar_week_start's
|
||||||
|
fixed-weekday anchor once the view isn't a literal 7-day week --
|
||||||
|
"start on the most recent Monday" stops meaning much for e.g. a
|
||||||
|
5-day view. Default 0 (starts today) is a behavior-preserving no-op
|
||||||
|
until someone changes the day count away from 7."""
|
||||||
|
conn.execute(text("ALTER TABLE frames ADD COLUMN calendar_week_start_offset INTEGER NOT NULL DEFAULT 0"))
|
||||||
|
|
||||||
|
|
||||||
MIGRATIONS = [
|
MIGRATIONS = [
|
||||||
(1, _migration_1),
|
(1, _migration_1),
|
||||||
(2, _migration_2),
|
(2, _migration_2),
|
||||||
@@ -202,6 +212,7 @@ MIGRATIONS = [
|
|||||||
(10, _migration_10),
|
(10, _migration_10),
|
||||||
(11, _migration_11),
|
(11, _migration_11),
|
||||||
(12, _migration_12),
|
(12, _migration_12),
|
||||||
|
(13, _migration_13),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,15 @@ class Frame(Base):
|
|||||||
# columns or stacked bands (see calendar_render.py's _build_week).
|
# columns or stacked bands (see calendar_render.py's _build_week).
|
||||||
calendar_week_days: Mapped[int] = mapped_column(Integer, default=7)
|
calendar_week_days: Mapped[int] = mapped_column(Integer, default=7)
|
||||||
calendar_week_layout: Mapped[str] = mapped_column(String, default="horizontal") # "horizontal" | "vertical"
|
calendar_week_layout: Mapped[str] = mapped_column(String, default="horizontal") # "horizontal" | "vertical"
|
||||||
|
# Only used when calendar_week_days != 7 -- calendar_week_start's
|
||||||
|
# fixed-weekday anchor ("start on the most recent Monday") stops
|
||||||
|
# making sense once the view isn't a literal calendar week, so a
|
||||||
|
# non-7-day view instead starts this many days from today (0 =
|
||||||
|
# starts today, negative = starts in the past, positive = starts in
|
||||||
|
# the future). Ignored (calendar_week_start governs instead) at the
|
||||||
|
# default 7 days, so this has no effect until someone actually
|
||||||
|
# changes the day count.
|
||||||
|
calendar_week_start_offset: Mapped[int] = mapped_column(Integer, default=0)
|
||||||
|
|
||||||
# Optional task list, week view only -- takes the space of one day
|
# Optional task list, week view only -- takes the space of one day
|
||||||
# slot rather than adding an extra one (see calendar_render.py's
|
# slot rather than adding an extra one (see calendar_render.py's
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ def api_config_save(
|
|||||||
calendar_week_start: int | None = Form(None),
|
calendar_week_start: int | None = Form(None),
|
||||||
calendar_week_days: int | None = Form(None),
|
calendar_week_days: int | None = Form(None),
|
||||||
calendar_week_layout: str | None = Form(None),
|
calendar_week_layout: str | None = Form(None),
|
||||||
|
calendar_week_start_offset: int | None = Form(None),
|
||||||
calendar_weather_enabled: bool | None = Form(None),
|
calendar_weather_enabled: bool | None = Form(None),
|
||||||
calendar_weather_units: str | None = Form(None),
|
calendar_weather_units: str | None = Form(None),
|
||||||
calendar_tasks_enabled: bool | None = Form(None),
|
calendar_tasks_enabled: bool | None = Form(None),
|
||||||
@@ -194,6 +195,11 @@ def api_config_save(
|
|||||||
cfg.calendar_week_days = new_days
|
cfg.calendar_week_days = new_days
|
||||||
if calendar_week_layout is not None:
|
if calendar_week_layout is not None:
|
||||||
cfg.calendar_week_layout = calendar_week_layout if calendar_week_layout in ("horizontal", "vertical") else "horizontal"
|
cfg.calendar_week_layout = calendar_week_layout if calendar_week_layout in ("horizontal", "vertical") else "horizontal"
|
||||||
|
if calendar_week_start_offset is not None:
|
||||||
|
new_offset = max(-30, min(30, calendar_week_start_offset))
|
||||||
|
if new_offset != cfg.calendar_week_start_offset:
|
||||||
|
cfg.calendar_browse_offset = 0
|
||||||
|
cfg.calendar_week_start_offset = new_offset
|
||||||
if calendar_weather_enabled is not None:
|
if calendar_weather_enabled is not None:
|
||||||
cfg.calendar_weather_enabled = calendar_weather_enabled
|
cfg.calendar_weather_enabled = calendar_weather_enabled
|
||||||
if calendar_weather_units is not None and calendar_weather_units in ("fahrenheit", "celsius"):
|
if calendar_weather_units is not None and calendar_weather_units in ("fahrenheit", "celsius"):
|
||||||
@@ -571,6 +577,7 @@ def api_preview_calendar(frame: Frame = Depends(require_frame_view), db: Session
|
|||||||
week_start=frame.calendar_week_start,
|
week_start=frame.calendar_week_start,
|
||||||
weather_cities=weather_cities, weather_units=frame.calendar_weather_units,
|
weather_cities=weather_cities, weather_units=frame.calendar_weather_units,
|
||||||
week_days=frame.calendar_week_days, week_layout=frame.calendar_week_layout, tasks=tasks,
|
week_days=frame.calendar_week_days, week_layout=frame.calendar_week_layout, tasks=tasks,
|
||||||
|
week_start_offset=frame.calendar_week_start_offset,
|
||||||
)
|
)
|
||||||
return Response(content=png, media_type="image/png")
|
return Response(content=png, media_type="image/png")
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ def _render_calendar_mode(db: Session, frame: Frame, request: Request, manage: d
|
|||||||
week_start = locked.calendar_week_start
|
week_start = locked.calendar_week_start
|
||||||
week_days = locked.calendar_week_days
|
week_days = locked.calendar_week_days
|
||||||
week_layout = locked.calendar_week_layout
|
week_layout = locked.calendar_week_layout
|
||||||
|
week_start_offset = locked.calendar_week_start_offset
|
||||||
inlay_wanted = locked.calendar_photo_inlay
|
inlay_wanted = locked.calendar_photo_inlay
|
||||||
|
|
||||||
events, summary = get_or_refresh_calendar_events(db, frame)
|
events, summary = get_or_refresh_calendar_events(db, frame)
|
||||||
@@ -183,7 +184,7 @@ def _render_calendar_mode(db: Session, frame: Frame, request: Request, manage: d
|
|||||||
palette_rgb=frame.palette_rgb, timezone=frame.timezone,
|
palette_rgb=frame.palette_rgb, timezone=frame.timezone,
|
||||||
photo_inlay=photo_inlay, fetch_summary=summary, manage=manage, week_start=week_start,
|
photo_inlay=photo_inlay, fetch_summary=summary, manage=manage, week_start=week_start,
|
||||||
weather_cities=weather_cities, weather_units=frame.calendar_weather_units,
|
weather_cities=weather_cities, weather_units=frame.calendar_weather_units,
|
||||||
week_days=week_days, week_layout=week_layout, tasks=tasks,
|
week_days=week_days, week_layout=week_layout, tasks=tasks, week_start_offset=week_start_offset,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
// Calendar card became its own tab (window.FRAME_API is set by the
|
// Calendar card became its own tab (window.FRAME_API is set by the
|
||||||
// template; checkboxes are always sent explicitly as "true"/"false").
|
// template; checkboxes are always sent explicitly as "true"/"false").
|
||||||
|
|
||||||
|
// Week-view-only settings (days/layout/start-offset) only matter when
|
||||||
|
// View is actually "Week"; "Week starts on" also matters for Month, so
|
||||||
|
// it gets its own, slightly looser condition. The start-offset row is
|
||||||
|
// further gated on the day count -- it's meaningless at the default 7
|
||||||
|
// days, where "Week starts on" governs instead (see
|
||||||
|
// calendar_render.py's _build_week).
|
||||||
|
function updateCalendarFieldVisibility() {
|
||||||
|
const view = document.getElementById('calendar_view').value;
|
||||||
|
const days = Number(document.getElementById('calendar_week_days').value);
|
||||||
|
const isWeek = view === 'week';
|
||||||
|
document.getElementById('calendar-week-start-row').style.display =
|
||||||
|
(view === 'week' || view === 'month') ? '' : 'none';
|
||||||
|
document.getElementById('calendar-week-days-row').style.display = isWeek ? '' : 'none';
|
||||||
|
document.getElementById('calendar-week-layout-row').style.display = isWeek ? '' : 'none';
|
||||||
|
document.getElementById('calendar-week-offset-row').style.display = (isWeek && days !== 7) ? '' : 'none';
|
||||||
|
}
|
||||||
|
document.getElementById('calendar_view').addEventListener('change', updateCalendarFieldVisibility);
|
||||||
|
document.getElementById('calendar_week_days').addEventListener('input', updateCalendarFieldVisibility);
|
||||||
|
updateCalendarFieldVisibility();
|
||||||
|
|
||||||
document.getElementById('calendar-config-form').addEventListener('submit', async (e) => {
|
document.getElementById('calendar-config-form').addEventListener('submit', async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const body = new URLSearchParams({
|
const body = new URLSearchParams({
|
||||||
@@ -10,6 +30,7 @@ document.getElementById('calendar-config-form').addEventListener('submit', async
|
|||||||
calendar_week_start: document.getElementById('calendar_week_start').value,
|
calendar_week_start: document.getElementById('calendar_week_start').value,
|
||||||
calendar_week_days: document.getElementById('calendar_week_days').value,
|
calendar_week_days: document.getElementById('calendar_week_days').value,
|
||||||
calendar_week_layout: document.getElementById('calendar_week_layout').value,
|
calendar_week_layout: document.getElementById('calendar_week_layout').value,
|
||||||
|
calendar_week_start_offset: document.getElementById('calendar_week_start_offset').value,
|
||||||
calendar_photo_inlay: String(document.getElementById('calendar_photo_inlay').checked),
|
calendar_photo_inlay: String(document.getElementById('calendar_photo_inlay').checked),
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<div id="calendar-week-start-row">
|
||||||
<label>Week starts on
|
<label>Week starts on
|
||||||
<select id="calendar_week_start">
|
<select id="calendar_week_start">
|
||||||
{% for value, label in week_start_labels.items() %}
|
{% for value, label in week_start_labels.items() %}
|
||||||
@@ -38,16 +39,28 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<p class="sub" style="margin-top: 4px;">Only affects the Week and Month views.</p>
|
<p class="sub" style="margin-top: 4px;">Only affects the Week and Month views, and (for Week) only at 7 days.</p>
|
||||||
|
</div>
|
||||||
|
<div id="calendar-week-days-row">
|
||||||
<label>Days to show (Week view)
|
<label>Days to show (Week view)
|
||||||
<input type="number" id="calendar_week_days" min="2" max="10" value="{{ frame.calendar_week_days }}">
|
<input type="number" id="calendar_week_days" min="2" max="10" value="{{ frame.calendar_week_days }}">
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div id="calendar-week-layout-row">
|
||||||
<label>Week view layout
|
<label>Week view layout
|
||||||
<select id="calendar_week_layout">
|
<select id="calendar_week_layout">
|
||||||
<option value="horizontal" {% if frame.calendar_week_layout == "horizontal" %}selected{% endif %}>Days side by side</option>
|
<option value="horizontal" {% if frame.calendar_week_layout == "horizontal" %}selected{% endif %}>Days side by side</option>
|
||||||
<option value="vertical" {% if frame.calendar_week_layout == "vertical" %}selected{% endif %}>Days stacked</option>
|
<option value="vertical" {% if frame.calendar_week_layout == "vertical" %}selected{% endif %}>Days stacked</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div id="calendar-week-offset-row">
|
||||||
|
<label>Week view starts (days from today)
|
||||||
|
<input type="number" id="calendar_week_start_offset" min="-30" max="30" value="{{ frame.calendar_week_start_offset }}">
|
||||||
|
</label>
|
||||||
|
<p class="sub" style="margin-top: 4px;">0 = starts today, negative = starts in the
|
||||||
|
past, positive = starts in the future. Only used when Days to show isn't 7.</p>
|
||||||
|
</div>
|
||||||
<div class="checkbox-row" id="calendar-inlay-row">
|
<div class="checkbox-row" id="calendar-inlay-row">
|
||||||
<input type="checkbox" id="calendar_photo_inlay" {% if frame.calendar_photo_inlay %}checked{% endif %}>
|
<input type="checkbox" id="calendar_photo_inlay" {% if frame.calendar_photo_inlay %}checked{% endif %}>
|
||||||
<label for="calendar_photo_inlay">Show a photo alongside the calendar</label>
|
<label for="calendar_photo_inlay">Show a photo alongside the calendar</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user