hot fixes for several UI and logic issues

This commit is contained in:
2025-11-17 15:41:51 -06:00
parent 5f2314a532
commit 72c4f3d29b
13 changed files with 233 additions and 93 deletions

View File

@@ -154,26 +154,33 @@
<form id="trigger-scan-form">
<div class="mb-3">
<label for="config-file" class="form-label">Config File</label>
<select class="form-select" id="config-file" name="config_file" required>
<select class="form-select" id="config-file" name="config_file" required {% if not config_files %}disabled{% endif %}>
<option value="">Select a config file...</option>
{% for config in config_files %}
<option value="{{ config }}">{{ config }}</option>
{% endfor %}
</select>
{% if config_files %}
<div class="form-text text-muted">
{% if config_files %}
Select a scan configuration file
{% else %}
<span class="text-warning">No config files found in /app/configs/</span>
{% endif %}
Select a scan configuration file
</div>
{% else %}
<div class="alert alert-warning mt-2 mb-0" role="alert">
<i class="bi bi-exclamation-triangle"></i>
<strong>No configurations available</strong>
<p class="mb-2 mt-2">You need to create a configuration file before you can trigger a scan.</p>
<a href="{{ url_for('main.upload_config') }}" class="btn btn-sm btn-primary">
<i class="bi bi-plus-circle"></i> Create Configuration
</a>
</div>
{% endif %}
</div>
<div id="trigger-error" class="alert alert-danger" style="display: none;"></div>
</form>
</div>
<div class="modal-footer" style="border-top: 1px solid #334155;">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="triggerScan()">
<button type="button" class="btn btn-primary" onclick="triggerScan()" {% if not config_files %}disabled{% endif %}>
<span id="modal-trigger-text">Trigger Scan</span>
<span id="modal-trigger-spinner" class="spinner-border spinner-border-sm ms-2" style="display: none;"></span>
</button>

View File

@@ -28,6 +28,13 @@
<!-- Error State -->
<div id="comparison-error" class="alert alert-danger" style="display: none;"></div>
<!-- Config Warning -->
<div id="config-warning" class="alert alert-warning" style="display: none;">
<i class="bi bi-exclamation-triangle"></i>
<strong>Different Configurations Detected</strong>
<p class="mb-0" id="config-warning-message"></p>
</div>
<!-- Comparison Content -->
<div id="comparison-content" style="display: none;">
<!-- Drift Score Card -->
@@ -52,14 +59,16 @@
<div class="mb-3">
<label class="form-label text-muted">Older Scan (#<span id="scan1-id"></span>)</label>
<div id="scan1-title" class="fw-bold">-</div>
<small class="text-muted" id="scan1-timestamp">-</small>
<small class="text-muted d-block" id="scan1-timestamp">-</small>
<small class="text-muted d-block"><i class="bi bi-file-earmark-text"></i> <span id="scan1-config">-</span></small>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label text-muted">Newer Scan (#<span id="scan2-id"></span>)</label>
<div id="scan2-title" class="fw-bold">-</div>
<small class="text-muted" id="scan2-timestamp">-</small>
<small class="text-muted d-block" id="scan2-timestamp">-</small>
<small class="text-muted d-block"><i class="bi bi-file-earmark-text"></i> <span id="scan2-config">-</span></small>
</div>
</div>
<div class="col-md-4">
@@ -340,6 +349,14 @@
}
function populateComparison(data) {
// Show config warning if configs differ
if (data.config_warning) {
const warningDiv = document.getElementById('config-warning');
const warningMessage = document.getElementById('config-warning-message');
warningMessage.textContent = data.config_warning;
warningDiv.style.display = 'block';
}
// Drift score
const driftScore = data.drift_score || 0;
document.getElementById('drift-score').textContent = driftScore.toFixed(3);
@@ -358,10 +375,12 @@
document.getElementById('scan1-id').textContent = data.scan1.id;
document.getElementById('scan1-title').textContent = data.scan1.title || 'Untitled Scan';
document.getElementById('scan1-timestamp').textContent = new Date(data.scan1.timestamp).toLocaleString();
document.getElementById('scan1-config').textContent = data.scan1.config_file || 'Unknown';
document.getElementById('scan2-id').textContent = data.scan2.id;
document.getElementById('scan2-title').textContent = data.scan2.title || 'Untitled Scan';
document.getElementById('scan2-timestamp').textContent = new Date(data.scan2.timestamp).toLocaleString();
document.getElementById('scan2-config').textContent = data.scan2.config_file || 'Unknown';
// Ports comparison
populatePortsComparison(data.ports);

View File

@@ -457,24 +457,44 @@
// Find previous scan and show compare button
let previousScanId = null;
let currentConfigFile = null;
async function findPreviousScan() {
try {
// Get list of scans to find the previous one
// Get current scan details first to know which config it used
const currentScanResponse = await fetch(`/api/scans/${scanId}`);
const currentScanData = await currentScanResponse.json();
currentConfigFile = currentScanData.config_file;
// Get list of completed scans
const response = await fetch('/api/scans?per_page=100&status=completed');
const data = await response.json();
if (data.scans && data.scans.length > 0) {
// Find scans older than current scan
// Find the current scan
const currentScanIndex = data.scans.findIndex(s => s.id === scanId);
if (currentScanIndex !== -1 && currentScanIndex < data.scans.length - 1) {
// Get the next scan in the list (which is older due to desc order)
previousScanId = data.scans[currentScanIndex + 1].id;
if (currentScanIndex !== -1) {
// Look for the most recent previous scan with the SAME config file
for (let i = currentScanIndex + 1; i < data.scans.length; i++) {
const previousScan = data.scans[i];
// Show the compare button
const compareBtn = document.getElementById('compare-btn');
if (compareBtn) {
compareBtn.style.display = 'inline-block';
// Check if this scan uses the same config
if (previousScan.config_file === currentConfigFile) {
previousScanId = previousScan.id;
// Show the compare button
const compareBtn = document.getElementById('compare-btn');
if (compareBtn) {
compareBtn.style.display = 'inline-block';
compareBtn.title = `Compare with Scan #${previousScanId} (same config)`;
}
break; // Found the most recent matching scan
}
}
// If no matching config found, don't show compare button
if (!previousScanId) {
console.log('No previous scans found with the same configuration');
}
}
}

View File

@@ -114,26 +114,33 @@
<form id="trigger-scan-form">
<div class="mb-3">
<label for="config-file" class="form-label">Config File</label>
<select class="form-select" id="config-file" name="config_file" required>
<select class="form-select" id="config-file" name="config_file" required {% if not config_files %}disabled{% endif %}>
<option value="">Select a config file...</option>
{% for config in config_files %}
<option value="{{ config }}">{{ config }}</option>
{% endfor %}
</select>
{% if config_files %}
<div class="form-text text-muted">
{% if config_files %}
Select a scan configuration file
{% else %}
<span class="text-warning">No config files found in /app/configs/</span>
{% endif %}
Select a scan configuration file
</div>
{% else %}
<div class="alert alert-warning mt-2 mb-0" role="alert">
<i class="bi bi-exclamation-triangle"></i>
<strong>No configurations available</strong>
<p class="mb-2 mt-2">You need to create a configuration file before you can trigger a scan.</p>
<a href="{{ url_for('main.upload_config') }}" class="btn btn-sm btn-primary">
<i class="bi bi-plus-circle"></i> Create Configuration
</a>
</div>
{% endif %}
</div>
<div id="trigger-error" class="alert alert-danger" style="display: none;"></div>
</form>
</div>
<div class="modal-footer" style="border-top: 1px solid #334155;">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="triggerScan()">
<button type="button" class="btn btn-primary" onclick="triggerScan()" {% if not config_files %}disabled{% endif %}>
<span id="modal-trigger-text">Trigger Scan</span>
<span id="modal-trigger-spinner" class="spinner-border spinner-border-sm ms-2" style="display: none;"></span>
</button>

View File

@@ -420,7 +420,8 @@ document.getElementById('create-schedule-form').addEventListener('submit', async
// Show notification
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
notification.className = `alert alert-${type} alert-dismissible fade show`;
notification.style.position = 'fixed';
notification.style.top = '20px';
notification.style.right = '20px';
notification.style.zIndex = '9999';

View File

@@ -555,7 +555,8 @@ async function deleteSchedule() {
// Show notification
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
notification.className = `alert alert-${type} alert-dismissible fade show`;
notification.style.position = 'fixed';
notification.style.top = '20px';
notification.style.right = '20px';
notification.style.zIndex = '9999';

View File

@@ -354,7 +354,8 @@ async function deleteSchedule(scheduleId) {
function showNotification(message, type = 'info') {
// Create notification element
const notification = document.createElement('div');
notification.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
notification.className = `alert alert-${type} alert-dismissible fade show`;
notification.style.position = 'fixed';
notification.style.top = '20px';
notification.style.right = '20px';
notification.style.zIndex = '9999';