diff --git a/webapp/src/components/table/table.tsx b/webapp/src/components/table/table.tsx index 25d5f38c2..335aef447 100644 --- a/webapp/src/components/table/table.tsx +++ b/webapp/src/components/table/table.tsx @@ -188,27 +188,27 @@ const Table = (props: Props): JSX.Element => { {/* Table rows */}
{activeView.fields.groupById && - visibleGroups.map((group) => { - return ( - ) - }) + visibleGroups.map((group) => { + return ( + ) + }) } {/* No Grouping, Rows, one per card */} @@ -224,6 +224,7 @@ const Table = (props: Props): JSX.Element => { addCard={props.addCard} onCardClicked={props.onCardClicked} onDrop={onDropToCard} + useVirtualizedList={true} /> }
diff --git a/webapp/src/components/table/tableGroup.tsx b/webapp/src/components/table/tableGroup.tsx index 1da01a442..2635b438a 100644 --- a/webapp/src/components/table/tableGroup.tsx +++ b/webapp/src/components/table/tableGroup.tsx @@ -32,31 +32,9 @@ type Props = { const TableGroup = (props: Props): JSX.Element => { const {board, activeView, group, onDropToGroup, groupByProperty} = props - const groupId = group.option.id - - const [{isOver}, drop] = useDrop(() => ({ - accept: 'card', - collect: (monitor) => ({ - isOver: monitor.isOver(), - }), - drop: (item: Card, monitor) => { - if (monitor.isOver({shallow: true})) { - onDropToGroup(item, groupId, '') - } - }, - }), [onDropToGroup, groupId]) - - let className = 'octo-table-group' - if (isOver) { - className += ' dragover' - } return ( -
+ <> { readonly={props.readonly} propertyNameChanged={props.propertyNameChanged} onDrop={props.onDropToGroupHeader} + key={group.option.id} + onDropToGroup={onDropToGroup} /> {(group.cards.length > 0) && @@ -81,8 +61,10 @@ const TableGroup = (props: Props): JSX.Element => { addCard={props.addCard} onCardClicked={props.onCardClicked} onDrop={props.onDropToCard} + useVirtualizedList={false} />} -
+ + ) } diff --git a/webapp/src/components/table/tableGroupHeaderRow.test.tsx b/webapp/src/components/table/tableGroupHeaderRow.test.tsx index 94330a20d..4ad2de563 100644 --- a/webapp/src/components/table/tableGroupHeaderRow.test.tsx +++ b/webapp/src/components/table/tableGroupHeaderRow.test.tsx @@ -71,6 +71,7 @@ test('should match snapshot, no groups', async () => { type: 'text', options: [{id: 'property1', value: 'Property 1', color: ''}], }} + onDropToGroup={jest.fn()} /> , ) @@ -89,6 +90,7 @@ test('should match snapshot with Group', async () => { addCard={jest.fn()} propertyNameChanged={jest.fn()} onDrop={jest.fn()} + onDropToGroup={jest.fn()} /> , ) @@ -107,6 +109,7 @@ test('should match snapshot on read only', async () => { addCard={jest.fn()} propertyNameChanged={jest.fn()} onDrop={jest.fn()} + onDropToGroup={jest.fn()} /> , ) @@ -130,6 +133,7 @@ test('should match snapshot, hide group', async () => { addCard={jest.fn()} propertyNameChanged={jest.fn()} onDrop={jest.fn()} + onDropToGroup={jest.fn()} /> , ) @@ -158,6 +162,7 @@ test('should match snapshot, add new', async () => { addCard={addNew} propertyNameChanged={jest.fn()} onDrop={jest.fn()} + onDropToGroup={jest.fn()} /> , ) @@ -184,6 +189,7 @@ test('should match snapshot, edit title', async () => { addCard={jest.fn()} propertyNameChanged={jest.fn()} onDrop={jest.fn()} + onDropToGroup={jest.fn()} /> , ) diff --git a/webapp/src/components/table/tableGroupHeaderRow.tsx b/webapp/src/components/table/tableGroupHeaderRow.tsx index 7d46d87ab..2ea95b513 100644 --- a/webapp/src/components/table/tableGroupHeaderRow.tsx +++ b/webapp/src/components/table/tableGroupHeaderRow.tsx @@ -1,13 +1,14 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. /* eslint-disable max-lines */ -import React, {useState, useEffect} from 'react' +import React, {useState, useEffect, useRef} from 'react' import {FormattedMessage, useIntl} from 'react-intl' +import {useDrag, useDrop} from 'react-dnd' import {Constants} from '../../constants' import {IPropertyOption, Board, IPropertyTemplate, BoardGroup} from '../../blocks/board' import {BoardView} from '../../blocks/boardView' -import {useSortable} from '../../hooks/sortable' +import {Card} from '../../blocks/card' import mutator from '../../mutator' import Button from '../../widgets/buttons/button' import IconButton from '../../widgets/buttons/iconButton' @@ -33,13 +34,42 @@ type Props = { addCard: (groupByOptionId?: string) => Promise propertyNameChanged: (option: IPropertyOption, text: string) => Promise onDrop: (srcOption: IPropertyOption, dstOption?: IPropertyOption) => void + onDropToGroup: (srcCard: Card, groupID: string, dstCardID: string) => void } const TableGroupHeaderRow = (props: Props): JSX.Element => { const {board, activeView, group, groupByProperty} = props const [groupTitle, setGroupTitle] = useState(group.option.value) - const [isDragging, isOver, groupHeaderRef] = useSortable('groupHeader', group.option, !props.readonly, props.onDrop) + const ref = useRef(null) + const [{isDragging}, drag] = useDrag(() => ({ + type: 'groupHeader', + item: group.option, + collect: (monitor) => ({ + isDragging: monitor.isDragging(), + }), + canDrag: () => !props.readonly, + }), ['groupHeader', group.option, props.readonly]) + + const [{isOver}, drop] = useDrop(() => ({ + accept: ['groupHeader', 'card'], + collect: (monitor) => ({ + isOver: monitor.isOver(), + }), + drop: (dragItem: IPropertyOption | Card, monitor) => { + // @ts-ignore + if (dragItem?.type === 'card' && monitor.isOver({shallow: true})) { + // @ts-ignore + props.onDropToGroup(dragItem, group.option.id, '') + return; + } + // @ts-ignore + props.onDrop(dragItem, group.option) + }, + canDrop: () => !props.readonly, + }), [group.option, props.onDrop, props.readonly]) + drop(drag(ref)) + const intl = useIntl() const columnResize = useColumnResize() @@ -59,7 +89,7 @@ const TableGroupHeaderRow = (props: Props): JSX.Element => { return (
diff --git a/webapp/src/components/table/tableRows.test.tsx b/webapp/src/components/table/tableRows.test.tsx index 66ba68c9c..de2204798 100644 --- a/webapp/src/components/table/tableRows.test.tsx +++ b/webapp/src/components/table/tableRows.test.tsx @@ -74,6 +74,7 @@ describe('components/table/TableRows', () => { addCard={addCard} onCardClicked={jest.fn()} onDrop={jest.fn()} + useVirtualizedList={false} /> , diff --git a/webapp/src/components/table/tableRows.tsx b/webapp/src/components/table/tableRows.tsx index 7bf44a78d..4e3282120 100644 --- a/webapp/src/components/table/tableRows.tsx +++ b/webapp/src/components/table/tableRows.tsx @@ -1,8 +1,8 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {useCallback} from 'react' -import {FixedSizeList, ListChildComponentProps} from 'react-window'; -import AutoSizer from 'react-virtualized-auto-sizer'; +import {FixedSizeList, ListChildComponentProps} from 'react-window' +import AutoSizer from 'react-virtualized-auto-sizer' import {Card} from '../../blocks/card' import {Board} from '../../blocks/board' @@ -23,21 +23,50 @@ type Props = { addCard: (groupByOptionId?: string) => Promise onCardClicked: (e: React.MouseEvent, card: Card) => void onDrop: (srcCard: Card, dstCard: Card) => void + useVirtualizedList: boolean } const TableRows = (props: Props): JSX.Element => { - const {board, cards, activeView} = props + const {board, cards, activeView, useVirtualizedList} = props const onClickRow = useCallback((e: React.MouseEvent, card: Card) => { props.onCardClicked(e, card) }, [props.onCardClicked]) + if (!useVirtualizedList) { + return ( + <> + {cards.map((card, idx) => { + return ( + + ) + })} + + ) + } + const isItemLoaded = (index: number) => { return index < cards.length; - }; + } const Item = ({index, style}: ListChildComponentProps) => { - const card = cards[index] if (isItemLoaded(index)) { return ( @@ -72,13 +101,13 @@ const TableRows = (props: Props): JSX.Element => { } return ( - - {({height, width}) => ( + + {({height}) => ( {Item}