Files
labhelper/boxes/templates/admin/boxes/box/change_list.html
2026-01-20 00:18:05 +01:00

127 lines
3.8 KiB
HTML

{% extends "admin/change_list.html" %}
{% block extrahead %}
{{ block.super }}
<style>
#result_list tbody tr {
cursor: move;
}
#result_list tbody tr.dragging {
opacity: 0.5;
background: #ffffd0;
}
#result_list tbody tr.drag-over {
border-top: 2px solid #417690;
}
</style>
{% endblock %}
{% block result_list %}
{{ block.super }}
<script>
document.addEventListener('DOMContentLoaded', function() {
const tbody = document.querySelector('#result_list tbody');
if (!tbody) return;
let draggedRow = null;
tbody.querySelectorAll('tr').forEach(row => {
row.draggable = true;
row.addEventListener('dragstart', function(e) {
draggedRow = this;
this.classList.add('dragging');
e.dataTransfer.effectAllowed = 'move';
});
row.addEventListener('dragend', function() {
this.classList.remove('dragging');
tbody.querySelectorAll('tr').forEach(r => r.classList.remove('drag-over'));
draggedRow = null;
});
row.addEventListener('dragover', function(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
if (this !== draggedRow) {
this.classList.add('drag-over');
}
});
row.addEventListener('dragleave', function() {
this.classList.remove('drag-over');
});
row.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('drag-over');
if (draggedRow && this !== draggedRow) {
const allRows = Array.from(tbody.querySelectorAll('tr'));
const draggedIndex = allRows.indexOf(draggedRow);
const targetIndex = allRows.indexOf(this);
if (draggedIndex < targetIndex) {
this.parentNode.insertBefore(draggedRow, this.nextSibling);
} else {
this.parentNode.insertBefore(draggedRow, this);
}
saveOrder();
}
});
});
function saveOrder() {
const rows = tbody.querySelectorAll('tr');
const order = [];
rows.forEach(row => {
// Use the action checkbox which contains the PK
const checkbox = row.querySelector('input[name="_selected_action"]');
if (checkbox) {
order.push(checkbox.value);
}
});
fetch('{% url "admin:boxes_box_reorder" %}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]')?.value || getCookie('csrftoken')
},
body: JSON.stringify({ order: order })
})
.then(response => response.json())
.then(data => {
if (data.status === 'ok') {
window.location.reload();
} else {
console.error('Reorder failed:', data.error);
alert('Failed to save order');
}
})
.catch(error => {
console.error('Reorder error:', error);
alert('Failed to save order');
});
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
});
</script>
{% endblock %}