hot fixes for several UI and logic issues
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user