@qnote/q-ai-note 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/app.js +56 -12
- package/dist/web/chatView.js +5 -1
- package/dist/web/styles.css +37 -8
- package/dist/web/vueRenderers.js +102 -11
- package/package.json +1 -1
package/dist/web/app.js
CHANGED
|
@@ -487,16 +487,50 @@ function renderWorkTree() {
|
|
|
487
487
|
});
|
|
488
488
|
await loadSandbox(state.currentSandbox.id);
|
|
489
489
|
},
|
|
490
|
-
onReorderLanes: treeReadonly ? undefined : async (dragRootId, targetRootId) => {
|
|
490
|
+
onReorderLanes: treeReadonly ? undefined : async (dragRootId, targetRootId, position = 'before') => {
|
|
491
491
|
if (!state.currentSandbox) return;
|
|
492
|
-
if (!dragRootId
|
|
492
|
+
if (!dragRootId) return;
|
|
493
|
+
if (targetRootId && dragRootId === targetRootId) return;
|
|
493
494
|
const roots = (state.currentSandbox.items || []).filter((item) => !item.parent_id);
|
|
494
495
|
const ordered = [...roots].sort((a, b) => compareSiblingOrder(a, b, 'lane_order_key'));
|
|
496
|
+
const missingLaneKeyRoots = ordered.filter((item) => !getNodeOrderKey(item, 'lane_order_key'));
|
|
497
|
+
if (missingLaneKeyRoots.length > 0) {
|
|
498
|
+
let leftKey = '';
|
|
499
|
+
for (const root of ordered) {
|
|
500
|
+
const currentKey = getNodeOrderKey(root, 'lane_order_key');
|
|
501
|
+
if (currentKey) {
|
|
502
|
+
leftKey = currentKey;
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const generatedKey = rankBetween(leftKey, '');
|
|
506
|
+
await apiRequest(`${API_BASE}/items/${root.id}`, {
|
|
507
|
+
method: 'PUT',
|
|
508
|
+
body: JSON.stringify({
|
|
509
|
+
extra_data: {
|
|
510
|
+
...(root.extra_data || {}),
|
|
511
|
+
lane_order_key: generatedKey,
|
|
512
|
+
},
|
|
513
|
+
}),
|
|
514
|
+
});
|
|
515
|
+
root.extra_data = {
|
|
516
|
+
...(root.extra_data || {}),
|
|
517
|
+
lane_order_key: generatedKey,
|
|
518
|
+
};
|
|
519
|
+
leftKey = generatedKey;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
495
522
|
const fromIdx = ordered.findIndex((item) => item.id === dragRootId);
|
|
496
|
-
|
|
497
|
-
if (fromIdx < 0 || toIdx < 0) return;
|
|
523
|
+
if (fromIdx < 0) return;
|
|
498
524
|
const [moved] = ordered.splice(fromIdx, 1);
|
|
499
|
-
ordered.
|
|
525
|
+
let insertIndex = ordered.length;
|
|
526
|
+
if (targetRootId) {
|
|
527
|
+
const targetIdx = ordered.findIndex((item) => item.id === targetRootId);
|
|
528
|
+
if (targetIdx < 0) return;
|
|
529
|
+
insertIndex = position === 'after' ? targetIdx + 1 : targetIdx;
|
|
530
|
+
} else if (position !== 'end') {
|
|
531
|
+
insertIndex = ordered.length;
|
|
532
|
+
}
|
|
533
|
+
ordered.splice(insertIndex, 0, moved);
|
|
500
534
|
const movedIndex = ordered.findIndex((item) => item.id === dragRootId);
|
|
501
535
|
const left = ordered[movedIndex - 1] || null;
|
|
502
536
|
const right = ordered[movedIndex + 1] || null;
|
|
@@ -623,7 +657,7 @@ function getNodeOrderKey(item, keyName = 'order_key') {
|
|
|
623
657
|
function compareSiblingOrder(a, b, keyName = 'order_key') {
|
|
624
658
|
const keyA = getNodeOrderKey(a, keyName);
|
|
625
659
|
const keyB = getNodeOrderKey(b, keyName);
|
|
626
|
-
if (keyA && keyB && keyA !== keyB) return keyA
|
|
660
|
+
if (keyA && keyB && keyA !== keyB) return keyA < keyB ? -1 : 1;
|
|
627
661
|
if (keyA && !keyB) return -1;
|
|
628
662
|
if (!keyA && keyB) return 1;
|
|
629
663
|
const numericA = Number(a?.extra_data?.lane_order);
|
|
@@ -633,7 +667,10 @@ function compareSiblingOrder(a, b, keyName = 'order_key') {
|
|
|
633
667
|
if (keyName === 'lane_order_key' && validA && validB && numericA !== numericB) return numericA - numericB;
|
|
634
668
|
if (keyName === 'lane_order_key' && validA && !validB) return -1;
|
|
635
669
|
if (keyName === 'lane_order_key' && !validA && validB) return 1;
|
|
636
|
-
|
|
670
|
+
const createdA = String(a?.created_at || '');
|
|
671
|
+
const createdB = String(b?.created_at || '');
|
|
672
|
+
if (createdA === createdB) return 0;
|
|
673
|
+
return createdA < createdB ? -1 : 1;
|
|
637
674
|
}
|
|
638
675
|
|
|
639
676
|
function populateParentSelect(items, preferredParentId = null) {
|
|
@@ -1468,7 +1505,14 @@ async function loadSandboxChats(sandboxId) {
|
|
|
1468
1505
|
const chats = await apiRequest(`${API_BASE}/chats/sandbox/${sandboxId}`);
|
|
1469
1506
|
state.chats = chats;
|
|
1470
1507
|
|
|
1471
|
-
mountHtmlList(
|
|
1508
|
+
mountHtmlList(
|
|
1509
|
+
'sandbox-chat-messages',
|
|
1510
|
+
chats.map((chat) => renderChatEntry(chat, {
|
|
1511
|
+
safeText,
|
|
1512
|
+
renderAIActionMessage,
|
|
1513
|
+
renderContent: (content) => renderMarkdownSnippet(content),
|
|
1514
|
+
})),
|
|
1515
|
+
);
|
|
1472
1516
|
|
|
1473
1517
|
messages.scrollTop = messages.scrollHeight;
|
|
1474
1518
|
}
|
|
@@ -1500,7 +1544,7 @@ function renderAIActionMessage(action) {
|
|
|
1500
1544
|
};
|
|
1501
1545
|
|
|
1502
1546
|
if (actionType === 'response' || actionType === 'clarify') {
|
|
1503
|
-
return `<div class="chat-message assistant">${
|
|
1547
|
+
return `<div class="chat-message assistant">${renderMarkdownSnippet(action.response || action.observation || '')}</div>`;
|
|
1504
1548
|
}
|
|
1505
1549
|
else if (actionType === 'confirm' && action.confirm_items) {
|
|
1506
1550
|
// Skip confirm, go directly to done
|
|
@@ -1527,7 +1571,7 @@ function renderAIActionMessage(action) {
|
|
|
1527
1571
|
</div>`;
|
|
1528
1572
|
}
|
|
1529
1573
|
|
|
1530
|
-
return `<div class="chat-message assistant">${
|
|
1574
|
+
return `<div class="chat-message assistant">${renderMarkdownSnippet(action.response || '')}</div>`;
|
|
1531
1575
|
}
|
|
1532
1576
|
|
|
1533
1577
|
window.undoOperation = async function(operationId, btn) {
|
|
@@ -2531,7 +2575,7 @@ async function initApp() {
|
|
|
2531
2575
|
const actionType = action.action;
|
|
2532
2576
|
|
|
2533
2577
|
if (actionType === 'response' || actionType === 'clarify') {
|
|
2534
|
-
messages.insertAdjacentHTML('beforeend', `<div class="chat-message assistant">${
|
|
2578
|
+
messages.insertAdjacentHTML('beforeend', `<div class="chat-message assistant">${renderMarkdownSnippet(action.response || action.observation || '')}</div>`);
|
|
2535
2579
|
messages.scrollTop = messages.scrollHeight;
|
|
2536
2580
|
|
|
2537
2581
|
if (actionType === 'clarify') {
|
|
@@ -2623,7 +2667,7 @@ async function initApp() {
|
|
|
2623
2667
|
state.pendingAction = null;
|
|
2624
2668
|
}
|
|
2625
2669
|
else if (actionType === 'stop') {
|
|
2626
|
-
messages.insertAdjacentHTML('beforeend', `<div class="chat-message assistant">${
|
|
2670
|
+
messages.insertAdjacentHTML('beforeend', `<div class="chat-message assistant">${renderMarkdownSnippet(action.observation || '已取消操作')}</div>`);
|
|
2627
2671
|
messages.scrollTop = messages.scrollHeight;
|
|
2628
2672
|
state.pendingAction = null;
|
|
2629
2673
|
}
|
package/dist/web/chatView.js
CHANGED
|
@@ -14,7 +14,7 @@ export function tryParseAssistantAction(content) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function renderChatEntry(chat, helpers) {
|
|
17
|
-
const { safeText, renderAIActionMessage } = helpers;
|
|
17
|
+
const { safeText, renderAIActionMessage, renderContent } = helpers;
|
|
18
18
|
|
|
19
19
|
if (!('role' in chat)) {
|
|
20
20
|
return `<div class="chat-message diary">[日记] ${safeText(chat.content)}</div>`;
|
|
@@ -25,6 +25,10 @@ export function renderChatEntry(chat, helpers) {
|
|
|
25
25
|
if (parsedAction) {
|
|
26
26
|
return renderAIActionMessage(parsedAction);
|
|
27
27
|
}
|
|
28
|
+
const contentHtml = typeof renderContent === 'function'
|
|
29
|
+
? renderContent(chat.content)
|
|
30
|
+
: safeText(chat.content);
|
|
31
|
+
return `<div class="chat-message assistant">${contentHtml}</div>`;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
return `<div class="chat-message ${chat.role}">${safeText(chat.content)}</div>`;
|
package/dist/web/styles.css
CHANGED
|
@@ -647,6 +647,30 @@ h2 {
|
|
|
647
647
|
flex-wrap: nowrap;
|
|
648
648
|
}
|
|
649
649
|
|
|
650
|
+
.dense-lane-drop-slot {
|
|
651
|
+
width: 14px;
|
|
652
|
+
min-width: 14px;
|
|
653
|
+
align-self: stretch;
|
|
654
|
+
border-radius: 6px;
|
|
655
|
+
min-height: 180px;
|
|
656
|
+
transition: background-color 0.15s ease, box-shadow 0.15s ease;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
.dense-lane-drop-slot.end {
|
|
660
|
+
width: 24px;
|
|
661
|
+
min-width: 24px;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
.dense-lane-drop-slot.lane-slot-drag-over {
|
|
665
|
+
background: rgba(59, 130, 246, 0.28);
|
|
666
|
+
box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.45);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
.dense-lane-board.is-lane-dragging-active .dense-lane-drop-slot {
|
|
670
|
+
background: rgba(148, 163, 184, 0.14);
|
|
671
|
+
box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.22);
|
|
672
|
+
}
|
|
673
|
+
|
|
650
674
|
.dense-lane {
|
|
651
675
|
min-width: var(--lane-width, 220px);
|
|
652
676
|
width: var(--lane-width, 220px);
|
|
@@ -746,21 +770,26 @@ h2 {
|
|
|
746
770
|
}
|
|
747
771
|
|
|
748
772
|
.lane-tree-title-line {
|
|
749
|
-
display:
|
|
773
|
+
display: flex;
|
|
774
|
+
flex-wrap: wrap;
|
|
750
775
|
align-items: center;
|
|
751
776
|
gap: 4px;
|
|
752
777
|
min-width: 0;
|
|
753
778
|
}
|
|
754
779
|
|
|
755
|
-
.lane-tree-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
gap: 4px;
|
|
759
|
-
min-height: 14px;
|
|
780
|
+
.lane-tree-title-line .dense-node-name {
|
|
781
|
+
flex: 1 1 auto;
|
|
782
|
+
min-width: 96px;
|
|
760
783
|
}
|
|
761
784
|
|
|
762
|
-
.lane-tree-
|
|
763
|
-
|
|
785
|
+
.lane-tree-title-line .node-entity-mini-badges,
|
|
786
|
+
.lane-tree-title-line .node-meta {
|
|
787
|
+
flex: 0 0 auto;
|
|
788
|
+
max-width: 100%;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.lane-tree-title-line .node-meta {
|
|
792
|
+
white-space: nowrap;
|
|
764
793
|
}
|
|
765
794
|
|
|
766
795
|
.lane-tree-node {
|
package/dist/web/vueRenderers.js
CHANGED
|
@@ -318,7 +318,6 @@ function renderDenseLaneNode(node, byParent, expandedIdSet, entitySummaryByNodeI
|
|
|
318
318
|
const hasChildren = children.length > 0;
|
|
319
319
|
const isExpanded = expandedIdSet.has(node.id);
|
|
320
320
|
const nodeSummary = entitySummaryByNodeId?.[node.id] || { issue: 0, knowledge: 0, capability: 0 };
|
|
321
|
-
const useStackSummary = depth >= 3;
|
|
322
321
|
const summaryBadgeHtml = renderEntityBadges(nodeSummary);
|
|
323
322
|
const summaryAssigneeHtml = showAssignee && node.assignee ? `<span class="node-meta">@${esc(node.assignee)}</span>` : '';
|
|
324
323
|
const previewHtml = renderEntityPreviewBoxes(node.id, entityRowsByNodeId, elementPreviewMode);
|
|
@@ -342,18 +341,12 @@ function renderDenseLaneNode(node, byParent, expandedIdSet, entitySummaryByNodeI
|
|
|
342
341
|
</button>
|
|
343
342
|
` : ''}
|
|
344
343
|
<span class="node-status ${esc(node.status)}"></span>
|
|
345
|
-
<div class="lane-tree-node-main
|
|
344
|
+
<div class="lane-tree-node-main">
|
|
346
345
|
<div class="lane-tree-title-line">
|
|
347
346
|
<span class="dense-node-name">${esc(node.name)}</span>
|
|
348
|
-
${
|
|
349
|
-
${
|
|
347
|
+
${summaryBadgeHtml}
|
|
348
|
+
${summaryAssigneeHtml}
|
|
350
349
|
</div>
|
|
351
|
-
${useStackSummary && (summaryBadgeHtml || summaryAssigneeHtml) ? `
|
|
352
|
-
<div class="lane-tree-summary-line">
|
|
353
|
-
${summaryBadgeHtml}
|
|
354
|
-
${summaryAssigneeHtml}
|
|
355
|
-
</div>
|
|
356
|
-
` : ''}
|
|
357
350
|
</div>
|
|
358
351
|
${readonly ? '' : `
|
|
359
352
|
<div class="node-actions">
|
|
@@ -411,6 +404,7 @@ function renderDenseTree(roots, byParent, expandedIdSet, entitySummaryByNodeId,
|
|
|
411
404
|
const laneWidth = getDenseLaneWidthPx(root, byParent, showAssignee);
|
|
412
405
|
const laneNameMax = Math.max(120, laneWidth - 86);
|
|
413
406
|
return `
|
|
407
|
+
<div class="dense-lane-drop-slot" data-lane-slot-root-id="${esc(root.id)}" data-lane-slot-position="before" title="拖拽到此处:插入到当前泳道之前"></div>
|
|
414
408
|
<section class="dense-lane" data-root-id="${esc(root.id)}" style="--lane-width:${laneWidth}px;--lane-name-max:${laneNameMax}px;">
|
|
415
409
|
${readonly ? '' : `<div class="dense-lane-drag-handle" data-lane-drag-id="${esc(root.id)}" draggable="true" title="拖拽调整泳道顺序">⋮⋮</div>`}
|
|
416
410
|
<div class="dense-lane-body">
|
|
@@ -419,6 +413,7 @@ function renderDenseTree(roots, byParent, expandedIdSet, entitySummaryByNodeId,
|
|
|
419
413
|
</section>
|
|
420
414
|
`;
|
|
421
415
|
}).join('')}
|
|
416
|
+
<div class="dense-lane-drop-slot end" data-lane-slot-end="1" title="拖拽到此处:移动到最后"></div>
|
|
422
417
|
</div>
|
|
423
418
|
`;
|
|
424
419
|
}
|
|
@@ -608,12 +603,16 @@ export function mountWorkTree(targetId, options) {
|
|
|
608
603
|
});
|
|
609
604
|
|
|
610
605
|
const laneEls = Array.from(container.querySelectorAll('.dense-lane[data-root-id]'));
|
|
606
|
+
const laneSlotEls = Array.from(container.querySelectorAll('.dense-lane-drop-slot[data-lane-slot-root-id]'));
|
|
607
|
+
const laneEndSlotEl = container.querySelector('.dense-lane-drop-slot[data-lane-slot-end="1"]');
|
|
608
|
+
const laneDropPositionByRootId = new Map();
|
|
611
609
|
const laneHandleEls = Array.from(container.querySelectorAll('.dense-lane-drag-handle[data-lane-drag-id]'));
|
|
612
610
|
laneHandleEls.forEach((handle) => {
|
|
613
611
|
const rootId = handle.getAttribute('data-lane-drag-id') || '';
|
|
614
612
|
handle.addEventListener('dragstart', (event) => {
|
|
615
613
|
draggingLaneId = rootId;
|
|
616
614
|
draggingNodeId = '';
|
|
615
|
+
board?.classList.add('is-lane-dragging-active');
|
|
617
616
|
const lane = handle.closest('.dense-lane');
|
|
618
617
|
lane?.classList.add('is-lane-dragging');
|
|
619
618
|
event.dataTransfer?.setData('text/plain', rootId);
|
|
@@ -622,6 +621,14 @@ export function mountWorkTree(targetId, options) {
|
|
|
622
621
|
handle.addEventListener('dragend', () => {
|
|
623
622
|
const lane = handle.closest('.dense-lane');
|
|
624
623
|
lane?.classList.remove('is-lane-dragging');
|
|
624
|
+
board?.classList.remove('is-lane-dragging-active');
|
|
625
|
+
laneEls.forEach((laneEl) => {
|
|
626
|
+
laneEl.classList.remove('lane-drag-over-target');
|
|
627
|
+
laneEl.removeAttribute('data-lane-drop-position');
|
|
628
|
+
});
|
|
629
|
+
laneSlotEls.forEach((slotEl) => slotEl.classList.remove('lane-slot-drag-over'));
|
|
630
|
+
laneEndSlotEl?.classList.remove('lane-slot-drag-over');
|
|
631
|
+
laneDropPositionByRootId.clear();
|
|
625
632
|
draggingLaneId = '';
|
|
626
633
|
});
|
|
627
634
|
});
|
|
@@ -630,17 +637,101 @@ export function mountWorkTree(targetId, options) {
|
|
|
630
637
|
el.addEventListener('dragover', (event) => {
|
|
631
638
|
if (!draggingLaneId || draggingLaneId === rootId) return;
|
|
632
639
|
event.preventDefault();
|
|
640
|
+
const rect = el.getBoundingClientRect();
|
|
641
|
+
const offsetX = event.clientX - rect.left;
|
|
642
|
+
const ratio = rect.width > 0 ? offsetX / rect.width : 0.5;
|
|
643
|
+
const laneDropPosition = ratio >= 0.5 ? 'after' : 'before';
|
|
644
|
+
laneDropPositionByRootId.set(rootId, laneDropPosition);
|
|
645
|
+
el.setAttribute('data-lane-drop-position', laneDropPosition);
|
|
633
646
|
el.classList.add('lane-drag-over-target');
|
|
634
647
|
});
|
|
635
648
|
el.addEventListener('dragleave', () => {
|
|
636
649
|
el.classList.remove('lane-drag-over-target');
|
|
650
|
+
el.removeAttribute('data-lane-drop-position');
|
|
651
|
+
laneDropPositionByRootId.delete(rootId);
|
|
637
652
|
});
|
|
638
653
|
el.addEventListener('drop', (event) => {
|
|
639
654
|
event.preventDefault();
|
|
640
655
|
el.classList.remove('lane-drag-over-target');
|
|
656
|
+
let laneDropPosition = laneDropPositionByRootId.get(rootId);
|
|
657
|
+
if (!laneDropPosition) {
|
|
658
|
+
const rect = el.getBoundingClientRect();
|
|
659
|
+
const offsetX = event.clientX - rect.left;
|
|
660
|
+
const ratio = rect.width > 0 ? offsetX / rect.width : 0.5;
|
|
661
|
+
laneDropPosition = ratio >= 0.5 ? 'after' : 'before';
|
|
662
|
+
}
|
|
663
|
+
el.removeAttribute('data-lane-drop-position');
|
|
664
|
+
laneDropPositionByRootId.delete(rootId);
|
|
641
665
|
if (!draggingLaneId || draggingLaneId === rootId) return;
|
|
642
|
-
|
|
666
|
+
if (laneDropPosition === 'before') {
|
|
667
|
+
event.stopPropagation();
|
|
668
|
+
onReorderLanes?.(draggingLaneId, rootId, 'before');
|
|
669
|
+
board?.classList.remove('is-lane-dragging-active');
|
|
670
|
+
draggingLaneId = '';
|
|
671
|
+
} else {
|
|
672
|
+
const orderedRootIds = laneEls
|
|
673
|
+
.map((laneEl) => laneEl.getAttribute('data-root-id') || '')
|
|
674
|
+
.filter((id) => id && id !== draggingLaneId);
|
|
675
|
+
const isLastTarget = orderedRootIds.length > 0 && orderedRootIds[orderedRootIds.length - 1] === rootId;
|
|
676
|
+
if (!isLastTarget) {
|
|
677
|
+
event.stopPropagation();
|
|
678
|
+
onReorderLanes?.(draggingLaneId, rootId, 'after');
|
|
679
|
+
board?.classList.remove('is-lane-dragging-active');
|
|
680
|
+
draggingLaneId = '';
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
laneSlotEls.forEach((slotEl) => {
|
|
686
|
+
const targetRootId = slotEl.getAttribute('data-lane-slot-root-id') || '';
|
|
687
|
+
slotEl.addEventListener('dragover', (event) => {
|
|
688
|
+
if (!draggingLaneId || draggingLaneId === targetRootId) return;
|
|
689
|
+
event.preventDefault();
|
|
690
|
+
slotEl.classList.add('lane-slot-drag-over');
|
|
691
|
+
});
|
|
692
|
+
slotEl.addEventListener('dragleave', () => {
|
|
693
|
+
slotEl.classList.remove('lane-slot-drag-over');
|
|
694
|
+
});
|
|
695
|
+
slotEl.addEventListener('drop', (event) => {
|
|
696
|
+
event.preventDefault();
|
|
697
|
+
event.stopPropagation();
|
|
698
|
+
slotEl.classList.remove('lane-slot-drag-over');
|
|
699
|
+
if (!draggingLaneId || draggingLaneId === targetRootId) return;
|
|
700
|
+
onReorderLanes?.(draggingLaneId, targetRootId, 'before');
|
|
701
|
+
board?.classList.remove('is-lane-dragging-active');
|
|
643
702
|
draggingLaneId = '';
|
|
644
703
|
});
|
|
645
704
|
});
|
|
705
|
+
laneEndSlotEl?.addEventListener('dragover', (event) => {
|
|
706
|
+
if (!draggingLaneId) return;
|
|
707
|
+
event.preventDefault();
|
|
708
|
+
laneEndSlotEl.classList.add('lane-slot-drag-over');
|
|
709
|
+
});
|
|
710
|
+
laneEndSlotEl?.addEventListener('dragleave', () => {
|
|
711
|
+
laneEndSlotEl.classList.remove('lane-slot-drag-over');
|
|
712
|
+
});
|
|
713
|
+
laneEndSlotEl?.addEventListener('drop', (event) => {
|
|
714
|
+
if (!draggingLaneId) return;
|
|
715
|
+
event.preventDefault();
|
|
716
|
+
event.stopPropagation();
|
|
717
|
+
laneEndSlotEl.classList.remove('lane-slot-drag-over');
|
|
718
|
+
onReorderLanes?.(draggingLaneId, '', 'end');
|
|
719
|
+
board?.classList.remove('is-lane-dragging-active');
|
|
720
|
+
draggingLaneId = '';
|
|
721
|
+
});
|
|
722
|
+
board?.addEventListener('dragover', (event) => {
|
|
723
|
+
if (!draggingLaneId) return;
|
|
724
|
+
event.preventDefault();
|
|
725
|
+
});
|
|
726
|
+
board?.addEventListener('drop', (event) => {
|
|
727
|
+
if (!draggingLaneId) return;
|
|
728
|
+
event.preventDefault();
|
|
729
|
+
laneEls.forEach((laneEl) => {
|
|
730
|
+
laneEl.classList.remove('lane-drag-over-target');
|
|
731
|
+
laneEl.removeAttribute('data-lane-drop-position');
|
|
732
|
+
});
|
|
733
|
+
laneDropPositionByRootId.clear();
|
|
734
|
+
onReorderLanes?.(draggingLaneId, '', 'end');
|
|
735
|
+
draggingLaneId = '';
|
|
736
|
+
});
|
|
646
737
|
}
|