Files
Server_Monitorizare_v2/templates/ansible/failure_reports.html

145 lines
5.6 KiB
HTML

{% extends "base.html" %}
{% block title %}Execution Failure Reports — Server Monitoring{% endblock %}
{% block page_title %}Execution Failure Reports{% endblock %}
{% block content %}
<div class="container-fluid">
<div id="alertArea"></div>
<!-- Header row -->
<div class="d-flex justify-content-between align-items-center mb-3">
<p class="text-muted mb-0">
Saved records of failed or unreachable hosts from completed playbook executions.
</p>
<span class="badge bg-secondary fs-6">{{ reports | length }} report(s)</span>
</div>
{% if reports %}
<div class="row g-3" id="reportsList">
{% for report in reports %}
<div class="col-12" id="report-{{ report.id }}">
<div class="card shadow-sm border-{% if report.unreachable_count > 0 and report.failed_count == 0 %}warning{% elif report.failed_count > 0 %}danger{% else %}secondary{% endif %}">
<!-- Card header -->
<div class="card-header d-flex justify-content-between align-items-start flex-wrap gap-2 py-2">
<div>
<i class="fas fa-exclamation-triangle me-2 text-{% if report.failed_count > 0 %}danger{% else %}warning{% endif %}"></i>
<strong>{{ report.playbook_name }}</strong>
<span class="text-muted ms-2" style="font-size:.82rem;">
Execution <code>{{ report.execution_id[:8] }}…</code>
</span>
</div>
<div class="d-flex align-items-center gap-2">
{% if report.failed_count > 0 %}
<span class="badge bg-danger"><i class="fas fa-times-circle me-1"></i>{{ report.failed_count }} failed</span>
{% endif %}
{% if report.unreachable_count > 0 %}
<span class="badge bg-warning text-dark"><i class="fas fa-plug me-1"></i>{{ report.unreachable_count }} unreachable</span>
{% endif %}
<span class="text-muted" style="font-size:.78rem;">
<i class="fas fa-calendar-alt me-1"></i>{{ report.saved_at[:19].replace('T',' ') }}
</span>
<a href="/ansible/executions/{{ report.execution_id }}" class="btn btn-sm btn-outline-secondary" target="_blank"
title="View full execution">
<i class="fas fa-external-link-alt"></i>
</a>
<button class="btn btn-sm btn-outline-danger" onclick="deleteReport({{ report.id }})"
title="Delete this report">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<!-- Host list -->
<div class="card-body py-2 px-0">
{% if report.note %}
<div class="px-3 pb-2">
<i class="fas fa-sticky-note text-muted me-1"></i>
<small class="text-muted">{{ report.note }}</small>
</div>
{% endif %}
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<thead class="table-light">
<tr>
<th style="width:50%">Hostname</th>
<th style="width:20%">Status</th>
<th>Reason</th>
</tr>
</thead>
<tbody>
{% for host in report.failed_hosts %}
<tr>
<td><strong>{{ host.hostname }}</strong></td>
<td>
{% if host.status == 'unreachable' %}
<span class="badge bg-warning text-dark">unreachable</span>
{% else %}
<span class="badge bg-danger">failed</span>
{% endif %}
</td>
<td class="text-muted" style="font-size:.85rem;">{{ host.reason }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="card">
<div class="card-body text-center py-5 text-muted">
<i class="fas fa-check-circle fa-3x mb-3 text-success"></i>
<p class="mb-0">No failure reports saved yet.<br>
Use the <strong>Save Report</strong> button in the execution popup when a playbook has failed or unreachable hosts.
</p>
</div>
</div>
{% endif %}
</div>
<script>
const API = '/api/ansible';
function showAlert(html, type='info') {
const area = document.getElementById('alertArea');
area.innerHTML = `<div class="alert alert-${type} alert-dismissible fade show">
${html}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>`;
setTimeout(() => { if (area.firstChild) area.firstChild.remove(); }, 5000);
}
async function deleteReport(reportId) {
if (!confirm('Delete this failure report?')) return;
try {
const r = await fetch(`${API}/failure-reports/${reportId}`, {method:'DELETE'});
const d = await r.json();
if (d.success) {
document.getElementById(`report-${reportId}`).remove();
showAlert('<i class="fas fa-check-circle me-1"></i>Report deleted.', 'success');
// Show empty state if no more reports
if (!document.querySelector('#reportsList .col-12')) {
document.getElementById('reportsList').innerHTML =
'<div class="col-12"><div class="card"><div class="card-body text-center py-5 text-muted">' +
'<i class="fas fa-check-circle fa-3x mb-3 text-success"></i>' +
'<p class="mb-0">No failure reports saved yet.</p></div></div></div>';
}
} else {
showAlert(`Error: ${d.error}`, 'danger');
}
} catch(e) {
showAlert('Network error: ' + e, 'danger');
}
}
</script>
{% endblock %}