add load time and autofocus
Some checks failed
Create and publish a Docker image / build-and-push-image (push) Failing after 10m5s

This commit is contained in:
Nicholas Orlowsky 2025-10-06 21:25:15 -04:00
parent 917428507d
commit 5539c8521d
No known key found for this signature in database
GPG key ID: A9F3BA4C0AA7A70B
10 changed files with 153 additions and 11 deletions

View file

@ -29,6 +29,10 @@ body {
max-width: 750px;
}
.next-col {
background-color: #55ff55 !important;
}
a {
text-decoration: none;
color: #114488;

View file

@ -134,7 +134,7 @@ pub async fn get_schedule_by_route_id(
AND
septa_schedule_days.service_id = septa_stop_schedules.service_id
WHERE
septa_stop_schedules.route_id = $1
septa_stop_schedules.route_id = $1 OR septa_stop_schedules.route_id = 'B2'
;"#,
id.clone(),
schedule_day_str.clone()

View file

@ -2,6 +2,7 @@ use libseptastic::{direction::Direction, stop_schedule::{Trip, TripTracking}};
use std::{cmp::Ordering, collections::BTreeMap};
use serde::{Serialize};
use libseptastic::stop_schedule::TripTracking::Tracked;
use chrono::Timelike;
#[derive(askama::Template)]
#[template(path = "layout.html")]
@ -49,9 +50,11 @@ pub struct TimetableDirection {
pub direction: Direction,
pub trip_ids: Vec<String>,
pub tracking_data: Vec<TripTracking>,
pub rows: Vec<TimetableStopRow>
pub rows: Vec<TimetableStopRow>,
pub next_id: Option<String>
}
pub fn build_timetables(
directions: Vec<Direction>,
trips: Vec<Trip>,
@ -59,6 +62,12 @@ pub fn build_timetables(
let mut results = Vec::new();
for direction in directions {
let now = chrono::Local::now();
let naive_time = now.time();
let seconds_since_midnight = naive_time.num_seconds_from_midnight();
let mut next_id: Option<String> = None;
let mut direction_trips: Vec<&Trip> = trips
.iter()
.filter(|trip| trip.direction_id == direction.direction_id)
@ -72,6 +81,14 @@ pub fn build_timetables(
.unwrap_or(i64::MAX)
});
for trip in direction_trips.clone() {
if let Some(last) = trip.schedule.last() {
if next_id == None && i64::from(seconds_since_midnight) < last.arrival_time {
next_id = Some(last.trip_id.clone());
}
}
}
let trip_ids: Vec<String> = direction_trips
.iter()
.map(|t| t.trip_id.clone())
@ -120,7 +137,8 @@ pub fn build_timetables(
direction: direction.clone(),
trip_ids,
rows,
tracking_data: live_trips
tracking_data: live_trips ,
next_id
});
}

View file

@ -18,6 +18,17 @@
<link rel="icon" type="image/x-icon" href="/assets/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<script>
window.onload = function () {
setTimeout(() => {
const perfData = window.performance.timing;
const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;
const loadTimeElement = document.getElementById('js_load_time');
loadTimeElement.textContent += ` ${pageLoadTime}ms`;
}, 0); // Minimal delay to wait for `loadEventEnd` to be populated
};
</script>
<noscript>
<style>
.js-only {
@ -67,6 +78,7 @@
{% if let Some(load_time) = load_time_ms %}
<p style="marin-top: 5px; color: #555555;"><small><i>Data loaded in {{ *load_time | format_load_time }}</i></small></p>
{% endif %}
<p class="js-only" style="marin-top: 5px; color: #555555;"><small><i id="js_load_time">Total load time</i></small></p>
</div>
<div>
{% if widescreen %}

View file

@ -31,7 +31,22 @@
</style>
<script>
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll("details[data-direction-id]").forEach(details => {
details.addEventListener("toggle", () => {
if (details.open) {
// Delay scroll until DOM is expanded/rendered
setTimeout(() => {
const directionId = details.getAttribute("data-direction-id");
const target = document.getElementById("next-col-" + directionId);
if (target) {
target.scrollIntoView({ behavior: "smooth", inline: "start", block: "nearest" });
}
}, 50); // Short delay to allow rendering
}
});
});
document.querySelectorAll(".train-direction-table").forEach((table) => {
table.addEventListener("click", (e) => {
const cell = e.target.closest("td, th");
@ -74,7 +89,7 @@ document.addEventListener("DOMContentLoaded", () => {
</div>
{% for timetable in timetables %}
<details style="margin-top: 15px;">
<details style="margin-top: 15px;" data-direction-id="{{ timetable.direction.direction_id }}">
<summary>
<div style="display: inline-block;">
<h3>{{ timetable.direction.direction | capitalize }} to</h3>
@ -87,7 +102,17 @@ document.addEventListener("DOMContentLoaded", () => {
<tr>
<th>Stop</th>
{% for trip_id in timetable.trip_ids %}
<th>{{ trip_id }}</th>
{% if let Some(next_id_v) = timetable.next_id %}
{% if next_id_v == trip_id %}
<th class="next-col" id="next-col-{{ timetable.direction.direction_id }}">
{% else %}
<th>
{% endif %}
{% else %}
<th>
{% endif %}
{{ trip_id }}
</th>
{% endfor %}
</tr>
</thead>