138 lines
6.5 KiB
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 %} |