Public display improvements WIP

This commit is contained in:
James Pattinson
2025-12-10 11:25:33 +00:00
parent 169c3af29b
commit 86f1dc65f4
3 changed files with 137 additions and 33 deletions

View File

@@ -62,6 +62,9 @@
padding: 12px;
text-align: left;
border: 1px solid #ccc;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
th {
@@ -134,7 +137,7 @@
<body>
<header>
<img src="assets/logo.png" alt="EGFH Logo" class="left-image">
<h1>Arrivals/Departures Information</h1>
<h1>Flight Information</h1>
<img src="assets/flightImg.png" alt="EGFH Logo" class="right-image">
</header>
@@ -145,15 +148,14 @@
<table>
<thead>
<tr>
<th>Registration</th>
<th>Aircraft Type</th>
<th>From</th>
<th>Due</th>
<th style="width: 25%;">Aircraft</th>
<th style="width: 60%;">From</th>
<th style="width: 15%;">Due</th>
</tr>
</thead>
<tbody id="arrivals-tbody">
<tr>
<td colspan="4" class="loading">Loading arrivals...</td>
<td colspan="3" class="loading">Loading arrivals...</td>
</tr>
</tbody>
</table>
@@ -165,15 +167,14 @@
<table>
<thead>
<tr>
<th>Registration</th>
<th>Aircraft Type</th>
<th>To</th>
<th>Due</th>
<th style="width: 25%;">Aircraft</th>
<th style="width: 60%;">To</th>
<th style="width: 15%;">Due</th>
</tr>
</thead>
<tbody id="departures-tbody">
<tr>
<td colspan="4" class="loading">Loading departures...</td>
<td colspan="3" class="loading">Loading departures...</td>
</tr>
</tbody>
</table>
@@ -191,6 +192,27 @@
<script>
let wsConnection = null;
// ICAO code to airport name cache
const airportNameCache = {};
async function getAirportName(code) {
if (!code || code.length !== 4 || !/^[A-Z]{4}$/.test(code)) return code;
if (airportNameCache[code]) return airportNameCache[code];
try {
const resp = await fetch(`/api/v1/airport/public/lookup/${code}`);
if (resp.ok) {
const data = await resp.json();
if (data && data.length && data[0].name) {
airportNameCache[code] = data[0].name;
return data[0].name;
}
}
} catch (error) {
console.error('Error looking up airport:', error);
}
return code;
}
// WebSocket connection for real-time updates
function connectWebSocket() {
@@ -276,22 +298,38 @@
const arrivals = await response.json();
if (arrivals.length === 0) {
tbody.innerHTML = '<tr><td colspan="4">No arrivals found.</td></tr>';
tbody.innerHTML = '<tr><td colspan="3">No arrivals found.</td></tr>';
return;
}
tbody.innerHTML = arrivals.map(arrival => `
<tr>
<td>${escapeHtml(arrival.ac_reg || '')}</td>
<td>${escapeHtml(arrival.ac_type || '')}</td>
<td>${escapeHtml(arrival.in_from || '')}</td>
<td>${convertToLocalTime(arrival.eta)}</td>
</tr>
`).join('');
// Build rows asynchronously to lookup airport names
const rows = await Promise.all(arrivals.map(async (arrival) => {
const aircraftDisplay = `${escapeHtml(arrival.ac_reg || '')} <span style="font-size: 0.8em; color: #666;">(${escapeHtml(arrival.ac_type || '')})</span>`;
const fromDisplay = await getAirportName(arrival.in_from || '');
// Show landed time if available, otherwise ETA
let timeDisplay;
if (arrival.status === 'LANDED' && arrival.landed_dt) {
const time = convertToLocalTime(arrival.landed_dt);
timeDisplay = `<div style="display: flex; align-items: center; gap: 8px;"><span style="color: #27ae60; font-weight: bold;">${time}</span><span style="font-size: 0.7em; background: #27ae60; color: white; padding: 2px 4px; border-radius: 3px; white-space: nowrap;">LANDED</span></div>`;
} else {
timeDisplay = convertToLocalTime(arrival.eta);
}
return `
<tr>
<td>${aircraftDisplay}</td>
<td>${escapeHtml(fromDisplay)}</td>
<td>${timeDisplay}</td>
</tr>
`;
}));
tbody.innerHTML = rows.join('');
} catch (error) {
console.error('Error loading arrivals:', error);
tbody.innerHTML = '<tr><td colspan="4" class="error">Error loading arrivals</td></tr>';
tbody.innerHTML = '<tr><td colspan="3" class="error">Error loading arrivals</td></tr>';
}
}
@@ -309,22 +347,38 @@
const departures = await response.json();
if (departures.length === 0) {
tbody.innerHTML = '<tr><td colspan="4">No departures found.</td></tr>';
tbody.innerHTML = '<tr><td colspan="3">No departures found.</td></tr>';
return;
}
tbody.innerHTML = departures.map(departure => `
<tr>
<td>${escapeHtml(departure.ac_reg || '')}</td>
<td>${escapeHtml(departure.ac_type || '')}</td>
<td>${escapeHtml(departure.out_to || '')}</td>
<td>${convertToLocalTime(departure.etd)}</td>
</tr>
`).join('');
// Build rows asynchronously to lookup airport names
const rows = await Promise.all(departures.map(async (departure) => {
const aircraftDisplay = `${escapeHtml(departure.ac_reg || '')} <span style="font-size: 0.8em; color: #666;">(${escapeHtml(departure.ac_type || '')})</span>`;
const toDisplay = await getAirportName(departure.out_to || '');
// Show departed time if available, otherwise ETD
let timeDisplay;
if (departure.status === 'DEPARTED' && departure.departed_dt) {
const time = convertToLocalTime(departure.departed_dt);
timeDisplay = `<div style="display: flex; align-items: center; gap: 8px;"><span style="color: #3498db; font-weight: bold;">${time}</span><span style="font-size: 0.7em; background: #3498db; color: white; padding: 2px 4px; border-radius: 3px; white-space: nowrap;">DEPARTED</span></div>`;
} else {
timeDisplay = convertToLocalTime(departure.etd);
}
return `
<tr>
<td>${aircraftDisplay}</td>
<td>${escapeHtml(toDisplay)}</td>
<td>${timeDisplay}</td>
</tr>
`;
}));
tbody.innerHTML = rows.join('');
} catch (error) {
console.error('Error loading departures:', error);
tbody.innerHTML = '<tr><td colspan="4" class="error">Error loading departures</td></tr>';
tbody.innerHTML = '<tr><td colspan="3" class="error">Error loading departures</td></tr>';
}
}