Add new front page with boxes and thing types tree
All checks were successful
Build containers when image tags change / build-if-image-changed (., web, containers, main container, git.baumann.gr/adebaumann/labhelper) (push) Successful in 29s
Build containers when image tags change / build-if-image-changed (data-loader, loader, initContainers, init-container, git.baumann.gr/adebaumann/labhelper-data-loader) (push) Successful in 6s

- Replace simple HTML index with full template
- Add grid of all boxes with details and item counts
- Add expandable tree view of thing types using MPTT
- Add 'mptt' to INSTALLED_APPS for recursetree tag
- Add jQuery for tree toggle functionality

Bump container version to 0.027
This commit is contained in:
2025-12-29 00:09:23 +01:00
parent fbd3c9bee5
commit 02e949d0ad
4 changed files with 214 additions and 4 deletions

View File

@@ -0,0 +1,205 @@
{% load mptt_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LabHelper</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
h1 {
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.nav-links {
margin-bottom: 20px;
text-align: right;
}
.nav-links a {
color: #4a90a4;
text-decoration: none;
margin-left: 20px;
}
.nav-links a:hover {
text-decoration: underline;
}
.section {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.section h2 {
color: #333;
margin-top: 0;
font-size: 20px;
border-bottom: 2px solid #4a90a4;
padding-bottom: 10px;
}
.box-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
}
.box-card {
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
border: 1px solid #e0e0e0;
transition: all 0.2s;
}
.box-card:hover {
border-color: #4a90a4;
box-shadow: 0 2px 5px rgba(74, 144, 164, 0.2);
}
.box-card a {
text-decoration: none;
color: #333;
display: block;
}
.box-card .box-id {
font-size: 18px;
font-weight: 600;
color: #4a90a4;
margin-bottom: 5px;
}
.box-card .box-type {
font-size: 14px;
color: #666;
}
.tree {
list-style: none;
padding-left: 20px;
}
.tree ul {
list-style: none;
padding-left: 20px;
}
.tree li {
padding: 5px 0;
}
.tree li a {
color: #4a90a4;
text-decoration: none;
font-size: 15px;
}
.tree li a:hover {
text-decoration: underline;
}
.tree-item {
display: flex;
align-items: center;
gap: 5px;
}
.tree-toggle {
cursor: pointer;
color: #999;
font-size: 14px;
user-select: none;
}
.tree ul {
list-style: none;
padding-left: 20px;
display: none;
}
.tree > li > ul {
display: block;
}
.tree li {
cursor: pointer;
}
.tree li a {
cursor: pointer;
}
.toggle-handle {
display: inline-block;
width: 20px;
color: #999;
font-weight: bold;
cursor: pointer;
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$(document).ready(function() {
$('.toggle-handle').click(function(e) {
e.stopPropagation();
var $ul = $(this).closest('li').children('ul');
if ($ul.length) {
$ul.toggle();
}
});
});
</script>
</head>
<body>
<div class="container">
<h1>LabHelper</h1>
<div class="nav-links">
<a href="/search/">Search Things</a>
<a href="/admin/">Admin</a>
</div>
<div class="section">
<h2>Boxes</h2>
{% if boxes %}
<div class="box-grid">
{% for box in boxes %}
<div class="box-card">
<a href="{% url 'box_detail' box.id %}">
<div class="box-id">Box {{ box.id }}</div>
<div class="box-type">{{ box.box_type.name }}</div>
<div class="box-type" style="font-size: 12px; margin-top: 3px;">
{{ box.box_type.width }} x {{ box.box_type.height }} x {{ box.box_type.length }} mm
</div>
<div class="box-type" style="font-size: 12px; margin-top: 3px;">
{{ box.things.count }} item{{ box.things.count|pluralize }}
</div>
</a>
</div>
{% endfor %}
</div>
{% else %}
<p>No boxes found.</p>
{% endif %}
</div>
<div class="section">
<h2>Thing Types</h2>
{% if thing_types %}
<ul class="tree">
{% recursetree thing_types %}
<li>
{% if children %}
<span class="toggle-handle">[-]</span>
{% else %}
<span class="toggle-handle">&nbsp;</span>
{% endif %}
<a href="{% url 'thing_type_detail' node.pk %}">{{ node.name }}</a>
{% if node.things.exists %}
<span style="color: #999; font-size: 13px;">({{ node.things.count }})</span>
{% endif %}
{% if children %}
<ul>
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
{% else %}
<p>No thing types found.</p>
{% endif %}
</div>
</div>
</body>
</html>

View File

@@ -6,9 +6,13 @@ from .models import Box, Thing, ThingType
def index(request):
"""Simple index page."""
html = '<h1>LabHelper</h1><p><a href="/search/">Search Things</a> | <a href="/admin/">Admin</a></p>'
return HttpResponse(html)
"""Home page with boxes and thing types."""
boxes = Box.objects.select_related('box_type').all().order_by('id')
thing_types = ThingType.objects.all()
return render(request, 'boxes/index.html', {
'boxes': boxes,
'thing_types': thing_types,
})
def box_detail(request, box_id):