feat: Add report templates API for CRUD operations and implement SLM settings modal
- 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.
This commit is contained in:
@@ -1307,123 +1307,6 @@ window.addEventListener('beforeunload', function() {
|
||||
// Timer will resume on next page load if measurement is still active
|
||||
stopMeasurementTimer();
|
||||
});
|
||||
|
||||
// ========================================
|
||||
// Settings Modal
|
||||
// ========================================
|
||||
async function openSettingsModal(unitId) {
|
||||
const modal = document.getElementById('settings-modal');
|
||||
const errorDiv = document.getElementById('settings-error');
|
||||
const successDiv = document.getElementById('settings-success');
|
||||
|
||||
// Clear previous messages
|
||||
errorDiv.classList.add('hidden');
|
||||
successDiv.classList.add('hidden');
|
||||
|
||||
// Store unit ID
|
||||
document.getElementById('settings-unit-id').value = unitId;
|
||||
|
||||
// Load current SLMM config
|
||||
try {
|
||||
const response = await fetch(`/api/slmm/${unitId}/config`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to load configuration');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
const config = result.data || {};
|
||||
|
||||
// Populate form fields
|
||||
document.getElementById('settings-host').value = config.host || '';
|
||||
document.getElementById('settings-tcp-port').value = config.tcp_port || 2255;
|
||||
document.getElementById('settings-ftp-port').value = config.ftp_port || 21;
|
||||
document.getElementById('settings-ftp-username').value = config.ftp_username || '';
|
||||
document.getElementById('settings-ftp-password').value = config.ftp_password || '';
|
||||
document.getElementById('settings-tcp-enabled').checked = config.tcp_enabled !== false;
|
||||
document.getElementById('settings-ftp-enabled').checked = config.ftp_enabled === true;
|
||||
document.getElementById('settings-web-enabled').checked = config.web_enabled === true;
|
||||
|
||||
modal.classList.remove('hidden');
|
||||
} catch (error) {
|
||||
console.error('Failed to load SLMM config:', error);
|
||||
errorDiv.textContent = 'Failed to load configuration: ' + error.message;
|
||||
errorDiv.classList.remove('hidden');
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function closeSettingsModal() {
|
||||
document.getElementById('settings-modal').classList.add('hidden');
|
||||
}
|
||||
|
||||
document.getElementById('settings-form').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const unitId = document.getElementById('settings-unit-id').value;
|
||||
const errorDiv = document.getElementById('settings-error');
|
||||
const successDiv = document.getElementById('settings-success');
|
||||
|
||||
errorDiv.classList.add('hidden');
|
||||
successDiv.classList.add('hidden');
|
||||
|
||||
// Gather form data
|
||||
const configData = {
|
||||
host: document.getElementById('settings-host').value.trim(),
|
||||
tcp_port: parseInt(document.getElementById('settings-tcp-port').value),
|
||||
ftp_port: parseInt(document.getElementById('settings-ftp-port').value),
|
||||
ftp_username: document.getElementById('settings-ftp-username').value.trim() || null,
|
||||
ftp_password: document.getElementById('settings-ftp-password').value || null,
|
||||
tcp_enabled: document.getElementById('settings-tcp-enabled').checked,
|
||||
ftp_enabled: document.getElementById('settings-ftp-enabled').checked,
|
||||
web_enabled: document.getElementById('settings-web-enabled').checked
|
||||
};
|
||||
|
||||
// Validation
|
||||
if (!configData.host) {
|
||||
errorDiv.textContent = 'Host/IP address is required';
|
||||
errorDiv.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
if (configData.tcp_port < 1 || configData.tcp_port > 65535) {
|
||||
errorDiv.textContent = 'TCP port must be between 1 and 65535';
|
||||
errorDiv.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
if (configData.ftp_port < 1 || configData.ftp_port > 65535) {
|
||||
errorDiv.textContent = 'FTP port must be between 1 and 65535';
|
||||
errorDiv.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/slmm/${unitId}/config`, {
|
||||
method: 'PUT',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(configData)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json().catch(() => ({}));
|
||||
throw new Error(data.detail || 'Failed to update configuration');
|
||||
}
|
||||
|
||||
successDiv.textContent = 'Configuration saved successfully!';
|
||||
successDiv.classList.remove('hidden');
|
||||
|
||||
// Close modal after 1.5 seconds
|
||||
setTimeout(() => {
|
||||
closeSettingsModal();
|
||||
// Optionally reload the page to reflect changes
|
||||
// window.location.reload();
|
||||
}, 1500);
|
||||
} catch (error) {
|
||||
errorDiv.textContent = error.message;
|
||||
errorDiv.classList.remove('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// ========================================
|
||||
// FTP Browser Modal
|
||||
// ========================================
|
||||
@@ -2201,125 +2084,6 @@ document.getElementById('preview-modal')?.addEventListener('click', function(e)
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Settings Modal -->
|
||||
<div id="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">
|
||||
<div class="p-6 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white">SLM Configuration</h3>
|
||||
<button onclick="closeSettingsModal()" 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="settings-form" class="p-6 space-y-6">
|
||||
<input type="hidden" id="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">Network Configuration</h4>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="col-span-2">
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Host / IP Address</label>
|
||||
<input type="text" id="settings-host"
|
||||
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., 192.168.1.100" required>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">TCP Port</label>
|
||||
<input type="number" id="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" required>
|
||||
<p class="text-xs text-gray-500 mt-1">Default: 2255 for NL-43/NL-53</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="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" required>
|
||||
<p class="text-xs text-gray-500 mt-1">Standard FTP port (default: 21)</p>
|
||||
</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">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="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="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="••••••••">
|
||||
<p class="text-xs text-gray-500 mt-1">Leave blank for anonymous</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Protocol Toggles -->
|
||||
<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">Protocol Settings</h4>
|
||||
|
||||
<div class="space-y-3">
|
||||
<label class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<div>
|
||||
<span class="font-medium text-gray-900 dark:text-white">TCP Communication</span>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Enable TCP control commands</p>
|
||||
</div>
|
||||
<input type="checkbox" id="settings-tcp-enabled"
|
||||
class="w-5 h-5 text-seismo-orange rounded border-gray-300 dark:border-gray-600 focus:ring-seismo-orange">
|
||||
</label>
|
||||
|
||||
<label class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<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 mt-1">Enable FTP file browsing and downloads</p>
|
||||
</div>
|
||||
<input type="checkbox" id="settings-ftp-enabled"
|
||||
class="w-5 h-5 text-seismo-orange rounded border-gray-300 dark:border-gray-600 focus:ring-seismo-orange">
|
||||
</label>
|
||||
|
||||
<label class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<div>
|
||||
<span class="font-medium text-gray-900 dark:text-white">Web Interface</span>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Enable web UI access (future feature)</p>
|
||||
</div>
|
||||
<input type="checkbox" id="settings-web-enabled"
|
||||
class="w-5 h-5 text-seismo-orange rounded border-gray-300 dark:border-gray-600 focus:ring-seismo-orange">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="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="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>
|
||||
|
||||
<div class="flex justify-end gap-3 pt-2 border-t border-gray-200 dark:border-gray-700">
|
||||
<button type="button" onclick="closeSettingsModal()"
|
||||
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="submit"
|
||||
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>
|
||||
|
||||
<!-- FTP Browser Modal -->
|
||||
<div id="ftp-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center">
|
||||
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl w-full max-w-4xl max-h-[90vh] overflow-hidden m-4 flex flex-col">
|
||||
@@ -2407,3 +2171,6 @@ document.getElementById('preview-modal')?.addEventListener('click', function(e)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Unified SLM Settings Modal -->
|
||||
{% include 'partials/slm_settings_modal.html' %}
|
||||
|
||||
Reference in New Issue
Block a user