Adding drag and drop on table
This commit is contained in:
parent
9ba35440e8
commit
13b8e40f98
3 changed files with 55 additions and 3 deletions
|
@ -29,7 +29,7 @@ type Props = {
|
||||||
|
|
||||||
const KanbanCard = React.memo((props: Props) => {
|
const KanbanCard = React.memo((props: Props) => {
|
||||||
const cardRef = useRef<HTMLDivElement>(null)
|
const cardRef = useRef<HTMLDivElement>(null)
|
||||||
const {card, intl, isSelected} = props
|
const {card, intl} = props
|
||||||
const [{isDragging}, drag] = useDrag(() => ({
|
const [{isDragging}, drag] = useDrag(() => ({
|
||||||
type: 'card',
|
type: 'card',
|
||||||
item: card,
|
item: card,
|
||||||
|
|
|
@ -54,6 +54,29 @@ const Table = (props: Props) => {
|
||||||
},
|
},
|
||||||
}), [changed])
|
}), [changed])
|
||||||
|
|
||||||
|
const onDropToCard = (srcCard: Card, dstCard: Card) => {
|
||||||
|
Utils.log(`onDropToCard: ${dstCard.title}`)
|
||||||
|
const {activeView} = boardTree
|
||||||
|
const {selectedCardIds} = props
|
||||||
|
|
||||||
|
const draggedCardIds = Array.from(new Set(selectedCardIds).add(srcCard.id))
|
||||||
|
const description = draggedCardIds.length > 1 ? `drag ${draggedCardIds.length} cards` : 'drag card'
|
||||||
|
|
||||||
|
// Update dstCard order
|
||||||
|
let cardOrder = Array.from(new Set([...activeView.cardOrder, ...boardTree.cards.map((o) => o.id)]))
|
||||||
|
const isDraggingDown = cardOrder.indexOf(srcCard.id) <= cardOrder.indexOf(dstCard.id)
|
||||||
|
cardOrder = cardOrder.filter((id) => !draggedCardIds.includes(id))
|
||||||
|
let destIndex = cardOrder.indexOf(dstCard.id)
|
||||||
|
if (isDraggingDown) {
|
||||||
|
destIndex += 1
|
||||||
|
}
|
||||||
|
cardOrder.splice(destIndex, 0, ...draggedCardIds)
|
||||||
|
|
||||||
|
mutator.performAsUndoGroup(async () => {
|
||||||
|
await mutator.changeViewCardOrder(activeView, cardOrder, description)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const onDropToColumn = async (template: IPropertyTemplate, container: IPropertyTemplate) => {
|
const onDropToColumn = async (template: IPropertyTemplate, container: IPropertyTemplate) => {
|
||||||
Utils.log(`ondrop. Source column: ${template.name}, dest column: ${container.name}`)
|
Utils.log(`ondrop. Source column: ${template.name}, dest column: ${container.name}`)
|
||||||
|
|
||||||
|
@ -139,6 +162,7 @@ const Table = (props: Props) => {
|
||||||
}}
|
}}
|
||||||
showCard={props.showCard}
|
showCard={props.showCard}
|
||||||
readonly={props.readonly}
|
readonly={props.readonly}
|
||||||
|
onDrop={onDropToCard}
|
||||||
/>)
|
/>)
|
||||||
|
|
||||||
return tableRow
|
return tableRow
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
import React, {useState, useRef, useEffect} from 'react'
|
import React, {useState, useRef, useEffect} from 'react'
|
||||||
import {FormattedMessage} from 'react-intl'
|
import {FormattedMessage} from 'react-intl'
|
||||||
|
import {useDrop, useDrag} from 'react-dnd'
|
||||||
|
|
||||||
import {Card} from '../../blocks/card'
|
import {Card} from '../../blocks/card'
|
||||||
import {Constants} from '../../constants'
|
import {Constants} from '../../constants'
|
||||||
|
@ -22,11 +23,31 @@ type Props = {
|
||||||
showCard: (cardId: string) => void
|
showCard: (cardId: string) => void
|
||||||
readonly: boolean
|
readonly: boolean
|
||||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
|
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
|
||||||
|
onDrop: (srcCard: Card, dstCard: Card) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const TableRow = React.memo((props: Props) => {
|
const TableRow = React.memo((props: Props) => {
|
||||||
const titleRef = useRef<Editable>(null)
|
const titleRef = useRef<Editable>(null)
|
||||||
const [title, setTitle] = useState(props.card.title)
|
const [title, setTitle] = useState(props.card.title)
|
||||||
|
const cardRef = useRef<HTMLDivElement>(null)
|
||||||
|
const {card} = props
|
||||||
|
const [{isDragging}, drag] = useDrag(() => ({
|
||||||
|
type: 'card',
|
||||||
|
item: card,
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isDragging: monitor.isDragging(),
|
||||||
|
}),
|
||||||
|
}), [card])
|
||||||
|
|
||||||
|
const [{isOver}, drop] = useDrop(() => ({
|
||||||
|
accept: 'card',
|
||||||
|
collect: (monitor) => ({
|
||||||
|
isOver: monitor.isOver(),
|
||||||
|
}),
|
||||||
|
drop: (item: Card) => {
|
||||||
|
props.onDrop(item, card)
|
||||||
|
},
|
||||||
|
}), [card, props.onDrop])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.focusOnMount) {
|
if (props.focusOnMount) {
|
||||||
|
@ -38,15 +59,22 @@ const TableRow = React.memo((props: Props) => {
|
||||||
return Math.max(Constants.minColumnWidth, props.boardTree.activeView.columnWidths[templateId] || 0)
|
return Math.max(Constants.minColumnWidth, props.boardTree.activeView.columnWidths[templateId] || 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const {boardTree, card, onSaveWithEnter} = props
|
const {boardTree, onSaveWithEnter} = props
|
||||||
const {board, activeView} = boardTree
|
const {board, activeView} = boardTree
|
||||||
|
|
||||||
const className = props.isSelected ? 'TableRow octo-table-row selected' : 'TableRow octo-table-row'
|
let className = props.isSelected ? 'TableRow octo-table-row selected' : 'TableRow octo-table-row'
|
||||||
|
if (isOver) {
|
||||||
|
className += ' dragover'
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(drag(cardRef))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={className}
|
className={className}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
|
ref={cardRef}
|
||||||
|
style={{opacity: isDragging ? 0.5 : 1}}
|
||||||
>
|
>
|
||||||
|
|
||||||
{/* Name / title */}
|
{/* Name / title */}
|
||||||
|
|
Loading…
Reference in a new issue