FIXME created for quick tagging
All checks were successful
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
Build containers when image tags change / build-if-image-changed (., web, containers, main container, git.baumann.gr/adebaumann/labhelper) (push) Successful in 4s
All checks were successful
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
Build containers when image tags change / build-if-image-changed (., web, containers, main container, git.baumann.gr/adebaumann/labhelper) (push) Successful in 4s
This commit is contained in:
145
boxes/templates/boxes/fixme.html
Normal file
145
boxes/templates/boxes/fixme.html
Normal file
@@ -0,0 +1,145 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Fixme - LabHelper{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
<div class="page-header">
|
||||
<h1><i class="fas fa-exclamation-triangle"></i> Fixme</h1>
|
||||
<p class="breadcrumb">Find and fix things missing tags for specific facets</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="section">
|
||||
<h2><i class="fas fa-tags"></i> Select a Facet</h2>
|
||||
|
||||
{% if facets %}
|
||||
<form method="get" action="{% url 'fixme' %}" class="facet-selector">
|
||||
<select name="facet_id" id="facet-select" onchange="this.form.submit()" class="form-control">
|
||||
<option value="">-- Choose a facet --</option>
|
||||
{% for facet in facets %}
|
||||
<option value="{{ facet.id }}" {% if selected_facet and selected_facet.id == facet.id %}selected{% endif %}>
|
||||
{{ facet.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<noscript>
|
||||
<button type="submit" class="btn btn-sm">
|
||||
<i class="fas fa-search"></i> Show Missing Things
|
||||
</button>
|
||||
</noscript>
|
||||
</form>
|
||||
{% else %}
|
||||
<p style="color: #888;">No facets found. Please create some facets first.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if selected_facet %}
|
||||
<div class="section">
|
||||
<h2><i class="fas fa-exclamation-circle"></i> Things Missing "{{ selected_facet.name }}" Tags</h2>
|
||||
|
||||
{% if missing_things %}
|
||||
<form method="post" action="{% url 'fixme' %}" id="fixme-form">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="facet_id" value="{{ selected_facet.id }}">
|
||||
|
||||
<div class="tags-selection" style="margin-bottom: 20px;">
|
||||
<h3><i class="fas fa-plus-circle"></i> Add Tags:</h3>
|
||||
{% if selected_facet.tags.all %}
|
||||
{% for tag in selected_facet.tags.all %}
|
||||
<label style="display: inline-block; margin-right: 15px; margin-bottom: 10px;">
|
||||
<input type="checkbox" name="tag_ids" value="{{ tag.id }}"
|
||||
{% if selected_facet.cardinality == 'single' %}onclick="uncheckOtherTags(this)"{% endif %}>
|
||||
<span style="background: {{ tag.facet.color }}; color: white; padding: 2px 8px; border-radius: 4px; font-size: 12px;">
|
||||
{{ tag.name }}
|
||||
</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
{% if selected_facet.cardinality == 'single' %}
|
||||
<p style="color: #888; font-size: 12px; margin-top: 10px;">
|
||||
<i class="fas fa-info-circle"></i> This facet allows only one tag per thing.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p style="color: #888;">No tags available for this facet. Please create some tags first.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="things-list" style="margin-bottom: 20px;">
|
||||
<h3><i class="fas fa-box"></i> Things to Update:</h3>
|
||||
{% for thing in missing_things %}
|
||||
<div style="background: #f8f9fa; padding: 10px; margin: 5px 0; border-radius: 5px; border-left: 4px solid #667eea;">
|
||||
<label style="display: block; cursor: pointer; width: 100%;">
|
||||
<input type="checkbox" name="thing_ids" value="{{ thing.id }}" style="margin-right: 10px;">
|
||||
<strong>{{ thing.name }}</strong>
|
||||
<span style="color: #888; margin-left: 10px;">(Box: {{ thing.box.id }})</span>
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button type="submit" class="btn">
|
||||
<i class="fas fa-save"></i> Add Selected Tags to Selected Things
|
||||
</button>
|
||||
<a href="{% url 'fixme' %}" class="btn btn-secondary">
|
||||
<i class="fas fa-times"></i> Clear Selection
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<p style="color: #28a745;">
|
||||
<i class="fas fa-check-circle"></i> All things have tags for "{{ selected_facet.name }}" facet!
|
||||
</p>
|
||||
<a href="{% url 'fixme' %}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Back to Facet Selection
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
function uncheckOtherTags(checkbox) {
|
||||
// For single cardinality facets, uncheck all other checkboxes
|
||||
var checkboxes = document.querySelectorAll('input[name="tag_ids"]');
|
||||
checkboxes.forEach(function(cb) {
|
||||
if (cb !== checkbox) {
|
||||
cb.checked = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add select all/none functionality for things
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var fixmeForm = document.getElementById('fixme-form');
|
||||
if (fixmeForm) {
|
||||
var thingsList = fixmeForm.querySelector('.things-list');
|
||||
if (thingsList) {
|
||||
var header = document.createElement('div');
|
||||
header.style.marginBottom = '10px';
|
||||
header.innerHTML = `
|
||||
<small>
|
||||
<a href="#" onclick="selectAllThings(); return false;">Select All</a> |
|
||||
<a href="#" onclick="deselectAllThings(); return false;">Deselect All</a>
|
||||
</small>
|
||||
`;
|
||||
thingsList.insertBefore(header, thingsList.firstChild.nextSibling);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function selectAllThings() {
|
||||
var checkboxes = document.querySelectorAll('input[name="thing_ids"]');
|
||||
checkboxes.forEach(function(cb) { cb.checked = true; });
|
||||
}
|
||||
|
||||
function deselectAllThings() {
|
||||
var checkboxes = document.querySelectorAll('input[name="thing_ids"]');
|
||||
checkboxes.forEach(function(cb) { cb.checked = false; });
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@@ -2,7 +2,7 @@ import bleach
|
||||
import markdown
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q, Prefetch
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
@@ -402,3 +402,49 @@ def resources_list(request):
|
||||
return render(request, 'boxes/resources_list.html', {
|
||||
'resources': resources,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def fixme(request):
|
||||
"""Page to find and fix things missing tags for specific facets."""
|
||||
facets = Facet.objects.all().prefetch_related('tags')
|
||||
|
||||
selected_facet = None
|
||||
missing_things = []
|
||||
|
||||
if request.method == 'GET' and 'facet_id' in request.GET:
|
||||
try:
|
||||
selected_facet = Facet.objects.get(pk=request.GET['facet_id'])
|
||||
# Find things that don't have any tag from this facet
|
||||
missing_things = Thing.objects.exclude(
|
||||
tags__facet=selected_facet
|
||||
).select_related('box', 'box__box_type').prefetch_related('tags')
|
||||
except Facet.DoesNotExist:
|
||||
selected_facet = None
|
||||
|
||||
elif request.method == 'POST':
|
||||
facet_id = request.POST.get('facet_id')
|
||||
tag_ids = request.POST.getlist('tag_ids')
|
||||
thing_ids = request.POST.getlist('thing_ids')
|
||||
|
||||
if facet_id and tag_ids and thing_ids:
|
||||
facet = get_object_or_404(Facet, pk=facet_id)
|
||||
tags = Tag.objects.filter(id__in=tag_ids, facet=facet)
|
||||
things = Thing.objects.filter(id__in=thing_ids)
|
||||
|
||||
for thing in things:
|
||||
if facet.cardinality == Facet.Cardinality.SINGLE:
|
||||
# Remove existing tags from this facet
|
||||
thing.tags.remove(*thing.tags.filter(facet=facet))
|
||||
# Add new tags
|
||||
for tag in tags:
|
||||
if tag.facet == facet:
|
||||
thing.tags.add(tag)
|
||||
|
||||
return redirect('fixme')
|
||||
|
||||
return render(request, 'boxes/fixme.html', {
|
||||
'facets': facets,
|
||||
'selected_facet': selected_facet,
|
||||
'missing_things': missing_things,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user