feat: add calibration sync system.

This commit is contained in:
2026-06-04 18:52:22 +00:00
parent 56bd3041cf
commit 6c41ccf1bd
4 changed files with 388 additions and 0 deletions
+49
View File
@@ -472,6 +472,20 @@
<button onclick="saveCalibrationDefaults()" class="mt-6 px-6 py-3 bg-seismo-orange hover:bg-orange-600 text-white rounded-lg transition-colors">
Save Defaults
</button>
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">Sync from SFM events</h3>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-3">
Reads <code>calibration_date</code> from each seismograph's most recent event sidecar and updates
<em>Last Calibrated</em> when the device reports a newer date than what's stored.
Manual edits made after the latest event are preserved. Runs automatically once a day.
</p>
<button onclick="runCalibrationSync()" id="cal-sync-btn"
class="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors">
Sync now
</button>
<div id="cal-sync-result" class="mt-3 text-sm text-gray-700 dark:text-gray-300"></div>
</div>
</div>
</div>
</div>
@@ -890,6 +904,41 @@ async function saveCalibrationDefaults() {
}
}
async function runCalibrationSync() {
const btn = document.getElementById('cal-sync-btn');
const out = document.getElementById('cal-sync-result');
btn.disabled = true;
const originalLabel = btn.textContent;
btn.textContent = 'Syncing…';
out.textContent = '';
out.className = 'mt-3 text-sm text-gray-700 dark:text-gray-300';
try {
const response = await fetch('/api/calibration/sync', { method: 'POST' });
const data = await response.json();
if (!response.ok) {
out.className = 'mt-3 text-sm text-red-600 dark:text-red-400';
out.textContent = 'Error: ' + (data.detail || response.statusText);
return;
}
const parts = [
`Checked ${data.checked}`,
`Updated ${data.updated}`,
`Already in sync ${data.already_in_sync}`,
`Manual kept ${data.skipped_manual_newer}`,
`No event ${data.no_event}`,
];
if (data.errors) parts.push(`Errors ${data.errors}`);
out.textContent = parts.join(' · ');
} catch (error) {
out.className = 'mt-3 text-sm text-red-600 dark:text-red-400';
out.textContent = 'Error: ' + error.message;
} finally {
btn.disabled = false;
btn.textContent = originalLabel;
}
}
// ========== DATA TAB - IMPORT/EXPORT ==========
// Merge Mode Import