- Implemented a new API router for managing report templates, including endpoints for listing, creating, retrieving, updating, and deleting templates. - Added a new HTML partial for a unified SLM settings modal, allowing users to configure SLM settings with dynamic modem selection and FTP credentials. - Created a report preview page with an editable data table using jspreadsheet, enabling users to modify report details and download the report as an Excel file.
535 lines
26 KiB
HTML
535 lines
26 KiB
HTML
<!-- Unified SLM Settings Modal - Include this partial where SLM settings are needed -->
|
|
<!-- Usage: include 'partials/slm_settings_modal.html' (with Jinja braces) -->
|
|
<!-- Then call: openSLMSettingsModal(unitId) from JavaScript -->
|
|
|
|
<div id="slm-settings-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center overflow-y-auto">
|
|
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl w-full max-w-2xl m-4 my-8">
|
|
<!-- Header -->
|
|
<div class="p-6 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<svg class="w-8 h-8 text-seismo-orange" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"></path>
|
|
</svg>
|
|
<div>
|
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">SLM Configuration</h3>
|
|
<p id="slm-settings-unit-display" class="text-sm text-gray-500 dark:text-gray-400"></p>
|
|
</div>
|
|
</div>
|
|
<button onclick="closeSLMSettingsModal()" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
|
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<form id="slm-settings-form" onsubmit="saveSLMSettings(event)" class="p-6 space-y-6">
|
|
<input type="hidden" id="slm-settings-unit-id">
|
|
|
|
<!-- Network Configuration -->
|
|
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white mb-4 flex items-center gap-2">
|
|
<svg class="w-5 h-5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"></path>
|
|
</svg>
|
|
Network Configuration
|
|
</h4>
|
|
|
|
<div class="space-y-4">
|
|
<!-- Modem Selection -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Connected via Modem</label>
|
|
<div class="flex gap-2">
|
|
<select id="slm-settings-modem" class="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
|
<option value="">Select a modem...</option>
|
|
<!-- Modems loaded dynamically -->
|
|
</select>
|
|
<button type="button" onclick="testModemConnection()" id="slm-settings-test-modem-btn"
|
|
class="px-4 py-2 text-blue-700 dark:text-blue-300 bg-blue-100 dark:bg-blue-900 hover:bg-blue-200 dark:hover:bg-blue-800 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
disabled title="Test modem connectivity">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Select the modem this SLM is connected through</p>
|
|
</div>
|
|
|
|
<!-- Port Configuration -->
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">TCP Port</label>
|
|
<input type="number" id="slm-settings-tcp-port"
|
|
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
|
|
placeholder="2255" min="1" max="65535" value="2255">
|
|
<p class="text-xs text-gray-500 mt-1">Control port (default: 2255)</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">FTP Port</label>
|
|
<input type="number" id="slm-settings-ftp-port"
|
|
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
|
|
placeholder="21" min="1" max="65535" value="21">
|
|
<p class="text-xs text-gray-500 mt-1">File transfer (default: 21)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FTP Credentials -->
|
|
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white mb-4 flex items-center gap-2">
|
|
<svg class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path>
|
|
</svg>
|
|
FTP Credentials
|
|
</h4>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Username</label>
|
|
<input type="text" id="slm-settings-ftp-username"
|
|
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
|
|
placeholder="anonymous">
|
|
<p class="text-xs text-gray-500 mt-1">Leave blank for anonymous</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Password</label>
|
|
<input type="password" id="slm-settings-ftp-password"
|
|
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
|
|
placeholder="Leave blank to keep existing">
|
|
<p class="text-xs text-gray-500 mt-1">Leave blank to keep existing</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Device Information -->
|
|
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white mb-4 flex items-center gap-2">
|
|
<svg class="w-5 h-5 text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"></path>
|
|
</svg>
|
|
Device Information
|
|
</h4>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Model</label>
|
|
<select id="slm-settings-model" class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
|
<option value="">Select model...</option>
|
|
<option value="NL-43">NL-43</option>
|
|
<option value="NL-53">NL-53</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Serial Number</label>
|
|
<input type="text" id="slm-settings-serial"
|
|
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
|
|
placeholder="e.g., SN123456">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-3 gap-4 mt-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Frequency Weighting</label>
|
|
<select id="slm-settings-freq-weighting" class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
|
<option value="">Select...</option>
|
|
<option value="A">A-weighting</option>
|
|
<option value="C">C-weighting</option>
|
|
<option value="Z">Z-weighting (Linear)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Time Weighting</label>
|
|
<select id="slm-settings-time-weighting" class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
|
<option value="">Select...</option>
|
|
<option value="Fast">Fast (125ms)</option>
|
|
<option value="Slow">Slow (1s)</option>
|
|
<option value="Impulse">Impulse</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Measurement Range</label>
|
|
<select id="slm-settings-range" class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
|
<option value="">Select...</option>
|
|
<option value="30-130">30-130 dB</option>
|
|
<option value="40-140">40-140 dB</option>
|
|
<option value="50-140">50-140 dB</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FTP Enable Toggle -->
|
|
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
|
<label class="flex items-center justify-between cursor-pointer">
|
|
<div class="flex items-center gap-3">
|
|
<svg class="w-5 h-5 text-orange-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"></path>
|
|
</svg>
|
|
<div>
|
|
<span class="font-medium text-gray-900 dark:text-white">FTP File Transfer</span>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400">Enable FTP for file browsing and downloads</p>
|
|
</div>
|
|
</div>
|
|
<input type="checkbox" id="slm-settings-ftp-enabled"
|
|
class="w-5 h-5 text-seismo-orange rounded border-gray-300 dark:border-gray-600 focus:ring-seismo-orange">
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Status Messages -->
|
|
<div id="slm-settings-error" class="hidden text-sm p-3 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg"></div>
|
|
<div id="slm-settings-success" class="hidden text-sm p-3 bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-green-400 rounded-lg"></div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="flex justify-end gap-3 pt-2 border-t border-gray-200 dark:border-gray-700">
|
|
<button type="button" onclick="closeSLMSettingsModal()"
|
|
class="px-6 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
|
|
Cancel
|
|
</button>
|
|
<button type="button" onclick="testSLMConnection()"
|
|
class="px-6 py-2 text-blue-700 dark:text-blue-300 bg-blue-100 dark:bg-blue-900 hover:bg-blue-200 dark:hover:bg-blue-800 rounded-lg">
|
|
Test SLM Connection
|
|
</button>
|
|
<button type="submit" id="slm-settings-save-btn"
|
|
class="px-6 py-2 bg-seismo-orange hover:bg-orange-600 text-white rounded-lg font-medium">
|
|
Save Configuration
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// ========================================
|
|
// Unified SLM Settings Modal JavaScript
|
|
// ========================================
|
|
|
|
let slmSettingsModems = []; // Cache modems list
|
|
|
|
// Open the SLM Settings Modal
|
|
async function openSLMSettingsModal(unitId) {
|
|
const modal = document.getElementById('slm-settings-modal');
|
|
const errorDiv = document.getElementById('slm-settings-error');
|
|
const successDiv = document.getElementById('slm-settings-success');
|
|
|
|
// Clear previous messages
|
|
errorDiv.classList.add('hidden');
|
|
successDiv.classList.add('hidden');
|
|
|
|
// Store unit ID
|
|
document.getElementById('slm-settings-unit-id').value = unitId;
|
|
document.getElementById('slm-settings-unit-display').textContent = unitId;
|
|
|
|
// Load modems list if not cached
|
|
if (slmSettingsModems.length === 0) {
|
|
await loadModemsForSLMSettings();
|
|
}
|
|
|
|
// Load current config from both Terra-View and SLMM
|
|
try {
|
|
// Fetch Terra-View unit data
|
|
const unitResponse = await fetch(`/api/roster/${unitId}`);
|
|
const unitData = unitResponse.ok ? await unitResponse.json() : {};
|
|
|
|
// Fetch SLMM config
|
|
const slmmResponse = await fetch(`/api/slmm/${unitId}/config`);
|
|
const slmmResult = slmmResponse.ok ? await slmmResponse.json() : {};
|
|
const slmmData = slmmResult.data || slmmResult || {};
|
|
|
|
// Populate form fields
|
|
// Modem selection
|
|
const modemSelect = document.getElementById('slm-settings-modem');
|
|
modemSelect.value = unitData.deployed_with_modem_id || '';
|
|
updateTestModemButton();
|
|
|
|
// Ports
|
|
document.getElementById('slm-settings-tcp-port').value = unitData.slm_tcp_port || slmmData.tcp_port || 2255;
|
|
document.getElementById('slm-settings-ftp-port').value = unitData.slm_ftp_port || slmmData.ftp_port || 21;
|
|
|
|
// FTP credentials from SLMM
|
|
document.getElementById('slm-settings-ftp-username').value = slmmData.ftp_username || '';
|
|
document.getElementById('slm-settings-ftp-password').value = ''; // Don't pre-fill
|
|
|
|
// Device info from Terra-View
|
|
document.getElementById('slm-settings-model').value = unitData.slm_model || '';
|
|
document.getElementById('slm-settings-serial').value = unitData.slm_serial_number || '';
|
|
document.getElementById('slm-settings-freq-weighting').value = unitData.slm_frequency_weighting || '';
|
|
document.getElementById('slm-settings-time-weighting').value = unitData.slm_time_weighting || '';
|
|
document.getElementById('slm-settings-range').value = unitData.slm_measurement_range || '';
|
|
|
|
// FTP enabled from SLMM
|
|
document.getElementById('slm-settings-ftp-enabled').checked = slmmData.ftp_enabled === true;
|
|
|
|
} catch (error) {
|
|
console.error('Failed to load SLM settings:', error);
|
|
errorDiv.textContent = 'Failed to load configuration: ' + error.message;
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
|
|
modal.classList.remove('hidden');
|
|
}
|
|
|
|
// Close the modal
|
|
function closeSLMSettingsModal() {
|
|
document.getElementById('slm-settings-modal').classList.add('hidden');
|
|
}
|
|
|
|
// Alias for backwards compatibility with existing code
|
|
function showFTPSettings(unitId) {
|
|
openSLMSettingsModal(unitId);
|
|
}
|
|
function closeFTPSettings() {
|
|
closeSLMSettingsModal();
|
|
}
|
|
function openSettingsModal(unitId) {
|
|
openSLMSettingsModal(unitId);
|
|
}
|
|
function closeSettingsModal() {
|
|
closeSLMSettingsModal();
|
|
}
|
|
function openConfigModal(unitId) {
|
|
openSLMSettingsModal(unitId);
|
|
}
|
|
function closeConfigModal() {
|
|
closeSLMSettingsModal();
|
|
}
|
|
function openDeviceConfigModal(unitId) {
|
|
openSLMSettingsModal(unitId);
|
|
}
|
|
function closeDeviceConfigModal() {
|
|
closeSLMSettingsModal();
|
|
}
|
|
|
|
// Load modems for dropdown
|
|
async function loadModemsForSLMSettings() {
|
|
try {
|
|
const response = await fetch('/api/roster/modems');
|
|
slmSettingsModems = await response.json();
|
|
|
|
const select = document.getElementById('slm-settings-modem');
|
|
// Clear existing options except first
|
|
select.innerHTML = '<option value="">Select a modem...</option>';
|
|
|
|
slmSettingsModems.forEach(modem => {
|
|
const option = document.createElement('option');
|
|
option.value = modem.id;
|
|
const ipText = modem.ip_address ? ` (${modem.ip_address})` : '';
|
|
const deployedText = modem.deployed ? '' : ' [Benched]';
|
|
option.textContent = modem.id + ipText + deployedText;
|
|
select.appendChild(option);
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to load modems:', error);
|
|
}
|
|
}
|
|
|
|
// Update test modem button state based on selection
|
|
function updateTestModemButton() {
|
|
const modemSelect = document.getElementById('slm-settings-modem');
|
|
const testBtn = document.getElementById('slm-settings-test-modem-btn');
|
|
testBtn.disabled = !modemSelect.value;
|
|
}
|
|
|
|
// Listen for modem selection changes
|
|
document.getElementById('slm-settings-modem')?.addEventListener('change', updateTestModemButton);
|
|
|
|
// Test modem connection
|
|
async function testModemConnection() {
|
|
const modemId = document.getElementById('slm-settings-modem').value;
|
|
if (!modemId) return;
|
|
|
|
const errorDiv = document.getElementById('slm-settings-error');
|
|
const successDiv = document.getElementById('slm-settings-success');
|
|
|
|
errorDiv.classList.add('hidden');
|
|
successDiv.textContent = 'Pinging modem...';
|
|
successDiv.classList.remove('hidden');
|
|
|
|
try {
|
|
const response = await fetch(`/api/slm-dashboard/test-modem/${modemId}`);
|
|
const data = await response.json();
|
|
|
|
if (response.ok && data.status === 'success') {
|
|
const ipAddr = data.ip_address || modemId;
|
|
const respTime = data.response_time || 'N/A';
|
|
successDiv.textContent = `✓ Modem responding! ${ipAddr} - ${respTime}ms`;
|
|
} else {
|
|
successDiv.classList.add('hidden');
|
|
errorDiv.textContent = '⚠ Modem not responding: ' + (data.detail || 'Unknown error');
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
} catch (error) {
|
|
successDiv.classList.add('hidden');
|
|
errorDiv.textContent = 'Failed to ping modem: ' + error.message;
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
// Test SLM connection
|
|
async function testSLMConnection() {
|
|
const unitId = document.getElementById('slm-settings-unit-id').value;
|
|
const errorDiv = document.getElementById('slm-settings-error');
|
|
const successDiv = document.getElementById('slm-settings-success');
|
|
|
|
errorDiv.classList.add('hidden');
|
|
successDiv.textContent = 'Testing SLM connection...';
|
|
successDiv.classList.remove('hidden');
|
|
|
|
try {
|
|
const response = await fetch(`/api/slmm/${unitId}/status`);
|
|
const data = await response.json();
|
|
|
|
if (response.ok && data.status === 'online') {
|
|
successDiv.textContent = '✓ SLM connection successful! Device is responding.';
|
|
} else {
|
|
successDiv.classList.add('hidden');
|
|
errorDiv.textContent = '⚠ SLM not responding or offline. Check network settings.';
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
} catch (error) {
|
|
successDiv.classList.add('hidden');
|
|
errorDiv.textContent = 'Connection test failed: ' + error.message;
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
// Save SLM settings
|
|
async function saveSLMSettings(event) {
|
|
event.preventDefault();
|
|
|
|
const unitId = document.getElementById('slm-settings-unit-id').value;
|
|
const saveBtn = document.getElementById('slm-settings-save-btn');
|
|
const errorDiv = document.getElementById('slm-settings-error');
|
|
const successDiv = document.getElementById('slm-settings-success');
|
|
|
|
saveBtn.disabled = true;
|
|
saveBtn.textContent = 'Saving...';
|
|
errorDiv.classList.add('hidden');
|
|
successDiv.classList.add('hidden');
|
|
|
|
// Get selected modem and resolve its IP
|
|
const modemId = document.getElementById('slm-settings-modem').value;
|
|
let modemIp = '';
|
|
if (modemId) {
|
|
const modem = slmSettingsModems.find(m => m.id === modemId);
|
|
modemIp = modem?.ip_address || '';
|
|
}
|
|
|
|
// Validation
|
|
if (!modemId) {
|
|
errorDiv.textContent = 'Please select a modem';
|
|
errorDiv.classList.remove('hidden');
|
|
saveBtn.disabled = false;
|
|
saveBtn.textContent = 'Save Configuration';
|
|
return;
|
|
}
|
|
|
|
if (!modemIp) {
|
|
errorDiv.textContent = 'Selected modem has no IP address configured';
|
|
errorDiv.classList.remove('hidden');
|
|
saveBtn.disabled = false;
|
|
saveBtn.textContent = 'Save Configuration';
|
|
return;
|
|
}
|
|
|
|
const tcpPort = parseInt(document.getElementById('slm-settings-tcp-port').value) || 2255;
|
|
const ftpPort = parseInt(document.getElementById('slm-settings-ftp-port').value) || 21;
|
|
|
|
if (tcpPort < 1 || tcpPort > 65535 || ftpPort < 1 || ftpPort > 65535) {
|
|
errorDiv.textContent = 'Port values must be between 1 and 65535';
|
|
errorDiv.classList.remove('hidden');
|
|
saveBtn.disabled = false;
|
|
saveBtn.textContent = 'Save Configuration';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 1. Update Terra-View database (device info + modem assignment)
|
|
const terraViewData = {
|
|
deployed_with_modem_id: modemId,
|
|
slm_model: document.getElementById('slm-settings-model').value || null,
|
|
slm_serial_number: document.getElementById('slm-settings-serial').value || null,
|
|
slm_frequency_weighting: document.getElementById('slm-settings-freq-weighting').value || null,
|
|
slm_time_weighting: document.getElementById('slm-settings-time-weighting').value || null,
|
|
slm_measurement_range: document.getElementById('slm-settings-range').value || null,
|
|
slm_tcp_port: tcpPort,
|
|
slm_ftp_port: ftpPort
|
|
};
|
|
|
|
const terraResponse = await fetch(`/api/slm-dashboard/config/${unitId}`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
body: new URLSearchParams(terraViewData)
|
|
});
|
|
|
|
if (!terraResponse.ok) {
|
|
throw new Error('Failed to save Terra-View configuration');
|
|
}
|
|
|
|
// 2. Update SLMM config (network + FTP credentials)
|
|
const slmmData = {
|
|
host: modemIp,
|
|
tcp_port: tcpPort,
|
|
ftp_port: ftpPort,
|
|
ftp_username: document.getElementById('slm-settings-ftp-username').value.trim() || null,
|
|
ftp_enabled: document.getElementById('slm-settings-ftp-enabled').checked
|
|
};
|
|
|
|
// Only include password if entered
|
|
const password = document.getElementById('slm-settings-ftp-password').value;
|
|
if (password) {
|
|
slmmData.ftp_password = password;
|
|
}
|
|
|
|
const slmmResponse = await fetch(`/api/slmm/${unitId}/config`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(slmmData)
|
|
});
|
|
|
|
if (!slmmResponse.ok) {
|
|
const errData = await slmmResponse.json().catch(() => ({}));
|
|
throw new Error(errData.detail || 'Failed to save SLMM configuration');
|
|
}
|
|
|
|
successDiv.textContent = 'Configuration saved successfully!';
|
|
successDiv.classList.remove('hidden');
|
|
|
|
// Close modal after delay and refresh if needed
|
|
setTimeout(() => {
|
|
closeSLMSettingsModal();
|
|
// Try to refresh any FTP status or unit lists on the page
|
|
if (typeof checkFTPStatus === 'function') {
|
|
checkFTPStatus(unitId);
|
|
}
|
|
if (typeof htmx !== 'undefined') {
|
|
htmx.trigger('#slm-list', 'load');
|
|
}
|
|
}, 1500);
|
|
|
|
} catch (error) {
|
|
errorDiv.textContent = 'Error: ' + error.message;
|
|
errorDiv.classList.remove('hidden');
|
|
} finally {
|
|
saveBtn.disabled = false;
|
|
saveBtn.textContent = 'Save Configuration';
|
|
}
|
|
}
|
|
|
|
// Alias for backwards compatibility
|
|
async function saveFTPSettings(event) {
|
|
return saveSLMSettings(event);
|
|
}
|
|
|
|
// Close modal on background click
|
|
document.getElementById('slm-settings-modal')?.addEventListener('click', function(e) {
|
|
if (e.target === this) {
|
|
closeSLMSettingsModal();
|
|
}
|
|
});
|
|
</script>
|