Cache provisional weekday timetables
This commit is contained in:
parent
378d2484d0
commit
bc7cb9cffa
6 changed files with 686 additions and 58 deletions
|
|
@ -23,7 +23,7 @@
|
|||
<div class="date-nav">
|
||||
<a href="{{ prev_results_url }}"
|
||||
class="btn-nav">← Prev</a>
|
||||
<strong>{{ travel_date_display }}{% if return_date %} to {{ return_date }}{% endif %}</strong>
|
||||
<strong>{{ travel_date_display }}{% if return_date_display %} to {{ return_date_display }}{% endif %}</strong>
|
||||
<a href="{{ next_results_url }}"
|
||||
class="btn-nav">Next →</a>
|
||||
</div>
|
||||
|
|
@ -87,8 +87,11 @@
|
|||
const DEFAULT_MAX_CONN = {{ default_max_connection }};
|
||||
let TRIP_FARES = {{ trip_fares_json | safe }};
|
||||
let ADVANCE_FARES = {{ advance_fares_json | safe }};
|
||||
let WALKON_API_URLS = {{ walkon_api_urls_json | safe }};
|
||||
let ADVANCE_API_URLS = {{ advance_api_urls_json | safe }};
|
||||
let ADVANCE_STREAM_URLS = {{ advance_stream_urls_json | safe }};
|
||||
const TIMETABLE_REFRESH_URL = {{ timetable_refresh_url|tojson }};
|
||||
const HAS_PROVISIONAL_TIMETABLE = {{ 'true' if provisional_timetable else 'false' }};
|
||||
let cachedAdvanceFares = ADVANCE_FARES;
|
||||
let currentNrClass = '{{ nr_class }}';
|
||||
let currentEsClass = '{{ es_class }}';
|
||||
|
|
@ -158,6 +161,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
function mergeWalkonFares(sectionId, fares) {
|
||||
for (var key in TRIP_FARES) {
|
||||
var row = TRIP_FARES[key];
|
||||
if (row.section !== sectionId || !row.advance_key || !fares[row.advance_key]) continue;
|
||||
var fare = fares[row.advance_key];
|
||||
row.walkon = {price: fare.price, ticket: fare.ticket || ''};
|
||||
}
|
||||
}
|
||||
|
||||
function mergeEurostarPrices(prices) {
|
||||
for (var key in prices) {
|
||||
for (var rowKey in TRIP_FARES) {
|
||||
var row = TRIP_FARES[rowKey];
|
||||
if (rowKey !== key && row.eurostar_key !== key) continue;
|
||||
if (prices[key].es_standard) row.es_standard = prices[key].es_standard;
|
||||
if (prices[key].es_plus) row.es_plus = prices[key].es_plus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sectionNeedsAdvance(sectionId) {
|
||||
for (var key in TRIP_FARES) {
|
||||
var row = TRIP_FARES[key];
|
||||
|
|
@ -306,7 +329,8 @@
|
|||
html += '</span>';
|
||||
totalSpan.innerHTML = html;
|
||||
} else {
|
||||
totalSpan.innerHTML = '';
|
||||
var missing = !nrFare ? 'No NR fare' : 'No Eurostar fare';
|
||||
totalSpan.innerHTML = '<span class="text-xs text-muted">' + missing + '</span>';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -315,6 +339,30 @@
|
|||
function initialiseResultsPage() {
|
||||
if (currentNrClass === 'advance_std' || currentNrClass === 'advance_1st') loadMissingAdvanceFares();
|
||||
updateDisplay();
|
||||
startTimetableRefresh();
|
||||
}
|
||||
|
||||
function startTimetableRefresh() {
|
||||
if (!HAS_PROVISIONAL_TIMETABLE || !TIMETABLE_REFRESH_URL || !window.EventSource) return;
|
||||
var source = new EventSource(TIMETABLE_REFRESH_URL);
|
||||
source.onmessage = function(event) {
|
||||
var msg = JSON.parse(event.data);
|
||||
if (msg.type === 'reload') {
|
||||
source.close();
|
||||
window.location.reload();
|
||||
} else if (msg.type === 'eurostar_prices') {
|
||||
mergeEurostarPrices(msg.prices);
|
||||
updateDisplay();
|
||||
} else if (msg.type === 'walkon_fares') {
|
||||
mergeWalkonFares(msg.section, msg.fares);
|
||||
updateDisplay();
|
||||
} else if (msg.type === 'done' || msg.type === 'error') {
|
||||
source.close();
|
||||
}
|
||||
};
|
||||
source.onerror = function() {
|
||||
source.close();
|
||||
};
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
|
@ -330,6 +378,9 @@
|
|||
{% if from_cache %}
|
||||
· <span class="text-muted text-sm">(cached)</span>
|
||||
{% endif %}
|
||||
{% if provisional_timetable %}
|
||||
· <span class="text-muted text-sm">checking exact timetable</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if error %}
|
||||
<div class="alert alert-error">
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
{% endif %}
|
||||
</h2>
|
||||
<p class="card-meta">
|
||||
{{ travel_date_display }}{% if return_date %} to {{ return_date }}{% endif %}
|
||||
{{ travel_date_display }}{% if return_date_display %} to {{ return_date_display }}{% endif %}
|
||||
</p>
|
||||
<div class="loading-panel" role="status" aria-live="polite">
|
||||
<span class="spinner" aria-hidden="true"></span>
|
||||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
<script>
|
||||
(function() {
|
||||
var attempts = 0;
|
||||
|
||||
function runScripts(root) {
|
||||
root.querySelectorAll('script').forEach(function(oldScript) {
|
||||
var script = document.createElement('script');
|
||||
|
|
@ -49,27 +51,36 @@
|
|||
});
|
||||
}
|
||||
|
||||
fetch({{ full_results_url|tojson }}, {headers: {'X-Requested-With': 'fetch'}})
|
||||
.then(function(response) {
|
||||
if (!response.ok) throw new Error('Could not load results');
|
||||
return response.text();
|
||||
})
|
||||
.then(function(html) {
|
||||
var doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
document.title = doc.title;
|
||||
var nextMain = doc.querySelector('main');
|
||||
var currentMain = document.querySelector('main');
|
||||
if (!nextMain || !currentMain) throw new Error('Results page was incomplete');
|
||||
currentMain.innerHTML = nextMain.innerHTML;
|
||||
runScripts(currentMain);
|
||||
history.replaceState(null, '', window.location.href);
|
||||
})
|
||||
.catch(function() {
|
||||
var panel = document.querySelector('.loading-panel');
|
||||
if (panel) {
|
||||
panel.innerHTML = '<div><strong>Could not load results</strong><p class="text-muted text-sm"><a href="{{ full_results_url }}">Try loading the full results page</a>.</p></div>';
|
||||
}
|
||||
});
|
||||
function loadResults() {
|
||||
attempts += 1;
|
||||
fetch({{ full_results_url|tojson }}, {headers: {'X-Requested-With': 'fetch'}})
|
||||
.then(function(response) {
|
||||
if (!response.ok) throw new Error('Could not load results');
|
||||
return response.text();
|
||||
})
|
||||
.then(function(html) {
|
||||
var doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
document.title = doc.title;
|
||||
var nextMain = doc.querySelector('main');
|
||||
var currentMain = document.querySelector('main');
|
||||
if (!nextMain || !currentMain) throw new Error('Results page was incomplete');
|
||||
currentMain.innerHTML = nextMain.innerHTML;
|
||||
runScripts(currentMain);
|
||||
history.replaceState(null, '', window.location.href);
|
||||
})
|
||||
.catch(function() {
|
||||
if (attempts < 3) {
|
||||
window.setTimeout(loadResults, attempts * 2000);
|
||||
return;
|
||||
}
|
||||
var panel = document.querySelector('.loading-panel');
|
||||
if (panel) {
|
||||
panel.innerHTML = '<div><strong>Could not load results</strong><p class="text-muted text-sm"><a href="{{ full_results_url }}">Try loading the full results page</a>.</p></div>';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadResults();
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue