Initial commit of AthonetTools
This commit is contained in:
153
templates/pages/system_browser.html
Normal file
153
templates/pages/system_browser.html
Normal file
@@ -0,0 +1,153 @@
|
||||
{% extends "layout.html" %}
|
||||
{% set active_page = 'system_browser' %}
|
||||
{% block title %}System Browser - {{ super() }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 id="page-title" class="mb-0">System Browser</h2>
|
||||
</div>
|
||||
<hr>
|
||||
<div id="browser-view">
|
||||
<p>Retrieve and display live status information for all connected customer networks. You can search, sort, and filter the results.</p>
|
||||
<button class="btn btn-primary" id="getBrowserDataBtn">Get System Status</button>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 my-3 align-items-end">
|
||||
<div class="col-md-6">
|
||||
<label for="customer-filter" class="form-label">Filter by Customer</label>
|
||||
<select id="customer-filter" class="form-select"></select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="search-input" class="form-label">Search Results</label>
|
||||
<input type="text" id="search-input" class="form-control" placeholder="Search any column...">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<div id="spinner" class="d-none spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div>
|
||||
<div id="results-output" class="p-3"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script defer>
|
||||
let fullBrowserData = [];
|
||||
let currentSort = { column: 'customer_id', direction: 'asc' };
|
||||
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const customerFilter = document.getElementById('customer-filter');
|
||||
|
||||
function renderTable(data) {
|
||||
let tableHtml = `<table class="table table-dark table-hover table-sm table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="tree-item" data-sort="customer_id">Customer ID <i class="bi bi-arrow-down-up"></i></th>
|
||||
<th class="tree-item" data-sort="customer_name">Customer Name <i class="bi bi-arrow-down-up"></i></th>
|
||||
<th class="tree-item" data-sort="common_name">Common Name <i class="bi bi-arrow-down-up"></i></th>
|
||||
<th class="tree-item" data-sort="virtual_ip">Virtual IP <i class="bi bi-arrow-down-up"></i></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>`;
|
||||
|
||||
data.forEach(client => {
|
||||
// ADDED: The necessary attributes to make the row clickable
|
||||
tableHtml += `
|
||||
<tr class="clickable-row"
|
||||
data-host-ip="${client.virtual_ip}"
|
||||
data-public-ip="${client.public_ip}"
|
||||
data-connected-since="${client.connected_since}"
|
||||
data-customer-name="${client.customer_name}"
|
||||
data-common-name="${client.common_name}"
|
||||
style="cursor: pointer;">
|
||||
<td>${client.customer_id}</td>
|
||||
<td>${client.customer_name}</td>
|
||||
<td>${client.common_name}</td>
|
||||
<td><a href="http://${client.virtual_ip}" target="_blank">${client.virtual_ip}</a></td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
tableHtml += '</tbody></table>';
|
||||
resultsOutput.innerHTML = tableHtml;
|
||||
}
|
||||
|
||||
function populateCustomerFilter(data) {
|
||||
const customers = [...new Set(data.map(item => item.customer_name))].sort();
|
||||
customerFilter.innerHTML = '<option value="">All Customers</option>';
|
||||
customers.forEach(customer => {
|
||||
const option = document.createElement('option');
|
||||
option.value = customer;
|
||||
option.textContent = customer;
|
||||
customerFilter.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
function applyFiltersAndSort() {
|
||||
let filteredData = [...fullBrowserData];
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const selectedCustomer = customerFilter.value;
|
||||
|
||||
if (selectedCustomer) {
|
||||
filteredData = filteredData.filter(item => item.customer_name === selectedCustomer);
|
||||
}
|
||||
|
||||
if (searchTerm) {
|
||||
filteredData = filteredData.filter(item =>
|
||||
Object.values(item).some(value =>
|
||||
String(value).toLowerCase().includes(searchTerm)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
filteredData.sort((a, b) => {
|
||||
const valA = a[currentSort.column] || '';
|
||||
const valB = b[currentSort.column] || '';
|
||||
if (valA < valB) return currentSort.direction === 'asc' ? -1 : 1;
|
||||
if (valA > valB) return currentSort.direction === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
renderTable(filteredData);
|
||||
}
|
||||
|
||||
document.getElementById('getBrowserDataBtn').addEventListener('click', async () => {
|
||||
const browserData = await apiCall('/api/system-browser/data', {});
|
||||
if (browserData) {
|
||||
fullBrowserData = browserData;
|
||||
populateCustomerFilter(fullBrowserData);
|
||||
applyFiltersAndSort();
|
||||
}
|
||||
});
|
||||
|
||||
searchInput.addEventListener('input', applyFiltersAndSort);
|
||||
customerFilter.addEventListener('change', applyFiltersAndSort);
|
||||
|
||||
// RESTORED: The full click handler for the results area
|
||||
resultsOutput.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';
|
||||
}
|
||||
applyFiltersAndSort();
|
||||
return;
|
||||
}
|
||||
|
||||
const row = event.target.closest('.clickable-row');
|
||||
if (row) {
|
||||
const hostIp = row.dataset.hostIp;
|
||||
if (hostIp && hostIp !== 'N/A') {
|
||||
const customerName = encodeURIComponent(row.dataset.customerName);
|
||||
const commonName = encodeURIComponent(row.dataset.commonName);
|
||||
const publicIp = encodeURIComponent(row.dataset.publicIp);
|
||||
const connectedSince = encodeURIComponent(row.dataset.connectedSince);
|
||||
|
||||
window.location.href = `/host/${hostIp}?customer_name=${customerName}&common_name=${commonName}&public_ip=${publicIp}&connected_since=${connectedSince}`;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user