fix: settings S3 surfaces fetch errors; recorder signal dot pulses

- screens-admin.jsx S3SettingsCard: when /settings/s3 fails, log to
  console and surface the message in the existing SettingsMsg banner
  instead of silently returning empty fields. Also logs the response
  payload on success so the next "endpoint blank" report is easier to
  diagnose. (closes part of #15)
- screens-ingest.jsx recorder row: wrap the signal value in a dot+text
  pair; add CSS so the dot pulses green when status=receiving and
  matches the value color otherwise. The pulse is the kind of cue the
  Live signal column was missing per #2.
This commit is contained in:
Zac Gaetano 2026-05-23 13:19:48 -04:00
parent 2515258dd4
commit 7e64675aa5
3 changed files with 44 additions and 3 deletions

View file

@ -1235,11 +1235,25 @@ function S3SettingsCard() {
React.useEffect(() => {
window.ZAMPP_API.fetch('/settings/s3')
.then(data => {
setS3({ s3_endpoint: data.s3_endpoint || '', s3_bucket: data.s3_bucket || '', s3_access_key: data.s3_access_key || '', s3_secret_key: '', s3_region: data.s3_region || 'us-east-1' });
// Diagnostic: previous reports of "endpoint always blank" were
// hard to chase without seeing the raw payload. Log it once on
// load so the next user can verify quickly.
try { console.debug('[settings] /settings/s3 →', data); } catch (_) {}
setS3({
s3_endpoint: data.s3_endpoint || '',
s3_bucket: data.s3_bucket || '',
s3_access_key: data.s3_access_key || '',
s3_secret_key: '',
s3_region: data.s3_region || 'us-east-1',
});
setSecretExists(!!data.s3_secret_key_exists);
setLoading(false);
})
.catch(() => setLoading(false));
.catch(err => {
console.error('[settings] /settings/s3 failed:', err);
setMsg({ ok: false, text: 'Could not load S3 settings: ' + (err.message || err) });
setLoading(false);
});
}, []);
const save = () => {

View file

@ -413,7 +413,10 @@ function RecorderRow({ recorder: initialRecorder, onRefresh }) {
</div>
<div className="recorder-stat">
<div className="stat-label">Signal</div>
<div className="stat-val" style={{ fontSize: 11, color: signalColor }}>{displaySignal}</div>
<div className="stat-val signal-val" style={{ fontSize: 11, color: signalColor }}>
<span className={'signal-dot ' + displaySignal} style={{ background: signalColor }} />
{displaySignal}
</div>
</div>
{liveStatus?.currentFps != null && (
<div className="recorder-stat">

View file

@ -517,3 +517,27 @@
box-shadow: 0 0 0 3px var(--live-soft);
animation: pulse 1.6s ease-in-out infinite;
}
/* ============================================================
Recorder row signal indicator with a pulsing dot when
actually receiving frames. Closes part of #2.
============================================================ */
.signal-val {
display: inline-flex;
align-items: center;
gap: 6px;
}
.signal-dot {
width: 6px;
height: 6px;
border-radius: 50%;
flex-shrink: 0;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.04);
}
.signal-dot.receiving {
animation: signalPulse 1.4s ease-in-out infinite;
}
@keyframes signalPulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(45, 212, 168, 0.6); }
50% { box-shadow: 0 0 0 6px rgba(45, 212, 168, 0); }
}