refactor: Extract timetable template to its own component#3229
Merged
Conversation
…ll />` component
…arate components
thecristen
requested changes
Jun 4, 2026
Collaborator
thecristen
left a comment
There was a problem hiding this comment.
There are three broken tests from the old timetable view test file, please fix!
I think the rest looks and works great. 🚀
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
The end goal of this work is to have a timetable component whose invocation will be (almost) as simple as
<.timetable timetable={@timetable} />. That will make it easier to render the Harbor Loop Ferry with two timetables on the same page, and give us more flexibility in how we render different types of timetable pages in the future.This PR goes about halfway - it splits out a separate component for the timetable (actually two... more on that in a moment), and adds more structure to the
%Timetable{}struct, introduced in #3206. The remaining refactor work is to pull the last bits of non-user-interaction data (i.e. alerts) into theTimetablesmodule. Once we do that, rendering a different layout for the Harbor Loop Ferry should be almost trivial.Two timetables?
We already have two different timetable implementations, although they're currently kind of muddled together, using the somewhat opaquely-named
use_pdf_schedules?flag.use_pdf_schedules?is true, then the timetable template expects@timetable_schedules,@header_stops, and@header_schedulesto be set.use_pdf_schedules?is false, then the timetable still expects@header_stopsand@header_schedulesto be set, but it gets its cell data from@trip_schedulesand@trip_messagesinstead (along with data from a few other fields, like@track_changes.A core part of this PR makes is to explicitly separate those two implementations into
<.linear_timetable />(so named because it can't support loops or trips that visit the same stops in different orders, and<.timetable />, which has no such constraint, but has fewer features (e.g. it doesn't support track changes... for now!). Most of the rest of this PR is cleanup around the edges of the contract between<.timetable />and the template that calls it, as well as the%Timetable{}struct that gets passed in.Asana Ticket: ⛴️ Make timetable its own component(s)
Implementation
Warning
This PR is quite large, so I'll walk through it commit-by-commit.
Groundwork
Tip
These commits lay the groundwork for all of the upcoming work - converting a bunch of HEEx code into components and updating some out-dated variable names
_timetable_scheduletemplate into<.timetable_cell />componentuse_pdf_timetable?tolinear_timetable?and swap the senseCleanup
Tip
A lot of the commits in this PR are relatively minor cleanup's around the edges. This is the first instance of those.
content_taginvocations with regular HEEx code<.timetable_cell_wrapper />and remove unnecessary variables@valuesyntax instead ofassigns[:value]assigns[:value]invocations were necessary when this code was in the template, but the way I pulled them into the component meant they were guaranteed to always be assigned (even if they were assigned asnil), meaning that@valueshould work just fine now.|| %{}was inside of the lookup[brackets]- i.e.map[key || %{}]. I'm guessing it was originally intended to bemap[key] || %{}, but the fact that everything already worked (and thatkeyin this context was guaranteed never to be falsey), means that it was easier to just get rid of the|| %{}entirely.Two timetables!
Tip
See discussion above. This is where I split the timetable glob into two fully different components and trimmed down the attributes passed into each.
<.timetable />and<.linear_timetable />into separate componentscell_backgroundin a function and remove a for loop<.stop_header_cell />@timetable_schedulesinstead of@header_stops%Timetable{}structTip
This section is where I started adding more structure to the
%Timetable{}struct and integrating it more tightly with the timetable component.timetabledirectly to theconninstead oftimetable_schedulesheader_tripsinstead ofheader_schedulesin the timetable@header_schedulesnot required in timetable templatestop_idfield from%Timetable.Cell{}Timetablesmodule was first introduced, it didn't deal with%Schedules.Trip{}structs at all, sotripswas a relatively non-confusing name for a list of%Schedule{}-lists (the schedules for a trip). This PR added handling for actual trip structs, so finding a new name for the variable formerly known astripsbecame much more virtuous.Screenshots
No visual changes.
How to test
This should have no actual changes, so take a look at some timetables for commuter rail and timetables for ferry (don't forget the loop ferry routes) and compare them to their prod equivalents.
Note
The Harbor Loop Ferry doesn't start until June 29, and doesn't run on weekends, so the fact that it doesn't a show a timetable for today is a feature, not a bug.