Improve progressive results loading
This commit is contained in:
parent
9691632f65
commit
378d2484d0
6 changed files with 369 additions and 60 deletions
|
|
@ -21,22 +21,22 @@
|
|||
{% endif %}
|
||||
</h2>
|
||||
<div class="date-nav">
|
||||
<a href="{{ url_for('results', station_crs=station_crs, slug=slug, travel_date=prev_date, journey_type=url_journey_type, return_date=return_date, min_connection=url_min_connection, max_connection=url_max_connection, nr_class=url_nr_class, es_class=url_es_class) }}"
|
||||
<a href="{{ prev_results_url }}"
|
||||
class="btn-nav">← Prev</a>
|
||||
<strong>{{ travel_date_display }}{% if return_date %} to {{ return_date }}{% endif %}</strong>
|
||||
<a href="{{ url_for('results', station_crs=station_crs, slug=slug, travel_date=next_date, journey_type=url_journey_type, return_date=return_date, min_connection=url_min_connection, max_connection=url_max_connection, nr_class=url_nr_class, es_class=url_es_class) }}"
|
||||
<a href="{{ next_results_url }}"
|
||||
class="btn-nav">Next →</a>
|
||||
</div>
|
||||
<div class="switcher-section">
|
||||
<div class="section-label">Switch destination for {{ travel_date_display }}</div>
|
||||
<div class="chip-row">
|
||||
{% for destination_slug, destination_name in destinations.items() %}
|
||||
{% for destination_slug, destination_name, destination_url in destination_links %}
|
||||
{% if destination_slug == slug %}
|
||||
<span class="chip-current">{{ destination_name }}</span>
|
||||
{% else %}
|
||||
<a
|
||||
class="chip-link"
|
||||
href="{{ url_for('results', station_crs=station_crs, slug=destination_slug, travel_date=travel_date, journey_type=url_journey_type, return_date=return_date, min_connection=url_min_connection, max_connection=url_max_connection, nr_class=url_nr_class, es_class=url_es_class) }}"
|
||||
href="{{ destination_url }}"
|
||||
>{{ destination_name }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
@ -70,6 +70,7 @@
|
|||
<button type="button" class="btn-group-option {% if nr_class == 'advance_std' %}active{% endif %}" onclick="setNrClass('advance_std')">Advance Std</button>
|
||||
<button type="button" class="btn-group-option {% if nr_class == 'advance_1st' %}active{% endif %}" onclick="setNrClass('advance_1st')">Advance 1st</button>
|
||||
</div>
|
||||
<span id="advance-loading" style="display:none"><span class="spinner spinner-inline" aria-hidden="true"></span>Loading advance fares</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="filter-label">Eurostar:</span>
|
||||
|
|
@ -81,9 +82,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const RESULTS_BASE = '{{ url_for('results', station_crs=station_crs, slug=slug, travel_date=travel_date) }}';
|
||||
const JOURNEY_TYPE = '{{ journey_type }}';
|
||||
const RETURN_DATE = '{{ return_date or '' }}';
|
||||
const RESULTS_BASE = '{{ results_base_url }}';
|
||||
const DEFAULT_MIN_CONN = {{ default_min_connection }};
|
||||
const DEFAULT_MAX_CONN = {{ default_max_connection }};
|
||||
let TRIP_FARES = {{ trip_fares_json | safe }};
|
||||
|
|
@ -95,12 +94,18 @@
|
|||
let currentEsClass = '{{ es_class }}';
|
||||
let advanceLoadingSections = {};
|
||||
|
||||
function updateAdvanceLoadingStatus() {
|
||||
var loading = Object.keys(advanceLoadingSections).some(function(sectionId) {
|
||||
return advanceLoadingSections[sectionId];
|
||||
});
|
||||
var el = document.getElementById('advance-loading');
|
||||
if (el) el.style.display = loading ? 'inline-flex' : 'none';
|
||||
}
|
||||
|
||||
function buildUrl(nrCls, esCls) {
|
||||
var min = parseInt(document.getElementById('min_conn_select').value);
|
||||
var max = parseInt(document.getElementById('max_conn_select').value);
|
||||
var params = [];
|
||||
if (JOURNEY_TYPE !== 'outbound') params.push('journey_type=' + encodeURIComponent(JOURNEY_TYPE));
|
||||
if (RETURN_DATE) params.push('return_date=' + encodeURIComponent(RETURN_DATE));
|
||||
if (min !== DEFAULT_MIN_CONN) params.push('min_connection=' + min);
|
||||
if (max !== DEFAULT_MAX_CONN) params.push('max_connection=' + max);
|
||||
if (nrCls !== 'walkon') params.push('nr_class=' + nrCls);
|
||||
|
|
@ -169,6 +174,7 @@
|
|||
function loadAdvanceFaresForSection(sectionId) {
|
||||
if (advanceLoadingSections[sectionId] || !ADVANCE_API_URLS[sectionId]) return;
|
||||
advanceLoadingSections[sectionId] = true;
|
||||
updateAdvanceLoadingStatus();
|
||||
if (!ADVANCE_FARES) ADVANCE_FARES = {};
|
||||
if (!ADVANCE_FARES[sectionId]) ADVANCE_FARES[sectionId] = {};
|
||||
|
||||
|
|
@ -183,6 +189,7 @@
|
|||
.catch(function() {})
|
||||
.finally(function() {
|
||||
advanceLoadingSections[sectionId] = false;
|
||||
updateAdvanceLoadingStatus();
|
||||
updateDisplay();
|
||||
});
|
||||
}
|
||||
|
|
@ -190,29 +197,41 @@
|
|||
function loadAdvanceFaresForSectionStreaming(sectionId) {
|
||||
if (advanceLoadingSections[sectionId] || !ADVANCE_STREAM_URLS[sectionId]) return;
|
||||
advanceLoadingSections[sectionId] = true;
|
||||
updateAdvanceLoadingStatus();
|
||||
if (!ADVANCE_FARES) ADVANCE_FARES = {};
|
||||
if (!ADVANCE_FARES[sectionId]) ADVANCE_FARES[sectionId] = {};
|
||||
|
||||
var hadMessage = false;
|
||||
var source = new EventSource(ADVANCE_STREAM_URLS[sectionId]);
|
||||
source.onmessage = function(event) {
|
||||
hadMessage = true;
|
||||
var msg = JSON.parse(event.data);
|
||||
if (msg.type === 'fares') mergeAdvanceFares(sectionId, msg.fares);
|
||||
if (msg.type === 'fares') {
|
||||
mergeAdvanceFares(sectionId, msg.fares);
|
||||
updateDisplay();
|
||||
}
|
||||
if (msg.type === 'done' || msg.type === 'error') {
|
||||
advanceLoadingSections[sectionId] = false;
|
||||
source.close();
|
||||
updateAdvanceLoadingStatus();
|
||||
updateDisplay();
|
||||
}
|
||||
};
|
||||
source.onerror = function() {
|
||||
advanceLoadingSections[sectionId] = false;
|
||||
source.close();
|
||||
updateDisplay();
|
||||
updateAdvanceLoadingStatus();
|
||||
if (!hadMessage && ADVANCE_API_URLS[sectionId]) {
|
||||
loadAdvanceFaresForSection(sectionId);
|
||||
} else {
|
||||
updateDisplay();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function loadMissingAdvanceFares() {
|
||||
for (var sectionId in ADVANCE_API_URLS) {
|
||||
if (sectionNeedsAdvance(sectionId)) loadAdvanceFaresForSection(sectionId);
|
||||
for (var sectionId in ADVANCE_STREAM_URLS) {
|
||||
if (sectionNeedsAdvance(sectionId)) loadAdvanceFaresForSectionStreaming(sectionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -281,8 +300,8 @@
|
|||
var total = totals[key];
|
||||
var html = '<span class="text-sm text-green" style="font-weight:700">' + fmtPrice(total);
|
||||
if (minTotal !== null && maxTotal !== null) {
|
||||
if (total <= minTotal + 10) html += ' <span title="Cheapest journey">low</span>';
|
||||
else if (total >= maxTotal - 10) html += ' <span title="Most expensive journey">high</span>';
|
||||
if (total <= minTotal + 10) html += ' <span title="Cheapest journey">🪙</span>';
|
||||
else if (total >= maxTotal - 10) html += ' <span title="Most expensive journey">💸</span>';
|
||||
}
|
||||
html += '</span>';
|
||||
totalSpan.innerHTML = html;
|
||||
|
|
@ -293,10 +312,16 @@
|
|||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (currentNrClass === 'advance_std' || currentNrClass === 'advance_1st') loadMissingAdvanceFares();
|
||||
updateDisplay();
|
||||
});
|
||||
function initialiseResultsPage() {
|
||||
if (currentNrClass === 'advance_std' || currentNrClass === 'advance_1st') loadMissingAdvanceFares();
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initialiseResultsPage);
|
||||
} else {
|
||||
initialiseResultsPage();
|
||||
}
|
||||
</script>
|
||||
<p class="card-meta">
|
||||
{{ gwr_count }} National Rail service{{ 's' if gwr_count != 1 }}
|
||||
|
|
@ -382,10 +407,14 @@
|
|||
<span class="fare-line es-plus">{% if row.eurostar_plus_price is not none %}<span class="text-sm font-bold">£{{ "%.2f"|format(row.eurostar_plus_price) }}</span>{% endif %}</span>
|
||||
</td>
|
||||
<td class="col-transfer" style="color:#4a5568">
|
||||
<span class="nowrap">{{ row.connection_duration }}{% if row.connection_minutes < 45 %} <span title="Tight connection">!</span>{% endif %}</span>
|
||||
<span class="nowrap">{{ row.connection_duration }}{% if row.connection_minutes < 45 %} <span title="Tight connection">⚠️</span>{% endif %}</span>
|
||||
{% if row.circle_services %}
|
||||
{% set c = row.circle_services[0] %}
|
||||
<br><span class="text-xs text-muted nowrap">Circle {{ c.depart }} → PAD {{ c.arrive_pad }} · £{{ "%.2f"|format(c.fare) }}</span>
|
||||
{% if row.circle_services | length > 1 %}
|
||||
{% set c2 = row.circle_services[1] %}
|
||||
<br><span class="text-xs text-muted nowrap" style="opacity:0.7">next {{ c2.depart }} → PAD {{ c2.arrive_pad }} · £{{ "%.2f"|format(c2.fare) }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
|
@ -410,10 +439,14 @@
|
|||
<span class="fare-line nr-advance-1st"></span>
|
||||
</td>
|
||||
<td class="col-transfer" style="color:#4a5568">
|
||||
<span class="nowrap">{{ row.connection_duration }}{% if row.connection_minutes < 80 %} <span title="Tight connection">!</span>{% endif %}</span>
|
||||
<span class="nowrap">{{ row.connection_duration }}{% if row.connection_minutes < 80 %} <span title="Tight connection">⚠️</span>{% endif %}</span>
|
||||
{% if row.circle_services %}
|
||||
{% set c = row.circle_services[0] %}
|
||||
<br><span class="text-xs text-muted nowrap">Circle {{ c.depart }} → KX {{ c.arrive_kx }} · £{{ "%.2f"|format(c.fare) }}</span>
|
||||
{% if row.circle_services | length > 1 %}
|
||||
{% set c2 = row.circle_services[1] %}
|
||||
<br><span class="text-xs text-muted nowrap" style="opacity:0.7">next {{ c2.depart }} → KX {{ c2.arrive_kx }} · £{{ "%.2f"|format(c2.fare) }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue