feat: focus priority, focus links, task list assignment, lists drag-and-drop, URL display fixes

- Focus page: turn sequence number into persistent editable priority (focus_priority column)
- Focus detail: add links section (add existing, create new, unlink) via focus_links junction table
- Focus detail: add copy and inline edit for checklist items
- Task detail lists tab: add existing list assignment and unlink actions
- Lists page: add drag-and-drop reorder support
- Links/bookmarks pages: remove artificial URL truncation, use CSS ellipsis

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 22:19:06 +00:00
parent 30cff10150
commit 590f019ca7
12 changed files with 291 additions and 19 deletions

View File

@@ -24,7 +24,7 @@
{% if items %}
<div class="card mt-3">
{% for item in items %}
<div class="list-row">
<div class="list-row lists-drag-row" draggable="true" data-id="{{ item.id }}">
{% with reorder_url="/lists/reorder", item_id=item.id %}
{% include 'partials/reorder_arrows.html' %}
{% endwith %}
@@ -53,6 +53,9 @@
</div>
{% endfor %}
</div>
<form id="lists-reorder-form" action="/lists/reorder-all" method="post" style="display:none;">
<input type="hidden" name="item_ids" id="lists-reorder-ids">
</form>
{% else %}
<div class="empty-state mt-3">
<div class="empty-state-icon">&#9776;</div>
@@ -63,6 +66,52 @@
<script>
(function() {
// Drag-and-drop reorder
var dragRow = null;
var container = document.querySelector('.card.mt-3');
if (container) {
container.querySelectorAll('.lists-drag-row').forEach(function(row) {
row.addEventListener('dragstart', function(e) {
dragRow = row;
row.classList.add('dragging');
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', row.dataset.id);
});
row.addEventListener('dragend', function() {
row.classList.remove('dragging');
container.querySelectorAll('.lists-drag-row.drag-over').forEach(function(el) { el.classList.remove('drag-over'); });
if (dragRow) {
var allIds = [];
container.querySelectorAll('.lists-drag-row').forEach(function(r) { allIds.push(r.dataset.id); });
document.getElementById('lists-reorder-ids').value = allIds.join(',');
document.getElementById('lists-reorder-form').submit();
}
dragRow = null;
});
row.addEventListener('dragover', function(e) {
e.preventDefault();
if (!dragRow || row === dragRow) return;
e.dataTransfer.dropEffect = 'move';
container.querySelectorAll('.lists-drag-row.drag-over').forEach(function(el) { el.classList.remove('drag-over'); });
row.classList.add('drag-over');
});
row.addEventListener('dragleave', function() { row.classList.remove('drag-over'); });
row.addEventListener('drop', function(e) {
e.preventDefault();
if (!dragRow || row === dragRow) return;
row.classList.remove('drag-over');
var rows = Array.from(container.querySelectorAll('.lists-drag-row'));
var dragIdx = rows.indexOf(dragRow);
var targetIdx = rows.indexOf(row);
if (dragIdx < targetIdx) {
container.insertBefore(dragRow, row.nextSibling);
} else {
container.insertBefore(dragRow, row);
}
});
});
}
var domainSel = document.getElementById('domain-filter');
var projectSel = document.getElementById('project-filter');
var currentProjectId = '{{ current_project_id }}';