Files
LEDMatrix/web_interface/static/v3/js
Chuck fe5c1d0d5e feat(web): add Google Calendar picker widget for dynamic multi-calendar selection (#274)
* fix(install): add --prefer-binary to pip installs to avoid /tmp exhaustion

timezonefinder (~54 MB) includes large timezone polygon data files that pip
unpacks into /tmp during installation. On Raspberry Pi, the default tmpfs
/tmp size (often ~half of RAM) can be too small, causing the install to fail
with an out-of-space error.

Adding --prefer-binary tells pip to prefer pre-built binary wheels over
source distributions. Since timezonefinder and most other packages publish
wheels on PyPI (and piwheels.org has ARM wheels), this avoids the large
temporary /tmp extraction and speeds up installs generally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(timezone): use America/New_York instead of EST for ESPN API date queries

EST is a fixed UTC-5 offset that does not observe daylight saving time,
causing the ESPN API date to be off by one hour during EDT (March–November).
America/New_York correctly handles DST transitions.

The ESPN scoreboard API anchors its schedule calendar to Eastern US time,
so this Eastern timezone is intentionally kept for the API date — it is not
user-configurable. Game time display is converted separately to the user's
configured timezone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(web): add Google Calendar picker widget for dynamic calendar selection

Adds a new google-calendar-picker widget and API endpoint that lets users
load their available Google Calendars by name and check the ones they want,
instead of manually typing calendar IDs.

- GET /api/v3/plugins/calendar/list-calendars — calls plugin.get_calendars()
  and returns all accessible calendars with id, summary, and primary flag
- google-calendar-picker.js — new widget: "Load My Calendars" button renders
  a checklist; selections update a hidden comma-separated input for form submit
- plugin_config.html — handles x-widget: google-calendar-picker in array branch
- base.html — loads the new widget script

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(web): address PR review findings in google-calendar-picker

- api_v3.py: replace broad except block with specific exception handling,
  log full traceback via module logger, normalize/validate get_calendars()
  output to stable {id,summary,primary} objects, return opaque user-friendly
  error message instead of leaking str(e)
- google-calendar-picker.js: fix button label only updating to "Refresh
  Calendars" on success (restore original label on error); update summary
  paragraph via syncHiddenAndSummary() on every checkbox change so UI stays
  in sync with hidden input; pass summary element through loadCalendars and
  renderCheckboxes instead of re-querying DOM
- plugin_config.html: bound initWidget retry loop with MAX_RETRIES=40 to
  prevent infinite timers; normalize legacy comma-separated string values
  to arrays before passing to widget.render so pre-existing config populates
  correctly
- install_dependencies_apt.py: update install_via_pip docstring to document
  both --break-system-packages and --prefer-binary flags

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(web): harden list_calendar_calendars input validation

- Remove unused `as e` binding from ValueError/TypeError/KeyError except clause
- Replace hasattr(__iter__) with isinstance(list|tuple) so non-sequence returns
  are rejected before iteration
- Validate each calendar entry is a collections.abc.Mapping; skip and warn on
  malformed items rather than propagating a TypeError
- Coerce id/summary to str safely if not already strings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(web): skip calendar entries with empty id in list_calendar_calendars

After coercing cal_id to str, check it is non-empty before appending to
the calendars list so entries with no usable id are never forwarded to
the client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Chuck <chuck@example.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 18:19:32 -05:00
..
2025-12-27 14:15:49 -05:00
2025-12-27 14:15:49 -05:00
2025-12-27 14:15:49 -05:00
2025-12-27 14:15:49 -05:00
2025-12-27 14:15:49 -05:00
2025-12-27 14:15:49 -05:00