screentinker/frontend/js/views
screentinker 65a24682f0
Stop schedules landing on the wrong date (#284)
Three separate defects all showed up as "I saved a schedule and it moved".

1. expandSchedule emitted two different wire formats. A one-off returned
   start_time untouched - a naive wall-clock string, which the browser parses
   in its own zone - while a recurring instance returned cursor.toISOString(),
   an absolute instant derived by reading that same string in the SERVER's
   zone. The browser converted it back and the two conversions do not cancel:
   an operator in Tokyo saving Wednesday 20:00 got Thursday 10:00 from a
   US-Central server. Only recurring schedules were affected, which is why it
   looked intermittent.

   The calendar was also the odd one out. services/scheduler.js compares
   start_time as a string and never builds a Date from it, so expandSchedule
   was the only place in the codebase treating a wall-clock time as an
   instant - the drawing disagreed with playback as well as with the browser.

2. Saving an edit moved the schedule to today. The save handler rebuilds
   start_time from `pendingCreateDate || new Date()`, and editSchedule()
   restored only HH:MM - it never recorded the date being edited. Changing a
   colour on a block dated 5 Aug rewrote it to this week. No timezone
   mismatch required; this one hit everybody and silently altered stored data.

3. A cancelled drag-create leaked its date into the next schedule.
   pendingCreateDate was cleared only on a successful save, and the modal's
   two dismissers are inline onclick="...display='none'" attributes that
   cannot reach that scope. The date is now assigned by every path that OPENS
   the modal, so no dismissal path can leave a stale value behind.

Tests assert the property rather than a literal: that the wire value is
wall-clock and that the day survives a server/browser zone mismatch in BOTH
directions. A literal-string assertion would pass just as happily with the
bug present on a differently-configured CI box. Both new files fail on the
parent commit and pass here; the schedule, calendar and timezone suites are
green at 85 tests.


Claude-Session: https://claude.ai/code/session_014kfhrUPit5MCqxeTQyqr56

Co-authored-by: Dan Walters <dan.walters@bytetinker.net>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:14:23 -05:00
..
activity.js Stop eight dashboard views reporting success for requests the server refused 2026-07-30 21:21:56 -05:00
admin-player-debug.js Add player debug overlay and server-side error telemetry sink 2026-05-15 15:20:42 -05:00
admin.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00
billing.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00
content-library.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00
dashboard.js Opt-in install statistics (#267) 2026-08-13 17:27:10 -05:00
designer.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00
device-detail.js Check what is IN a cached update, and add a way to throw it away (#274) 2026-08-14 08:37:05 -05:00
force-password-change.js feat(admin): admin-provisioned user creation + first-login gate (#10) 2026-06-05 11:03:56 -05:00
help.js Describe a portrait video wall as portrait, and stop a wall hiding its screens 2026-08-06 09:46:31 -05:00
kiosk.js Stop eight dashboard views reporting success for requests the server refused 2026-07-30 21:21:56 -05:00
layout-editor.js Portrait templates, a canvas that matches the layout, and a playlist mockup 2026-08-05 13:23:15 -05:00
login.js Let an existing account move to SSO, and ask who you are before how 2026-08-12 11:48:11 -05:00
no-workspace.js feat(signup): optional org-on-create for self-service signups (#12) 2026-06-05 11:16:27 -05:00
onboarding.js Default a video playlist item to the clip's own length (#237) 2026-08-06 09:36:53 -05:00
playlists.js Merge #239: let the playlist preview skip to any item 2026-08-06 09:52:20 -05:00
reports.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00
schedule.js Stop schedules landing on the wrong date (#284) 2026-08-18 09:14:23 -05:00
settings.js Install statistics: send on opt-in, name a blocked firewall, and add an operator collector (#268) 2026-08-13 19:00:37 -05:00
teams.js Stop eight dashboard views reporting success for requests the server refused 2026-07-30 21:21:56 -05:00
video-wall.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00
widgets.js Keep the widget editor's Preview isolated, whatever the org setting says 2026-08-11 15:53:57 -05:00
workspace-members.js Escape user-controlled data at the HTML sinks it actually reaches 2026-08-11 11:44:10 -05:00