fix: add undo disk selection capability #2
@@ -4,6 +4,21 @@ from typing import Dict
|
||||
|
||||
web_router = APIRouter()
|
||||
|
||||
# Navigation configuration - NEW TABS GO HERE!
|
||||
NAVIGATION = [
|
||||
{"name": "home", "label": "Home", "url": "/", "icon": "bi-house"},
|
||||
{"name": "benchmark", "label": "Benchmark", "url": "/benchmark", "icon": "bi-hdd"},
|
||||
{"name": "jobs", "label": "Job Queue", "url": "/jobs", "icon": "bi-list-task"},
|
||||
]
|
||||
|
||||
def get_active_tab(url: str) -> str:
|
||||
"""Determine which navigation tab is active."""
|
||||
for nav_item in NAVIGATION:
|
||||
if nav_item["url"] == url:
|
||||
return nav_item["name"]
|
||||
return "home"
|
||||
|
||||
|
||||
@web_router.get("/")
|
||||
async def render_home(request: Request):
|
||||
"""
|
||||
@@ -14,6 +29,37 @@ async def render_home(request: Request):
|
||||
name="index.html",
|
||||
request=request,
|
||||
context={
|
||||
"tools":tools
|
||||
"tools":tools,
|
||||
"navigation": NAVIGATION,
|
||||
"active_tab": get_active_tab("/")
|
||||
}
|
||||
)
|
||||
|
||||
@web_router.get("/benchmark")
|
||||
async def render_benchmark(request: Request):
|
||||
"""Render the benchmark page."""
|
||||
templates: Jinja2Templates = request.app.state.templates
|
||||
|
||||
return templates.TemplateResponse(
|
||||
name="benchmark.html",
|
||||
request=request,
|
||||
context={
|
||||
"navigation": NAVIGATION,
|
||||
"active_tab": get_active_tab("/benchmark")
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@web_router.get("/jobs")
|
||||
async def render_jobs(request: Request):
|
||||
"""Render the job queue page."""
|
||||
templates: Jinja2Templates = request.app.state.templates
|
||||
|
||||
return templates.TemplateResponse(
|
||||
name="jobs.html",
|
||||
request=request,
|
||||
context={
|
||||
"navigation": NAVIGATION,
|
||||
"active_tab": get_active_tab("/jobs")
|
||||
}
|
||||
)
|
||||
+32
-5
@@ -3,20 +3,47 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Disk Checker</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet">
|
||||
<title>Disk Checker - {% block title %}Home{% endblock %}</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
{% block extra_css %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navigation Bar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">Disk Checker</a>
|
||||
<!-- Logo / Brand -->
|
||||
<a class="navbar-brand" href="/">
|
||||
<i class="bi bi-hdd-stack"></i>
|
||||
Disk Checker
|
||||
</a>
|
||||
|
||||
<!-- Mobile toggle -->
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
{% for nav_item in navigation %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_tab == nav_item.name %}active{% endif %}"
|
||||
href="{{ nav_item.url }}">
|
||||
<i class="bi {{ nav_item.icon }}"></i>
|
||||
{{ nav_item.label }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<!-- Page Content -->
|
||||
<div class="container mt-4">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Benchmark{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>Benchmark</h2>
|
||||
<p class="text-muted">Configure and run disk benchmarks.</p>
|
||||
|
||||
<!-- Placeholder content - will be implemented later -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Select Drive</h5>
|
||||
<p class="card-text">Choose a drive to benchmark from the list below.</p>
|
||||
|
||||
<!-- Drive selection will go here -->
|
||||
<div id="drive-selector"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,8 +1,10 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
{% block title %}Home{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<!--Available tools section-->
|
||||
<h2>Available Benchmarking Tools</h2>
|
||||
|
||||
@@ -37,8 +39,12 @@
|
||||
<i class="bi bi-info-circle"></i>
|
||||
Mounted drives are grayed out and cannot be benchmarked.
|
||||
</p>
|
||||
<div id="drives-list" hx-get="/api/v1/drives" hx-trigger="load" hx-target="#drives-content"></div>
|
||||
<div id="drives-list"
|
||||
hx-get="/api/v1/drives"
|
||||
hx-trigger="load"
|
||||
hx-target="#drives-content"></div>
|
||||
<div id="drives-content" class="row"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Job Queue{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>Job Queue</h2>
|
||||
<p class="text-muted">Monitor and manage benchmark jobs.</p>
|
||||
|
||||
<!-- Jobs list -->
|
||||
<div id="jobs-list"
|
||||
hx-get="/api/v1/jobs"
|
||||
hx-trigger="load"
|
||||
hx-target="#jobs-content">
|
||||
<p>Loading jobs...</p>
|
||||
</div>
|
||||
<div id="jobs-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// Load jobs when page loads
|
||||
document.addEventListener('htmx:afterRequest', function(evt) {
|
||||
if (evt.detail.target.id === 'jobs-content') {
|
||||
renderJobs(JSON.parse(evt.detail.xhr.response));
|
||||
}
|
||||
});
|
||||
|
||||
function renderJobs(jobIds) {
|
||||
const container = document.getElementById('jobs-content');
|
||||
container.innerHTML = '';
|
||||
|
||||
if (!jobIds || jobIds.length === 0) {
|
||||
container.innerHTML = '<div class="alert alert-info">No jobs in queue.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
jobIds.forEach(jobId => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'card mb-2';
|
||||
div.innerHTML = `
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${jobId}</h5>
|
||||
<p class="card-text text-muted">Job details will appear here...</p>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(div);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user