Files
AthonetTools/templates/pages/host_details.html

138 lines
6.5 KiB
HTML

{% extends "layout.html" %}
{% set active_page = 'system_browser' %}
{% block title %}Host Details - {{ super() }}{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 id="page-title" class="mb-0">Details for {{ details.system.hostname }}</h2>
<a href="{{ url_for('system_browser_page') }}" class="btn btn-secondary">
<i class="bi bi-arrow-left"></i> Back to System Browser
</a>
</div>
<hr>
{% if details and not details.error %}
<div class="row g-4">
<div class="col-md-4">
<h5>System Information</h5>
<dl class="row">
<dt class="col-sm-5">Hostname</dt><dd class="col-sm-7">{{ details.system.hostname }}</dd>
<dt class="col-sm-5">Customer</dt><dd class="col-sm-7">{{ details.browser_info.customer_name }}</dd>
<dt class="col-sm-5">Common Name</dt><dd class="col-sm-7">{{ details.browser_info.common_name }}</dd>
<dt class="col-sm-5">Virtual IP</dt><dd class="col-sm-7">{{ request.view_args.host_ip }}</dd>
<dt class="col-sm-5">Public IP</dt><dd class="col-sm-7">{{ details.browser_info.public_ip }}</dd>
<dt class="col-sm-5">Connected Since</dt><dd class="col-sm-7">{{ details.browser_info.connected_since }}</dd>
</dl>
</div>
<div class="col-md-4">
<h5>Site Information</h5>
<dl class="row">
<dt class="col-sm-4">Node Name</dt><dd class="col-sm-8">{{ details.site.current_node.name }}</dd>
<dt class="col-sm-4">API Address</dt><dd class="col-sm-8">{{ details.site.current_node.api_address }}</dd>
<dt class="col-sm-4">Site ID</dt><dd class="col-sm-8"><code>{{ details.licensed_host.siteid.value }}</code></dd>
</dl>
</div>
<div class="col-md-4">
<h5>License Information</h5>
{% if details.license and details.license.license and details.license.license.license_params %}
<dl class="row">
<dt class="col-sm-5">Status</dt><dd class="col-sm-7">{{ details.license.state.str }}</dd>
<dt class="col-sm-5">Start Date</dt><dd class="col-sm-7">{{ details.license.license.license_params.start_date_str }}</dd>
<dt class="col-sm-5">Expire Date</dt><dd class="col-sm-7">{{ details.license.license.license_params.expire_date_str }}</dd>
</dl>
{% else %}
<div class="alert alert-warning">No license information found.</div>
{% endif %}
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<h5>Services Status</h5>
<div class="table-responsive">
<table class="table table-sm table-dark table-hover table-compact">
<thead id="services-table-head">
<tr>
<th data-sort="name">Service <i class="bi bi-arrow-down-up"></i></th>
<th data-sort="version">Version <i class="bi bi-arrow-down-up"></i></th>
<th data-sort="state">Status <i class="bi bi-arrow-down-up"></i></th>
<th data-sort="license_id">License ID <i class="bi bi-arrow-down-up"></i></th>
<th data-sort="start_date">Start Date <i class="bi bi-arrow-down-up"></i></th>
<th data-sort="expire_date">Expire Date <i class="bi bi-arrow-down-up"></i></th>
</tr>
</thead>
<tbody id="services-table-body">
</tbody>
</table>
</div>
</div>
</div>
{% else %}
<div class="alert alert-danger">Could not load details for this host. Please check the server logs.</div>
{% endif %}
{% endblock %}
{% block extra_scripts %}
<script defer>
const allServices = {{ details.services|tojson }};
let currentSort = { column: 'name', direction: 'asc' };
function renderServiceTable(services) {
const tableBody = document.getElementById('services-table-body');
tableBody.innerHTML = '';
services.forEach(service => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${service.name}</td>
<td>${service.version}</td>
<td><span class="badge ${service.state === 'started' ? 'bg-success' : 'bg-danger'}">${service.state}</span></td>
<td><code>${service.license ? service.license.license_id : 'N/A'}</code></td>
<td>${service.license ? service.license.license.license_params.start_date_str : 'N/A'}</td>
<td>${service.license ? service.license.license.license_params.expire_date_str : 'N/A'}</td>
`;
tableBody.appendChild(row);
});
}
function sortAndRender() {
allServices.sort((a, b) => {
let valA, valB;
if (currentSort.column === 'license_id') {
valA = a.license ? a.license.license_id : '';
valB = b.license ? b.license.license_id : '';
} else if (currentSort.column === 'start_date' || currentSort.column === 'expire_date') {
valA = a.license ? a.license.license.license_params[currentSort.column + '_str'] : '';
valB = b.license ? b.license.license.license_params[currentSort.column + '_str'] : '';
} else {
valA = a[currentSort.column] || '';
valB = b[currentSort.column] || '';
}
if (valA < valB) return currentSort.direction === 'asc' ? -1 : 1;
if (valA > valB) return currentSort.direction === 'asc' ? 1 : -1;
return 0;
});
renderServiceTable(allServices);
}
document.addEventListener('DOMContentLoaded', () => {
sortAndRender();
});
document.getElementById('services-table-head').addEventListener('click', (event) => {
const header = event.target.closest('th[data-sort]');
if (header) {
const sortColumn = header.dataset.sort;
if (currentSort.column === sortColumn) {
currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc';
} else {
currentSort.column = sortColumn;
currentSort.direction = 'asc';
}
sortAndRender();
}
});
</script>
{% endblock %}