Public board fixes
This commit is contained in:
143
web/index.html
143
web/index.html
@@ -302,10 +302,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Build rows asynchronously to lookup airport names
|
||||
const rows = await Promise.all(arrivals.map(async (arrival) => {
|
||||
// Build rows with metadata for sorting
|
||||
const rowsWithData = await Promise.all(arrivals.map(async (arrival) => {
|
||||
const isLocal = arrival.isLocalFlight;
|
||||
const isBookedIn = arrival.isBookedIn;
|
||||
const isLanded = arrival.status === 'LANDED' || (arrival.status === 'DEPARTED' && arrival.landed_dt);
|
||||
|
||||
let html = '';
|
||||
let sortKey = '';
|
||||
|
||||
if (isLocal) {
|
||||
// Local flight
|
||||
@@ -315,63 +319,72 @@
|
||||
const time = convertToLocalTime(arrival.eta);
|
||||
const 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;">IN AIR</span></div>`;
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${aircraftDisplay}</td>
|
||||
<td>${fromDisplay}</td>
|
||||
<td>${timeDisplay}</td>
|
||||
</tr>
|
||||
`;
|
||||
html = `<tr><td>${aircraftDisplay}</td><td>${fromDisplay}</td><td>${timeDisplay}</td></tr>`;
|
||||
sortKey = `0-${arrival.eta}`; // Live flights, sort by ETA
|
||||
} else if (isBookedIn) {
|
||||
// Booked-in arrival
|
||||
const aircraftId = arrival.callsign || arrival.registration || '';
|
||||
const aircraftDisplay = `${escapeHtml(aircraftId)} <span style="font-size: 0.8em; color: #666;">(${escapeHtml(arrival.type || '')})</span>`;
|
||||
const fromDisplay = await getAirportName(arrival.in_from || '');
|
||||
|
||||
let timeDisplay;
|
||||
let timeDisplay, sortTime;
|
||||
if (arrival.status === 'LANDED' && arrival.landed_dt) {
|
||||
// Show landed time if LANDED
|
||||
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>`;
|
||||
sortTime = arrival.landed_dt;
|
||||
} else {
|
||||
// Show ETA if BOOKED_IN
|
||||
const time = convertToLocalTime(arrival.eta);
|
||||
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;">IN AIR</span></div>`;
|
||||
sortTime = arrival.eta;
|
||||
}
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${aircraftDisplay}</td>
|
||||
<td>${escapeHtml(fromDisplay)}</td>
|
||||
<td>${timeDisplay}</td>
|
||||
</tr>
|
||||
`;
|
||||
html = `<tr><td>${aircraftDisplay}</td><td>${escapeHtml(fromDisplay)}</td><td>${timeDisplay}</td></tr>`;
|
||||
sortKey = isLanded ? `1-${sortTime}` : `0-${sortTime}`; // 0=live, 1=completed
|
||||
} else {
|
||||
// PPR
|
||||
const aircraftId = arrival.ac_call || arrival.ac_reg || '';
|
||||
const aircraftDisplay = `${escapeHtml(aircraftId)} <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;
|
||||
let timeDisplay, sortTime;
|
||||
if ((arrival.status === 'LANDED' || arrival.status === 'DEPARTED') && 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>`;
|
||||
sortTime = arrival.landed_dt;
|
||||
} else {
|
||||
timeDisplay = convertToLocalTime(arrival.eta);
|
||||
sortTime = arrival.eta;
|
||||
}
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${aircraftDisplay}</td>
|
||||
<td>${escapeHtml(fromDisplay)}</td>
|
||||
<td>${timeDisplay}</td>
|
||||
</tr>
|
||||
`;
|
||||
html = `<tr><td>${aircraftDisplay}</td><td>${escapeHtml(fromDisplay)}</td><td>${timeDisplay}</td></tr>`;
|
||||
sortKey = isLanded ? `1-${sortTime}` : `0-${sortTime}`;
|
||||
}
|
||||
|
||||
return { html, sortKey, isLanded };
|
||||
}));
|
||||
|
||||
tbody.innerHTML = rows.join('');
|
||||
// Sort: live flights first (0) by ETA ascending, then completed flights (1) by time descending
|
||||
rowsWithData.sort((a, b) => {
|
||||
const aParts = a.sortKey.split('-');
|
||||
const bParts = b.sortKey.split('-');
|
||||
const aType = parseInt(aParts[0]);
|
||||
const bType = parseInt(bParts[0]);
|
||||
|
||||
if (aType !== bType) return aType - bType; // Live before completed
|
||||
|
||||
// Sort by time
|
||||
if (aType === 0) {
|
||||
// Live flights: ascending (earliest first)
|
||||
return aParts[1].localeCompare(bParts[1]);
|
||||
} else {
|
||||
// Completed flights: descending (most recent first)
|
||||
return bParts[1].localeCompare(aParts[1]);
|
||||
}
|
||||
});
|
||||
|
||||
tbody.innerHTML = rowsWithData.map(r => r.html).join('');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading arrivals:', error);
|
||||
@@ -397,10 +410,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Build rows asynchronously to lookup airport names
|
||||
const rows = await Promise.all(departures.map(async (departure) => {
|
||||
// Build rows with metadata for sorting
|
||||
const rowsWithData = await Promise.all(departures.map(async (departure) => {
|
||||
const isLocal = departure.isLocalFlight;
|
||||
const isDeparture = departure.isDeparture;
|
||||
const isDeparted = departure.status === 'DEPARTED';
|
||||
|
||||
let html = '';
|
||||
let sortKey = '';
|
||||
|
||||
if (isLocal) {
|
||||
// Local flight
|
||||
@@ -410,54 +427,70 @@
|
||||
const time = convertToLocalTime(departure.etd);
|
||||
const timeDisplay = `<div>${escapeHtml(time)}</div>`;
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${aircraftDisplay}</td>
|
||||
<td>${toDisplay}</td>
|
||||
<td>${timeDisplay}</td>
|
||||
</tr>
|
||||
`;
|
||||
html = `<tr><td>${aircraftDisplay}</td><td>${toDisplay}</td><td>${timeDisplay}</td></tr>`;
|
||||
sortKey = `0-${departure.etd}`; // Live flights, sort by ETD
|
||||
} else if (isDeparture) {
|
||||
// Departure to other airport
|
||||
const aircraftId = departure.ac_call || departure.ac_reg || '';
|
||||
const aircraftDisplay = `${escapeHtml(aircraftId)} <span style="font-size: 0.8em; color: #666;">(${escapeHtml(departure.ac_type || '')})</span>`;
|
||||
const toDisplay = await getAirportName(departure.out_to || '');
|
||||
const time = convertToLocalTime(departure.etd);
|
||||
const timeDisplay = `<div>${escapeHtml(time)}</div>`;
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${aircraftDisplay}</td>
|
||||
<td>${toDisplay}</td>
|
||||
<td>${timeDisplay}</td>
|
||||
</tr>
|
||||
`;
|
||||
let timeDisplay, sortTime;
|
||||
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>`;
|
||||
sortTime = departure.departed_dt;
|
||||
} else {
|
||||
const time = convertToLocalTime(departure.etd);
|
||||
timeDisplay = `<div>${escapeHtml(time)}</div>`;
|
||||
sortTime = departure.etd;
|
||||
}
|
||||
|
||||
html = `<tr><td>${aircraftDisplay}</td><td>${toDisplay}</td><td>${timeDisplay}</td></tr>`;
|
||||
sortKey = isDeparted ? `1-${sortTime}` : `0-${sortTime}`; // 0=live, 1=completed
|
||||
} else {
|
||||
// PPR
|
||||
const aircraftId = departure.ac_call || departure.ac_reg || '';
|
||||
const aircraftDisplay = `${escapeHtml(aircraftId)} <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;
|
||||
let timeDisplay, sortTime;
|
||||
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>`;
|
||||
sortTime = departure.departed_dt;
|
||||
} else {
|
||||
timeDisplay = convertToLocalTime(departure.etd);
|
||||
sortTime = departure.etd;
|
||||
}
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${aircraftDisplay}</td>
|
||||
<td>${escapeHtml(toDisplay)}</td>
|
||||
<td>${timeDisplay}</td>
|
||||
</tr>
|
||||
`;
|
||||
html = `<tr><td>${aircraftDisplay}</td><td>${escapeHtml(toDisplay)}</td><td>${timeDisplay}</td></tr>`;
|
||||
sortKey = isDeparted ? `1-${sortTime}` : `0-${sortTime}`;
|
||||
}
|
||||
|
||||
return { html, sortKey, isDeparted };
|
||||
}));
|
||||
|
||||
tbody.innerHTML = rows.join('');
|
||||
// Sort: live flights first (0) by ETD ascending, then completed flights (1) by time descending
|
||||
rowsWithData.sort((a, b) => {
|
||||
const aParts = a.sortKey.split('-');
|
||||
const bParts = b.sortKey.split('-');
|
||||
const aType = parseInt(aParts[0]);
|
||||
const bType = parseInt(bParts[0]);
|
||||
|
||||
if (aType !== bType) return aType - bType; // Live before completed
|
||||
|
||||
// Sort by time
|
||||
if (aType === 0) {
|
||||
// Live flights: ascending (earliest first)
|
||||
return aParts[1].localeCompare(bParts[1]);
|
||||
} else {
|
||||
// Completed flights: descending (most recent first)
|
||||
return bParts[1].localeCompare(aParts[1]);
|
||||
}
|
||||
});
|
||||
|
||||
tbody.innerHTML = rowsWithData.map(r => r.html).join('');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading departures:', error);
|
||||
|
||||
Reference in New Issue
Block a user