calendar-dates only service handling #108
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
gtfs.zone/coloring-book#108
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
GTFS allows a
service_idto be defined exclusively incalendar_dates.txtwith no corresponding row incalendar.txt. The codebase has two gaps when this occurs:calendar, so calendar_dates-only services never appear in it.The fix for both gaps is straightforward: union data from both tables where only
calendaris currently read, and derive the date range from the existing exception dates rather than defaulting to today.Relevant context
src/modules/page-content-renderer.ts:renderRoute(~L458): buildsallServicesfromgetAllRows('calendar')only (~L509). Uses it to populate the "Add timetable for service"<select>. The rendering code callsgetServiceDisplay(service)which already falls back toservice_idas the label, so synthesized records with only aservice_idfield render fine.src/modules/service-days-controller.ts:renderServiceEditorHTML(~L415): callsrenderWeeklyPattern,renderDateRange, andrenderExceptionswithcalendar(which isnullfor calendar_dates-only services).renderWeeklyPattern(~L456): already renders all buttons unselected whencalendaris null — no change needed.renderDateRange(~L492): derives start/end fromcalendar?.start_date/calendar?.end_date— both are empty strings whencalendaris null, producing blank inputs.matchPatterns(~L706): already falls back to min/max of exception dates whencalendaris null (lines ~L712-719) — exceptions section renders correctly as-is.toggleDay(~L168): whencalendaris null, creates a newcalendar.txtentry withstart_date=today,end_date=today+1year, then records it viapatchManager.recordInsert.updateDateRange(~L244): same null-calendar fallback with today/today+1year.Phase 1 — Fix "Add timetable" dropdown
File:
src/modules/page-content-renderer.tsThe dropdown only shows services from
calendar. Services defined only incalendar_dates.txtare invisible even though trips can (and should) reference them.renderRoute()(~L509): after fetchingallServicesfromcalendar, also fetch all rows fromcalendar_datesviathis.dependencies.gtfsDatabase.getAllRows('calendar_dates').Set<string>of service_ids already present inallServices.calendar_datesrows byservice_id(one row per date, so many rows per service) and, for each unique id not in the set, push a minimal{ service_id }record intoallServices.getServiceDisplayalready falls back to the rawservice_idas label.Gotcha:
calendar_dateshas one row per(service_id, date)pair — deduplication before merging is essential.Phase 2 — Fix service-days editor display and calendar creation
File:
src/modules/service-days-controller.tsDisplay (blank date range)
renderServiceEditorHTML(~L415): whencalendaris null andexceptions.length > 0, sort the exceptiondatefields (YYYYMMDD, so lexicographic sort is correct) and derivederivedStart = sorted[0],derivedEnd = sorted[last].renderDateRange:derivedDates?: { start: string; end: string }. Whencalendaris null, usederivedDates.start/derivedDates.endto populate the input values instead of empty strings.renderServiceEditorHTMLdown intorenderDateRange.Calendar creation on first edit
Both
toggleDayandupdateDateRangealready create acalendar.txtentry (viainsertRows+patchManager.recordInsert) whencalendaris null — the patch handling is correct. The only problem is the fallback date range (today / today+1year).!calendarbranch oftoggleDay(~L179): before constructing the new calendar object, querycalendar_datesfor thisservice_id. If rows are returned, computestart_date = min(row.date),end_date = max(row.date). Fall back to today/today+1year only whencalendar_datesis also empty.!calendarbranch ofupdateDateRange(~L262).Note: do not create a
calendar.txtentry on page load — only on the first user-initiated edit. The existing code structure already ensures this; the fix is only to the date values used when that entry is created.Implementation notes:
updateDateRangeconstructs the full calendar object before thecalendar[dateType] = gtfsDateline, so for the null-calendar path we initializestart_dateandend_datein the object literal directly using the derivedotherDate— the subsequentcalendar[dateType] = gtfsDateline then correctly overwrites whichever field the user just edited.