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 16s
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 3s
133 lines
4.0 KiB
Python
133 lines
4.0 KiB
Python
from django.contrib.auth.decorators import login_required
|
|
from django.http import HttpResponse, JsonResponse
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
|
|
from .forms import ThingFormSet
|
|
from .models import Box, Thing, ThingType
|
|
|
|
|
|
@login_required
|
|
def index(request):
|
|
"""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,
|
|
})
|
|
|
|
|
|
@login_required
|
|
def box_detail(request, box_id):
|
|
"""Display contents of a box."""
|
|
box = get_object_or_404(Box, pk=box_id)
|
|
things = box.things.select_related('thing_type').all()
|
|
return render(request, 'boxes/box_detail.html', {
|
|
'box': box,
|
|
'things': things,
|
|
})
|
|
|
|
|
|
@login_required
|
|
def thing_detail(request, thing_id):
|
|
"""Display details of a thing."""
|
|
thing = get_object_or_404(
|
|
Thing.objects.select_related('thing_type', 'box', 'box__box_type'),
|
|
pk=thing_id
|
|
)
|
|
|
|
boxes = Box.objects.select_related('box_type').all().order_by('id')
|
|
|
|
if request.method == 'POST':
|
|
new_box_id = request.POST.get('new_box')
|
|
if new_box_id:
|
|
new_box = get_object_or_404(Box, pk=new_box_id)
|
|
thing.box = new_box
|
|
thing.save()
|
|
return redirect('thing_detail', thing_id=thing.id)
|
|
|
|
return render(request, 'boxes/thing_detail.html', {
|
|
'thing': thing,
|
|
'boxes': boxes,
|
|
})
|
|
|
|
|
|
@login_required
|
|
def search(request):
|
|
"""Search page for things."""
|
|
return render(request, 'boxes/search.html')
|
|
|
|
|
|
@login_required
|
|
def search_api(request):
|
|
"""AJAX endpoint for searching things."""
|
|
query = request.GET.get('q', '').strip()
|
|
if len(query) < 2:
|
|
return JsonResponse({'results': []})
|
|
|
|
things = Thing.objects.filter(
|
|
name__icontains=query
|
|
).select_related('thing_type', 'box')[:50]
|
|
|
|
results = [
|
|
{
|
|
'id': thing.id,
|
|
'name': thing.name,
|
|
'type': thing.thing_type.name,
|
|
'box': thing.box.id,
|
|
'description': thing.description[:100] if thing.description else '',
|
|
}
|
|
for thing in things
|
|
]
|
|
return JsonResponse({'results': results})
|
|
|
|
|
|
@login_required
|
|
def add_things(request, box_id):
|
|
"""Add multiple things to a box at once."""
|
|
box = get_object_or_404(Box, pk=box_id)
|
|
|
|
success_message = None
|
|
|
|
if request.method == 'POST':
|
|
formset = ThingFormSet(request.POST, queryset=Thing.objects.filter(box=box))
|
|
|
|
if formset.is_valid():
|
|
things = formset.save(commit=False)
|
|
created_count = 0
|
|
for thing in things:
|
|
if thing.name or thing.thing_type or thing.description or thing.picture:
|
|
thing.box = box
|
|
thing.save()
|
|
created_count += 1
|
|
if created_count > 0:
|
|
success_message = f'Added {created_count} thing{"s" if created_count > 1 else ""} successfully.'
|
|
formset = ThingFormSet(queryset=Thing.objects.filter(box=box))
|
|
else:
|
|
formset = ThingFormSet(queryset=Thing.objects.filter(box=box))
|
|
|
|
return render(request, 'boxes/add_things.html', {
|
|
'box': box,
|
|
'formset': formset,
|
|
'success_message': success_message,
|
|
})
|
|
|
|
|
|
@login_required
|
|
def thing_type_detail(request, type_id):
|
|
"""Display details of a thing type with its hierarchy and things."""
|
|
thing_type = get_object_or_404(ThingType, pk=type_id)
|
|
|
|
descendants = thing_type.get_descendants(include_self=True)
|
|
things_by_type = {}
|
|
|
|
for descendant in descendants:
|
|
things = descendant.things.select_related('box', 'box__box_type').all()
|
|
if things:
|
|
things_by_type[descendant] = things
|
|
|
|
return render(request, 'boxes/thing_type_detail.html', {
|
|
'thing_type': thing_type,
|
|
'things_by_type': things_by_type,
|
|
})
|