From a9a55a2287df0bce5dfb9901eaeddb8779245636 Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Fri, 22 Nov 2024 06:43:49 +0500 Subject: [PATCH] Fix kanban drag-and-drop (#7219) --- packages/kanban/src/components/Kanban.svelte | 48 +++++++++++++++++-- .../kanban/src/components/KanbanRow.svelte | 24 +++++----- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/packages/kanban/src/components/Kanban.svelte b/packages/kanban/src/components/Kanban.svelte index ab641e6688..a787d8327c 100644 --- a/packages/kanban/src/components/Kanban.svelte +++ b/packages/kanban/src/components/Kanban.svelte @@ -82,12 +82,13 @@ return } - if (!dontUpdateRank && dragCardInitialRank !== dragCard.rank) { + if (!dontUpdateRank && dragCardInitialRank !== dragCard.rank && dragCardInitialRank !== undefined) { const dragCardRank = dragCard.rank updates = { ...updates, rank: dragCardRank } + dragCard.rank = dragCardInitialRank } if (Object.keys(updates).length > 0) { await client.diffUpdate(dragCard, updates) @@ -175,6 +176,15 @@ return false } + interface DragCardOverPos { + dragCardId: Ref + dragCardPos: number + overCardId: Ref + overCardPos: number + } + + let cardOverPos: DragCardOverPos | undefined + function cardDragOver (evt: CardDragEvent, object: Item, state: CategoryType): void { if (dragCard !== undefined && !dontUpdateRank) { const updates = getUpdateProps(dragCard, state) @@ -183,9 +193,29 @@ } if (object._id !== dragCard._id) { let arr = getGroupByValues(groupByDocs, state) ?? [] - const dragCardIndex = arr.findIndex((p) => p._id === dragCard?._id) - const targetIndex = arr.findIndex((p) => p._id === object._id) + let dragCardIndex = -1 + let targetIndex = -1 if ( + cardOverPos !== undefined && + cardOverPos.overCardId === object._id && + cardOverPos.dragCardId === dragCard._id + ) { + dragCardIndex = cardOverPos.dragCardPos + targetIndex = cardOverPos.overCardPos + } else { + dragCardIndex = arr.findIndex((p) => p._id === dragCard?._id) + targetIndex = arr.findIndex((p) => p._id === object._id) + cardOverPos = { + dragCardId: dragCard._id, + dragCardPos: dragCardIndex, + overCardId: object._id, + overCardPos: targetIndex + } + } + + if ( + dragCardIndex !== -1 && + targetIndex !== -1 && dragswap(evt, targetIndex, dragCardIndex) && arr[targetIndex] !== undefined && arr[dragCardIndex] !== undefined @@ -194,20 +224,28 @@ arr = [...arr.slice(0, targetIndex), dragCard, ...arr.slice(targetIndex)] setGroupByValues(groupByDocs, state, arr) groupByDocs = groupByDocs + cardOverPos = undefined } } } } - function cardDrop (evt: CardDragEvent, object: Item, state: CategoryType): void { + + async function cardDrop (evt: CardDragEvent, object: Item, state: CategoryType): Promise { if (!dontUpdateRank && dragCard !== undefined) { const arr = getGroupByValues(groupByDocs, state) ?? [] const s = arr.findIndex((p) => p._id === dragCard?._id) if (s !== -1) { dragCard.rank = makeRank(arr[s - 1]?.rank, arr[s + 1]?.rank) + const updates = getUpdateProps(dragCard, state) + + if (updates === undefined) { + await client.update(dragCard, { rank: dragCard.rank }) + } } } isDragging = false } + async function onDragStart (object: Item, state: CategoryType): Promise { dragCardInitialState = state dragCardState = state @@ -383,7 +421,7 @@ cardDragOver(evt, obj, state) }} cardDrop={(evt, obj) => { - cardDrop(evt, obj, state) + void cardDrop(evt, obj, state) }} {onDragStart} {showMenu} diff --git a/packages/kanban/src/components/KanbanRow.svelte b/packages/kanban/src/components/KanbanRow.svelte index 40ca360441..c9a78b8cbb 100644 --- a/packages/kanban/src/components/KanbanRow.svelte +++ b/packages/kanban/src/components/KanbanRow.svelte @@ -84,21 +84,23 @@ : state } - $: void limiter.add(async () => { - docQuery.query( - _class, - groupQuery, - (res) => { - limitedObjects = toIdMap(res) - }, - { ...options, limit } - ) - }) + $: docQuery.query( + _class, + groupQuery, + (res) => { + limitedObjects = toIdMap(res) + }, + { ...options, limit } + ) + + function getObject (_id: Ref, limitedObjects: IdMap): DocWithRank | undefined { + return limitedObjects.get(_id) ?? (_id === dragCard?._id ? dragCard : undefined) + } {#each stateObjects as objectRef, i (objectRef._id)} {@const dragged = isDragging && objectRef._id === dragCard?._id} - {@const object = limitedObjects.get(objectRef._id) ?? (objectRef._id === dragCard?._id ? dragCard : undefined)} + {@const object = getObject(objectRef._id, limitedObjects)} {#if object !== undefined}