mirror of
https://github.com/smittix/intercept.git
synced 2026-07-07 17:18:11 -07:00
Stabilize satellite dashboard sidebar panels
This commit is contained in:
@@ -560,12 +560,24 @@ body {
|
|||||||
|
|
||||||
/* Pass list */
|
/* Pass list */
|
||||||
.pass-list {
|
.pass-list {
|
||||||
flex: 1;
|
flex: 0 0 auto;
|
||||||
min-height: 0;
|
min-height: 180px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gs-panel {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-height: 240px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gs-panel .panel-content {
|
||||||
|
height: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.pass-list-content {
|
.pass-list-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@@ -602,6 +602,7 @@
|
|||||||
let _txRequestId = 0;
|
let _txRequestId = 0;
|
||||||
let _telemetryPollTimer = null;
|
let _telemetryPollTimer = null;
|
||||||
let _passRequestId = 0;
|
let _passRequestId = 0;
|
||||||
|
const DASHBOARD_FETCH_TIMEOUT_MS = 10000;
|
||||||
const BUILTIN_TX_FALLBACK = {
|
const BUILTIN_TX_FALLBACK = {
|
||||||
25544: [
|
25544: [
|
||||||
{ description: 'APRS digipeater', downlink_low: 145.825, downlink_high: 145.825, uplink_low: null, uplink_high: null, mode: 'FM AX.25', baud: 1200, status: 'active', type: 'beacon', service: 'Packet' },
|
{ description: 'APRS digipeater', downlink_low: 145.825, downlink_high: 145.825, uplink_low: null, uplink_high: null, mode: 'FM AX.25', baud: 1200, status: 'active', type: 'beacon', service: 'Packet' },
|
||||||
@@ -630,7 +631,7 @@
|
|||||||
void btn.offsetWidth; // force reflow to restart animation
|
void btn.offsetWidth; // force reflow to restart animation
|
||||||
btn.classList.add('spinning');
|
btn.classList.add('spinning');
|
||||||
}
|
}
|
||||||
fetch('/satellite/tracked?enabled=true')
|
fetch('/satellite/tracked?enabled=true', { credentials: 'same-origin' })
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const prevSelected = selectedSatellite;
|
const prevSelected = selectedSatellite;
|
||||||
@@ -846,9 +847,13 @@
|
|||||||
if (!Number.isFinite(lat) || !Number.isFinite(lon) || !selectedSatellite) return;
|
if (!Number.isFinite(lat) || !Number.isFinite(lon) || !selectedSatellite) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), DASHBOARD_FETCH_TIMEOUT_MS);
|
||||||
const response = await fetch('/satellite/position', {
|
const response = await fetch('/satellite/position', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
signal: controller.signal,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
latitude: lat,
|
latitude: lat,
|
||||||
longitude: lon,
|
longitude: lon,
|
||||||
@@ -856,7 +861,10 @@
|
|||||||
includeTrack: false
|
includeTrack: false
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
clearTimeout(timeout);
|
||||||
if (!response.ok) return;
|
if (!response.ok) return;
|
||||||
|
const contentType = response.headers.get('Content-Type') || '';
|
||||||
|
if (!contentType.includes('application/json')) return;
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.status !== 'success' || !Array.isArray(data.positions)) return;
|
if (data.status !== 'success' || !Array.isArray(data.positions)) return;
|
||||||
if (!findSelectedPosition(data.positions)) {
|
if (!findSelectedPosition(data.positions)) {
|
||||||
@@ -1124,9 +1132,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), DASHBOARD_FETCH_TIMEOUT_MS);
|
||||||
const response = await fetch('/satellite/predict', {
|
const response = await fetch('/satellite/predict', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
signal: controller.signal,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
latitude: lat,
|
latitude: lat,
|
||||||
longitude: lon,
|
longitude: lon,
|
||||||
@@ -1135,7 +1147,12 @@
|
|||||||
satellites: [selectedSatellite]
|
satellites: [selectedSatellite]
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
const contentType = response.headers.get('Content-Type') || '';
|
||||||
|
if (!contentType.includes('application/json')) {
|
||||||
|
throw new Error('Unexpected response while calculating passes');
|
||||||
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (requestId !== _passRequestId) return;
|
if (requestId !== _passRequestId) return;
|
||||||
if (data.status === 'success') {
|
if (data.status === 'success') {
|
||||||
@@ -1156,12 +1173,20 @@
|
|||||||
renderPassList();
|
renderPassList();
|
||||||
document.getElementById('trackingStatus').textContent = 'ERROR';
|
document.getElementById('trackingStatus').textContent = 'ERROR';
|
||||||
document.getElementById('trackingDot').style.background = 'var(--accent-red)';
|
document.getElementById('trackingDot').style.background = 'var(--accent-red)';
|
||||||
|
if (container) {
|
||||||
|
container.innerHTML = `<div style="text-align:center;color:var(--text-secondary);padding:20px;">${data.message || 'Failed to calculate passes'}</div>`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (requestId !== _passRequestId) return;
|
if (requestId !== _passRequestId) return;
|
||||||
console.error('Pass calculation error:', err);
|
console.error('Pass calculation error:', err);
|
||||||
passes = [];
|
passes = [];
|
||||||
renderPassList();
|
if (container) {
|
||||||
|
const timedOut = err && (err.name === 'AbortError' || String(err).includes('AbortError'));
|
||||||
|
container.innerHTML = `<div style="text-align:center;color:var(--text-secondary);padding:20px;">${timedOut ? 'Timed out calculating passes' : 'Failed to calculate passes'}</div>`;
|
||||||
|
} else {
|
||||||
|
renderPassList();
|
||||||
|
}
|
||||||
document.getElementById('trackingStatus').textContent = 'OFFLINE';
|
document.getElementById('trackingStatus').textContent = 'OFFLINE';
|
||||||
document.getElementById('trackingDot').style.background = 'var(--accent-red)';
|
document.getElementById('trackingDot').style.background = 'var(--accent-red)';
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1651,7 +1676,10 @@
|
|||||||
try {
|
try {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeout = setTimeout(() => controller.abort(), 7000);
|
const timeout = setTimeout(() => controller.abort(), 7000);
|
||||||
const r = await fetch(`/satellite/transmitters/${noradId}`, { signal: controller.signal });
|
const r = await fetch(`/satellite/transmitters/${noradId}`, {
|
||||||
|
signal: controller.signal,
|
||||||
|
credentials: 'same-origin'
|
||||||
|
});
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
|
|||||||
Reference in New Issue
Block a user