127 lines
3.8 KiB
HTML
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 %}
|