Added pagination to the nodes list

This commit is contained in:
Pablo Revilla
2025-05-27 09:28:09 -07:00
parent 5f8c78cf98
commit 124c5f2840
2 changed files with 57 additions and 17 deletions

View File

@@ -9,7 +9,6 @@ table {
margin-right: auto;
}
th, td {
padding: 10px;
border: 1px solid #333;
@@ -67,7 +66,32 @@ tr:nth-child(odd) {
width: 80%;
margin-left: auto;
margin-right: auto;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 1em;
gap: 6px;
}
.pagination li {
list-style: none;
}
.pagination li a {
color: white;
background-color: #333;
padding: 6px 12px;
text-decoration: none;
border-radius: 4px;
border: 1px solid #555;
font-size: 14px;
}
.pagination li.active a {
background-color: #007bff;
border-color: #007bff;
}
{% endblock %}
@@ -139,6 +163,9 @@ tr:nth-child(odd) {
{% endfor %}
</tbody>
</table>
<!-- Pagination Controls -->
<div class="pagination"></div>
{% else %}
<p>No nodes found.</p>
{% endif %}
@@ -153,14 +180,19 @@ tr:nth-child(odd) {
valueNames: [
"long_name", "short_name", "hw_model", "firmware", "role",
"last_lat", "last_long", "channel", { name: "last_update", attr: "data-timestamp" }
]
],
page: 50,
pagination: {
paginationClass: "pagination"
}
};
nodeList = new List("node-list", options);
updateCount(); // Update count on load
updateCount();
nodeList.on("updated", function () {
updateCount(); // Update count when search or sort changes
updateCount();
});
});
@@ -176,7 +208,7 @@ tr:nth-child(odd) {
return matchesRole && matchesChannel && matchesHWModel;
});
updateCount(); // Update the count after filtering
updateCount();
}
function updateCount() {
@@ -189,22 +221,21 @@ tr:nth-child(odd) {
var rows = table.querySelectorAll("tr");
var csvContent = [];
// Extract header row
var headers = [];
table.querySelectorAll("th").forEach(th => headers.push(th.innerText));
csvContent.push(headers.join(","));
// Extract table rows
rows.forEach(row => {
var cells = row.querySelectorAll("td");
if (cells.length > 0) {
var rowData = [];
cells.forEach(cell => rowData.push(cell.innerText));
csvContent.push(rowData.join(","));
if (row.style.display !== "none") {
var cells = row.querySelectorAll("td");
if (cells.length > 0) {
var rowData = [];
cells.forEach(cell => rowData.push(cell.innerText));
csvContent.push(rowData.join(","));
}
}
});
// Create CSV file and trigger download
var csvString = csvContent.join("\n");
var blob = new Blob([csvString], { type: "text/csv" });
var a = document.createElement("a");

View File

@@ -1020,27 +1020,36 @@ async def nodelist(request):
content_type="text/plain",
)
@routes.get("/api")
async def api(request):
try:
# Extract optional query parameters
role = request.query.get("role")
channel = request.query.get("channel")
hw_model = request.query.get("hw_model")
# Fetch filtered nodes
nodes = await store.get_nodes(role, channel, hw_model)
# Convert node objects to dictionaries for JSON output
nodes_json = [node.to_dict() for node in nodes]
return web.json_response({"nodes": nodes_json})
# Return a pretty-printed JSON response
return web.json_response(
{"nodes": nodes_json},
dumps=lambda obj: json.dumps(obj, indent=2) # Pretty print for development
)
except Exception as e:
import traceback
# Log error and stack trace to console
print("Error in /api endpoint:", str(e))
print(traceback.format_exc())
# Return a plain-text error response
return web.Response(
text=f"An error occurred: {str(e)}",
status=500,
content_type="text/plain",
content_type="text/plain"
)